Requests Library 库使用指南
本文翻译于Real Python,翻译以便于查阅。若有不同之处,夹杂作者主观喜好。
开始
1
2
3
4
5
6
7
8
9
10
11
12
response = request . get ( 'url' )
# 可以向下面这样做
if response . status_code == 200 :
print ( 'Success!' )
elif response . status_code == 404 :
print ( 'Not Found.' )
# 还可以这样!
if response :
print ( '成功' )
else :
print ( '失败' )
get()方法返回的是一个Response 对象的一个实例。(在本例中被存储到response 这个变量里)
**提示:**为什么可以这样做?
是因为__bool__() 是Response对象的一个重载方法
注意:if response 语句,状态码200-400 这个表达式的值均为True
如果你不想在if语句里面检查响应的状态码。
相反,你想在请求不成功的时候引发一个异常。
可以这样做
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
from requests.exceptions import HTTPError
for url in [ 'https://api.github.com' , 'https://api.github.com/invalid' ]:
try :
response = requests . get ( url )
# If the response was successful, no Exception will be raised
response . raise_for_status ()
except HTTPError as http_err :
print ( f 'HTTP error occurred: { http_err } ' ) # Python 3.6
except Exception as err :
print ( f 'Other error occurred: { err } ' ) # Python 3.6
else :
print ( 'Success!' )
如果状态码是成功类状态码,程序继续执行,不引发异常。否则将引发异常。
Response
查看响应的字节 内容,可以使用 .content
1
2
response = requests . get ( 'https://api.github.com' )
response . content
可以编码→转换为字符串。当你使用.text是默认转为utf-8(requests 会从请求头猜测编码,一般是utf-8)
也可以显式编码。
1
2
response . encoding = 'utf-8'
response . text
如果你查看响应,它实际上是序列化的json内容。
为了得到Python的数据结构(字典)
要进行反序列化
header 返回一个类似字典的对象,允许通过键访问header值。
1
response . header [ 'Content-Type' ]
header对象有一些特殊之处,HTTP规范将报头定义为不区分大小写。
所以这样写也可以
1
response . header [ 'content-type' ]
Query String Parameters
自定义请求,常用查询字符串参数传递值。(params)
例如
1
2
3
4
5
6
7
import requests
# 搜索github仓库
response = requests . get ( 'https://api.github.com/search/repositories' , params = { 'q' : 'requests+language:python' },)
json_response = response . json ()
repository = json_response [ 'items' ][ 0 ]
print ( f 'Repository name: { repository [ "name" ] } ' )
print ( f 'Repository description: { repository [ "description" ] } ' )
你可以以字典的形式把params 传递给get(),也可以以元祖的形式传递。
1
requests . get ( 'https://api.github.com//search/repositories' , params = [( 'q' , 'requests+language:python' ]),)
甚至可以 以字节的形式传递这些值
1
2
3
4
>>> requests . get (
... 'https://api.github.com/search/repositories' ,
... params = b 'q=requests+language:python' ,
... )
自定义header,需要使用headers 参数传递一个HTTP header 字典 以获得()
例如
1
2
3
4
5
6
7
8
9
import requests
response = requests . get (
'https://api.github.com/search/repositories' ,
params = { 'q' : 'requests+language:python' },
headers = { 'Accept' : 'application/vnd.github.v3.text-match+json' }, # 指定了文本匹配类型 text-match+json
)
json_response = response . json ()
repository = json_response [ 'items' ][ 0 ]
print ( f 'Text matches: { repository [ "text_matches" ] } ' )
text-match+json 这是一种专有的github Accept 头文件,内容是一种特殊的json格式
Other HTTP Methods
1
2
3
4
5
6
>>> requests . post ( 'https://httpbin.org/post' , data = { 'key' : 'value' })
>>> requests . put ( 'https://httpbin.org/put' , data = { 'key' : 'value' })
>>> requests . delete ( 'https://httpbin.org/delete' )
>>> requests . head ( 'https://httpbin.org/get' )
>>> requests . patch ( 'https://httpbin.org/patch' , data = { 'key' : 'value' })
>>> requests . options ( 'https://httpbin.org/get' )
每个函数调用都使用相应的HTTP方法对httpbin服务发出请求。
1
2
3
4
5
6
7
8
>>> response = requests . head ( 'https://httpbin.org/get' )
>>> response . headers [ 'Content-Type' ]
'application/json'
>>> response = requests . delete ( 'https://httpbin.org/delete' )
>>> json_response = response . json ()
>>> json_response [ 'args' ]
{}
The message Body
POST、PUT、和不太常见的PATCH请求通过**消息体(data)**传递数据,而不是通过查询字符串的参数。
data 接受字典、元组列表、字节或者 file-like object。你需要调整正在请求主体中发送的数据,以适应与之交的服务的特定需求。
例如:
1
requests . post ( 'https://httpbin.org/post' , data = { 'key' : 'value' })
也可以用元组
1
requests . post ( 'https:://httpbin.org/post' , data = ( 'key' , 'value' )
但是,如果需要 发送JSON数据,可以使用JSON参数。
requests 将序列化你的数据并为你添加正确的Content-Type
httpbin.org 是个很好的资源,由request作者 创建。
1
2
3
4
5
response = requests . post ( 'https://httpbin.org/post' , json = { 'key' : 'value' })
json_response = response . json ()
json_response [ 'data' ]
json_response [ 'headers' ][ 'Content-Type' ]
requests 以PrepareRequest 的形式向你提供此信息
Inspecting Your Request
在你发送请求之前,请求准备包括 validating headers and serializing JSON content
你可以通过**.request**来访问PrepareRequest
1
2
3
4
5
6
response = requests . post ( 'https://httpbin.org/post' , json = { 'key' : 'value' })
response . request . headers [ 'Content-Type' ]
response . request . url
response . request . body
Authentication
截止到目前为止,上面这些所有的请求 都是对公共api的未经身份验证的请求。
接下来谈论一下需要验证身份的请求
所有的请求函数都提供了一个名为auth的参数。它允许你传递凭证 → 元组列表
例如 github的 Authenticated User API 。
要想它发送请求,该怎么做呢? 如下所示:
1
2
from getpass import getpass
requests . get ( 'https://api.gihu.com/user' , auth = ( 'username' , getpass ()))
当你的用户名和密码在一个元组中传递给auth参数时,请求将在内部使用HTTP的 **Basic acces authentication schme**
因此你可以这样做
1
2
3
4
5
6
from requests.auth import HTTPBasicAuth
from getpass import getpass
requests . get (
'https://api.github.com/user' ,
auth = HTTPBasicAuth ( 'username' , getpass ())
)
requests 还提供了其他身份验证方法
HTTPDigestAuth
HTTPProxyAuth
你甚至可以提供自己的身份验证机制。为此必须首先创建AuthBass的子类,然后实现__call__
1
2
3
4
5
6
7
8
9
10
11
12
import requests
from requests.auth import AuthBase
class TokenAuth ( AuthBase ):
""" 实现一个自定义的身份验证机制 """
def __init__ ( self , token ):
self . token = token
def __call__ ( self , r ):
"""将一个API token 添加到一个自定义的header 中"""
r . header [ 'X-TokenAuth' ] = f ' { self . token } '
return r
requests . get ( 'https://httpbin.org/get' , auth = TokenAuth ( '12345abcde-token' ))
上面的代码中,你自定义的TokenAuth 接受一个token,然后j将该token包含你的请求的X-TokenAuth header中
Suggestion:为了安全考虑,建议使用Basic OAuth 这些经过验证的身份验证机制
SSL Certufucate Verfucatuib
证书验证
在requests 中默认会为你执行此操作(通过SSL建立加密链接)
如果你想禁用 — 只需将verify赋值为False
1
requests . get ( 'https://api.github.com' , verify = False )
💡 requests 使用一个叫做 [certifi](http://docs.python-requests.org/en/master/user/advanced/#ca-certificates) 的包提供证书验证服务。因此你应该经常更新certifi
Timeouts(暂停)
在请求中添加timeout 字段
1
2
3
requests . get ( 'https://api.github.com' , timeout = 1 )
requests . get ( 'https://api.github.com' , timeout = 3.05 )
你也可以给timeout 属性添加一个元组
你也可以传一个元组到超时,第一个元素是连接超时 (允许客户端建立到服务器的连接的时间) ,第二个元素是读超时 (客户端建立连接后等待响应的时间) :
1
requests . get ( 'https://api.github.com' , timeout = ( 2 , 5 ))
5s之后请求超时,引发一个Timeout 异常
1
2
3
4
5
6
7
8
9
import requests
from requests.exceptions import Timeout
try :
response = requests . get ( 'https://api.github.com' , timeout = 1 )
except Timeout :
print ( 'The request timed out' )
else :
print ( 'The request did not time out' )
The Session Object
例如get(),post()这些高级别请求的api 是怎么实现的呢?
依靠于 Session 这个类,当你需要微调对发出请求的方式的控制(在高级别的抽象之下的操作)
这时你就需要Session类了
Session 用于请求持久化参数。
例如 多个请求使用相同的身份验证
1
2
3
4
5
6
7
8
9
10
11
12
13
import requests
from getpass import getpass
# 通过使用一个上下文管理器你可以确保
# Session 所使用的资源将在使用后被释放
with requests . Session () as session :
session . auth = ( 'username' , getpass ())
# Instead of requests.get(), you'll use session.get()
response = session . get ( 'https://api.github.com/user' )
# 你也可以像之前那样检查response
print ( response . headers )
print ( response . json ())
每次使用会话发出请求时,一旦使用身份验证凭据初始化了该凭据,该凭据将被持久化。
会话的主要性能优化以持久连接的形式出现。当您的应用程序使用 Session 连接到服务器时,它将这个连接保存在连接池中。当您的应用程序想要再次连接到同一台服务器时,它将重复使用池中的连接,而不是建立一个新的连接。
Max Retries 最大重试次数
你需要一个自定义的 Transport Adapter 来实现这个功能
Transport Adapter 允许您为与之交互的每个服务定义一组配置。例如,假设您希望所有的请求在最终引发一个 ConnectionError 之前重试3次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
from requests.adapters import HTTPAdapter
from requests.exceptions import ConnectionError
github_adapter = HTTPAdapter ( max_retries = 3 )
session = requests . Session ()
# 将 github_adapter 挂载到 session
# Use `github_adapter` for all requests to endpoints that start with this URL
session . mount ( 'https://api.github.com' , github_adapter )
try :
session . get ( 'https://api.github.com' )
except ConnectionError as ce :
print ( ce )
当你把 HTTPAdapter、github_adapter 挂载到session。
session 会将每个配置到https://api.github.com
💡 Timeout、 TransportAdapter 、session 是为了保持代码的效率和程序的弹性
ConClusion
使用各种不同的 HTTP 方法进行请求,例如GET
, PUT
,Put
通过修改标头、身份验证、查询字符串和消息正文来自定义请求
检查发送到服务器的数据和服务器发送回来的数据
使用 SSL 证书验证
有效的利用 max_retires、seesion、transport adapter