Python 的 Requests 库入门
尽管 Requests 库是许多 Python 开发人员的常用工具,但它并未包含在Python 的标准库中。做出这一决定有充分的理由,主要是该库可以作为一个独立的项目继续更自由地发展。
注意: Requests 不直接支持异步 HTTP 请求。如果你的程序需要异步支持,你应该尝试AIOHTTP或HTTPX。后者库与 Requests 的语法广泛兼容。
由于 Requests 是第三方库,因此您需要先安装它,然后才能在代码中使用它。作为一种良好做法,您应该将外部包安装到虚拟环境中,但<font style="color:rgb(34, 34, 34);">requests</font>
如果您打算在多个项目中使用它,您可以选择安装到全局环境中。
无论您是否在虚拟环境中工作,您都需要安装<font style="color:rgb(34, 34, 34);">requests</font>
:
壳
$ python -m pip install requests
pip安装完成后<font style="color:rgb(34, 34, 34);">requests</font>
,您可以在应用程序中使用它。导入<font style="color:rgb(34, 34, 34);">requests</font>
如下所示:
Python
import requests
现在您已完成所有设置,是时候开始您的请求之旅了。您的第一个目标是学习如何发出请求
<font style="color:rgb(34, 34, 34);">GET</font>
。
GET 请求
HTTP 方法(例如<font style="color:rgb(34, 34, 34);">GET</font>
和<font style="color:rgb(34, 34, 34);">POST</font>
)决定了您在发出 HTTP 请求时尝试执行的操作。除了<font style="color:rgb(34, 34, 34);">GET</font>
和 之外<font style="color:rgb(34, 34, 34);">POST</font>
,您还将在本教程的后面部分使用其他几种常用方法。
最常见的 HTTP 方法之一是<font style="color:rgb(34, 34, 34);">GET</font>
。该<font style="color:rgb(34, 34, 34);">GET</font>
方法表示您正在尝试从指定资源获取或检索数据。要<font style="color:rgb(34, 34, 34);">GET</font>
使用 Requests 发出请求,您可以调用<font style="color:rgb(34, 34, 34);">requests.get()</font>
。
为了测试这一点,您可以通过调用以下 URL<font style="color:rgb(34, 34, 34);">GET</font>
向GitHub 的 REST API发出请求:<font style="color:rgb(34, 34, 34);">get()</font>
Python
>>> import requests
>>> requests.get("https://api.github.com")
<Response [200]>
恭喜!您已发出第一个请求。现在您将更深入地了解该请求的响应。
回应
A` Response` 是一个功能强大的对象,可用于检查请求的结果。再次发出相同的请求,但这次将返回值存储在变量中,[ 以便](https://realpython.com/python-variables/) 您可以仔细查看其属性和行为:Python
>>> import requests
>>> response = requests.get("https://api.github.com")
在此示例中,您捕获了 的返回值<font style="color:rgb(34, 34, 34);">get()</font>
(即 的一个实例)<font style="color:rgb(34, 34, 34);">Response</font>
,并将其存储在名为 的变量中<font style="color:rgb(34, 34, 34);">response</font>
。现在您可以使用<font style="color:rgb(34, 34, 34);">response</font>
来查看有关请求结果的大量信息<font style="color:rgb(34, 34, 34);">GET</font>
。
状态代码
您可以收集的第一点信息` Response` 是状态代码。状态代码会告知您请求的状态。例如,<font style="color:rgb(34, 34, 34);">200 OK</font>
状态表示您的请求成功,而<font style="color:rgb(34, 34, 34);">404 NOT FOUND</font>
状态表示未找到您要查找的资源。还有许多其他可能的状态代码,可以让您具体了解请求发生的情况。
通过访问<font style="color:rgb(34, 34, 34);">.status_code</font>
,你可以看到服务器返回的状态代码:
Python
>>> response.status_code
200
<font style="color:rgb(34, 34, 34);">.status_code</font>
返回<font style="color:rgb(34, 34, 34);">200</font>
,这意味着您的请求成功并且服务器响应了您请求的数据。
有时,你可能希望使用此信息在代码中做出决策:
Python
if response.status_code == 200:
print("Success!")
elif response.status_code == 404:
print("Not Found.")
按照这种逻辑,如果服务器返回<font style="color:rgb(34, 34, 34);">200</font>
状态代码,则程序将打印 <font style="color:rgb(34, 34, 34);">Success!</font>
。如果结果为<font style="color:rgb(34, 34, 34);">404</font>
,则程序将打印<font style="color:rgb(34, 34, 34);">Not Found</font>
。
Requests 更进一步简化了这个过程。如果您<font style="color:rgb(34, 34, 34);">Response</font>
在条件表达式中使用实例,则<font style="color:rgb(34, 34, 34);">True</font>
如果状态代码小于<font style="color:rgb(34, 34, 34);">400</font>
,它将评估为,<font style="color:rgb(34, 34, 34);">False</font>
否则。
因此,您可以通过重写语句来简化最后一个例子<font style="color:rgb(34, 34, 34);">if</font>
:
Python
if response:
print("Success!")
else:
raise Exception(f"Non-success status code: {response.status_code}")
在上面的代码片段中,您隐式检查了 是否<font style="color:rgb(34, 34, 34);">.status_code</font>
在<font style="color:rgb(34, 34, 34);">response</font>
和 之间<font style="color:rgb(34, 34, 34);">200</font>
。<font style="color:rgb(34, 34, 34);">399</font>
如果不是,则引发一个异常,该异常在f 字符串中包含非成功状态代码。
注意:此真值测试是可行的,因为是上的.bool()重载方法<font style="color:rgb(34, 34, 34);background-color:rgb(223, 235, 245);">Response</font>
。这意味着 的适配默认行为<font style="color:rgb(34, 34, 34);background-color:rgb(223, 235, 245);">Response</font>
在确定对象的真值时会考虑状态代码。
请记住,此方法不会验证状态代码是否等于<font style="color:rgb(34, 34, 34);">200</font>
。原因是,在<font style="color:rgb(34, 34, 34);">200</font>
to<font style="color:rgb(34, 34, 34);">399</font>
范围内的其他状态代码(例如<font style="color:rgb(34, 34, 34);">204 NO CONTENT</font>
和<font style="color:rgb(34, 34, 34);">304 NOT MODIFIED</font>
)也被视为成功,因为它们提供了一些可行的响应。
例如,状态代码<font style="color:rgb(34, 34, 34);">204</font>
告诉您响应成功,但消息正文中没有要返回的内容。
因此,请确保仅当您想知道请求是否成功时才使用这种方便的简写。然后,如有必要,您需要根据状态代码适当地处理响应。
假设您不想在语句中检查响应的状态代码<font style="color:rgb(34, 34, 34);">if</font>
。相反,您想使用 Request 的内置功能在请求失败时引发异常。您可以使用以下方式执行此操作<font style="color:rgb(34, 34, 34);">.raise_for_status()</font>
:
Python<font style="background-color:rgb(216, 227, 235);">raise_error.py</font>
import requests
from requests.exceptions import HTTPError
URLS = ["https://api.github.com", "https://api.github.com/invalid"]
for url in URLS:
try:
response = requests.get(url)
response.raise_for_status()
except HTTPError as http_err:
print(f"HTTP error occurred: {http_err}")
except Exception as err:
print(f"Other error occurred: {err}")
else:
print("Success!")
如果您调用.raise_for_status(),则 Requests 将针对和<font style="color:rgb(34, 34, 34);">HTTPError</font>
之间的状态代码引发异常。如果状态代码表示请求成功,则程序将继续执行而不会引发该异常。<font style="color:rgb(34, 34, 34);">400</font>``<font style="color:rgb(34, 34, 34);">600</font>
现在,您已经了解了很多有关如何处理从服务器返回的响应的状态代码的知识。但是,当您发出请求时<font style="color:rgb(34, 34, 34);">GET</font>
,您很少只关心响应的状态代码。通常,您希望看到更多信息。接下来,您将了解如何查看服务器在响应正文中发回的实际数据。
请求的响应<font style="color:rgb(34, 34, 34);">GET</font>
通常在消息正文中包含一些有价值的信息,称为有效负载。使用 的属性和方法<font style="color:rgb(34, 34, 34);">Response</font>
,您可以以多种不同的格式查看有效负载。
要查看响应的内容bytes,可以使用<font style="color:rgb(34, 34, 34);">.content</font>
:
Python
>>> import requests
>>> response = requests.get("https://api.github.com")
>>> response.content
b'{"current_user_url":"https://api.github.com/user", ...}'
>>> type(response.content)
<class 'bytes'>
虽然<font style="color:rgb(34, 34, 34);">.content</font>
允许您访问响应有效负载的原始字节,但您通常希望使用字符编码(例如UTF-8 )将它们转换为字符串。当您访问时将为您执行此操作:<font style="color:rgb(34, 34, 34);">response</font>``<font style="color:rgb(34, 34, 34);">.text</font>
Python
>>> response.text
'{"current_user_url":"https://api.github.com/user", ...}'
>>> type(response.text)
<class 'str'>
由于解码需要编码<font style="color:rgb(34, 34, 34);">bytes</font>
方案,如果您未指定编码方案,Requests 将尝试根据响应的标头<font style="color:rgb(34, 34, 34);">str</font>
猜测编码。您可以在访问之前通过设置来提供显式编码:<font style="color:rgb(34, 34, 34);">.encoding</font>``<font style="color:rgb(34, 34, 34);">.text</font>
Python
>>> response.encoding = "utf-8" # Optional: Requests infers this.
>>> response.text
'{"current_user_url":"https://api.github.com/user", ...}'
如果您查看响应,您会发现它实际上是序列化的 JSON 内容。要获取字典,您可以获取<font style="color:rgb(34, 34, 34);">str</font>
从中检索的字典<font style="color:rgb(34, 34, 34);">.text</font>
并使用 对其进行反序列化json.loads()。但是,完成此任务的更简单方法是使用<font style="color:rgb(34, 34, 34);">.json()</font>
:
Python
>>> response.json()
{'current_user_url': 'https://api.github.com/user', ...}
>>> type(response.json())
<class 'dict'>
返回值<font style="color:rgb(34, 34, 34);">type</font>
的<font style="color:rgb(34, 34, 34);">.json()</font>
是一个字典,因此您可以通过键访问对象中的值:
Python
>>> response_dict = response.json()
>>> response_dict["emojis_url"]
'https://api.github.com/emojis'
您可以使用状态代码和消息正文做很多事情。但是,如果您需要更多信息,例如有关响应本身的元数据,则需要查看响应的标头。
标头
响应标头可以为您提供有用的信息,例如响应负载的内容类型以及缓存响应的时间限制。要查看这些标头,请访问` .headers` :Python
>>> import requests
>>> response = requests.get("https://api.github.com")
>>> response.headers
{'Server': 'GitHub.com',
...
'X-GitHub-Request-Id': 'AE83:3F40:2151C46:438A840:65C38178'}
<font style="color:rgb(34, 34, 34);">.headers</font>
返回一个类似字典的对象,允许您按键访问标头值。例如,要查看响应有效负载的内容类型,您可以访问<font style="color:rgb(34, 34, 34);">"Content-Type"</font>
:
Python
>>> response.headers["Content-Type"]
'application/json; charset=utf-8'
不过,这个类似字典的 headers 对象有一些特殊之处。HTTP 规范将 headers 定义为不区分大小写,这意味着您可以访问这些 headers 而不必担心它们的大小写:
Python
>>> response.headers["content-type"]
'application/json; charset=utf-8'
无论您使用键<font style="color:rgb(34, 34, 34);">"content-type"</font>
还是<font style="color:rgb(34, 34, 34);">"Content-Type"</font>
,您都会获得相同的值。
现在您已经了解了最有用的属性和方法<font style="color:rgb(34, 34, 34);">Response</font>
,并且已经对 Requests 的基本用法有了很好的了解。您可以从互联网获取内容并处理收到的响应。
但互联网不仅仅是简单明了的 URL。在下一节中,您将回顾一下,看看当您自定义<font style="color:rgb(34, 34, 34);">GET</font>
请求以考虑查询字符串参数时,您的响应会如何变化。
查询字符串参数
自定义请求的一种常见方法是通过 URL 中的[ 查询字符串](https://en.wikipedia.org/wiki/Query_string)` GET` 参数传递值。要使用 执行此操作 ,您需要将数据传递给 。例如,您可以使用 GitHub 的[ 存储库搜索](https://docs.github.com/en/rest/search/search#search-repositories) API 来查找流行的 Python 存储库:` get()`` params`Python<font style="background-color:rgb(216, 227, 235);">search_popular_repos.py</font>
import requests
# Search GitHub's repositories for popular Python projects
response = requests.get(
"https://api.github.com/search/repositories",
params={"q": "language:python", "sort": "stars", "order": "desc"},
)
# Inspect some attributes of the first three repositories
json_response = response.json()
popular_repositories = json_response["items"]
for repo in popular_repositories[:3]:
print(f"Name: {repo['name']}")
print(f"Description: {repo['description']}")
print(f"Stars: {repo['stargazers_count']}")
print()
通过将字典传递给<font style="color:rgb(34, 34, 34);">params</font>
的参数<font style="color:rgb(34, 34, 34);">get()</font>
,您可以修改搜索 API 返回的结果。
您可以以字典的形式传递,就像您刚才做的那样,或者以元组列表的形式<font style="color:rgb(34, 34, 34);">params</font>
传递:<font style="color:rgb(34, 34, 34);">get()</font>
Python
>>> import requests
>>> requests.get(
... "https://api.github.com/search/repositories",
... [("q", "language:python"), ("sort", "stars"), ("order", "desc")],
... )
<Response [200]>
您甚至可以将值传递为<font style="color:rgb(34, 34, 34);">bytes</font>
:
Python
>>> requests.get(
... "https://api.github.com/search/repositories",
... params=b"q=language:python&sort=stars&order=desc",
... )
<Response [200]>
查询字符串对于参数化请求非常有用<font style="color:rgb(34, 34, 34);">GET</font>
。自定义请求的另一种方法是添加或修改您发送的标头。
请求标头
` get()` 要自定义标头,您可以使用参数 传递 HTTP 标头字典` headers` 。例如,您可以通过` text-match` 在` Accept` 标头中指定媒体类型来更改之前的搜索请求,以在结果中突出显示匹配的搜索词:Python<font style="background-color:rgb(216, 227, 235);">text_matches.py</font>
import requests
response = requests.get(
"https://api.github.com/search/repositories",
params={"q": '"real python"'},
headers={"Accept": "application/vnd.github.text-match+json"},
)
# View the new `text-matches` list which provides information
# about your search term within the results
json_response = response.json()
first_repository = json_response["items"][0]
print(first_repository["text_matches"][0]["matches"])
标<font style="color:rgb(34, 34, 34);">Accept</font>
头会告诉服务器您的应用程序可以处理哪些内容类型。在本例中,由于您希望突出显示匹配的搜索词,因此您使用标头值<font style="color:rgb(34, 34, 34);">application/vnd.github.text-match+json</font>
,这是一个专有的 GitHub<font style="color:rgb(34, 34, 34);">Accept</font>
标头,其中的内容是特殊的 JSON 格式。
如果您运行此代码,那么您将获得类似于下面所示的结果:
壳
$ python text_matches.py
[{'text': 'Real Python', 'indices': [23, 34]}]
在了解更多自定义请求的方法之前,您可以通过探索其他 HTTP 方法来拓宽您的视野。
其他 HTTP 方法
除 之外` GET` ,其他流行的 HTTP 方法包括` POST` 、` PUT` 、` DELETE` 、` HEAD` 、` PATCH` 和` OPTIONS` 。对于其中每一种 HTTP 方法,Requests 都提供了一个函数,其签名与 类似` get()` 。注意:要尝试这些 HTTP 方法,您需要向httpbin.org发出请求。httpbin 服务是 Requests 的原作者Kenneth Reitz创建的一项重要资源。该服务接受测试请求并使用有关请求的数据进行响应。
您会注意到,Requests为所有提到的HTTP方法提供了一个直观的界面:
Python
>>> import requests
>>> requests.get("https://httpbin.org/get")
<Response [200]>
>>> requests.post("https://httpbin.org/post", data={"key": "value"})
<Response [200]>
>>> requests.put("https://httpbin.org/put", data={"key": "value"})
<Response [200]>
>>> requests.delete("https://httpbin.org/delete")
<Response [200]>
>>> requests.head("https://httpbin.org/get")
<Response [200]>
>>> requests.patch("https://httpbin.org/patch", data={"key": "value"})
<Response [200]>
>>> requests.options("https://httpbin.org/get")
<Response [200]>
在上面的示例代码中,您调用每个函数使用相应的 HTTP 方法向 httpbin 服务发出请求。
注意:所有这些函数都是的高级快捷方式requests.request(),传递相关 HTTP 方法的名称:
Python
>>> requests.request("GET", "https://httpbin.org/get")
<Response [200]>
您可以使用等效的低级函数调用,但 Python 的 Requests 库的强大之处在于其人性化的高级界面。
您可以按照与之前相同的方式检查响应:
Python
>>> 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"]
{}
<font style="color:rgb(34, 34, 34);">Response</font>
每个方法都会返回标头、响应主体、状态代码等。
接下来,您将仔细研究<font style="color:rgb(34, 34, 34);">POST</font>
、<font style="color:rgb(34, 34, 34);">PUT</font>
和<font style="color:rgb(34, 34, 34);">PATCH</font>
方法,并了解它们与其他请求类型的不同之处。
邮件正文
根据 HTTP 规范,、` POST` 和` PUT` 不太常见的` PATCH` 请求通过消息正文传递数据,而不是通过查询字符串中的参数传递数据。使用请求,您将有效负载传递给相应函数的` data` 参数。<font style="color:rgb(34, 34, 34);">data</font>
接受字典、元组列表、字节或类似文件的对象。您需要调整请求正文中发送的数据,以满足您与之交互的服务的特定需求。
例如,如果您的请求的内容类型是<font style="color:rgb(34, 34, 34);">application/x-www-form-urlencoded</font>
,那么您可以将表单数据作为字典发送:
Python
>>> import requests
>>> requests.post("https://httpbin.org/post", data={"key": "value"})
<Response [200]>
您还可以将相同的数据作为元组列表发送:
Python
>>> requests.post("https://httpbin.org/post", data=[("key", "value")])
<Response [200]>
但是,如果您需要发送 JSON 数据,则可以使用参数<font style="color:rgb(34, 34, 34);">json</font>
。当您通过传递 JSON 数据时,Requests 将序列化您的数据并为您<font style="color:rgb(34, 34, 34);">json</font>
添加正确的标头。<font style="color:rgb(34, 34, 34);">Content-Type</font>
就像你之前学到的,httpbin 服务接受测试请求并响应有关请求的数据。例如,你可以使用它来检查基本<font style="color:rgb(34, 34, 34);">POST</font>
请求:
Python
>>> response = requests.post("https://httpbin.org/post", json={"key": "value"})
>>> json_response = response.json()
>>> json_response["data"]
'{"key": "value"}'
>>> json_response["headers"]["Content-Type"]
'application/json'
您可以从响应中看到,服务器已收到您发送的请求数据和标头。Requests 还会以 的形式向您提供此信息,<font style="color:rgb(34, 34, 34);">PreparedRequest</font>
您将在下一节中更详细地查看该信息。
要求检查
当您发出请求时,Requests 库会在实际将请求发送到目标服务器之前对其进行准备。请求准备包括验证标头和序列化 JSON 内容等。您可以<font style="color:rgb(34, 34, 34);">PreparedRequest</font>
通过访问对象<font style="color:rgb(34, 34, 34);">.request</font>
来查看对象<font style="color:rgb(34, 34, 34);">Response</font>
:
Python
>>> import requests
>>> response = requests.post("https://httpbin.org/post", json={"key":"value"})
>>> response.request.headers["Content-Type"]
'application/json'
>>> response.request.url
'https://httpbin.org/post'
>>> response.request.body
b'{"key": "value"}'
通过检查,<font style="color:rgb(34, 34, 34);">PreparedRequest</font>
您可以访问有关所发出请求的各种信息,例如有效负载、URL、标头、身份验证等。
到目前为止,您已经发出了很多不同类型的请求,但它们都有一个共同点:它们都是对公共 API 的未经身份验证的请求。您可能会遇到的许多服务都希望您以某种方式进行身份验证。
验证
身份验证可帮助服务了解您的身份。通常,您可以通过标` Authorization` 头或服务定义的自定义标头传递数据,向服务器提供您的凭据。到目前为止,您看到的所有 Requests 函数都提供了一个名为 的参数` auth` ,它允许您传递您的凭据:Python
>>> import requests
>>> response = requests.get(
... "https://httpbin.org/basic-auth/user/passwd",
... auth=("user", "passwd")
... )
>>> response.status_code
200
>>> response.request.headers["Authorization"]
'Basic dXNlcjpwYXNzd2Q='
<font style="color:rgb(34, 34, 34);">auth</font>
如果您在元组中传递的凭据有效,则请求成功。
当您将凭据以元组的形式传递给参数时,Requests 会在后台使用 HTTP 的基本访问身份验证方案<font style="color:rgb(34, 34, 34);">auth</font>
应用凭据。
基本身份验证方案显示/隐藏
您可以通过使用以下方式传递显式的基本身份验证凭据来发出相同的请求<font style="color:rgb(34, 34, 34);">HTTPBasicAuth</font>
:
Python
>>> from requests.auth import HTTPBasicAuth
>>> requests.get(
... "https://httpbin.org/basic-auth/user/passwd",
... auth=HTTPBasicAuth("user", "passwd")
... )
<Response [200]>
尽管您不需要明确进行基本身份验证,但您可能希望使用其他方法进行身份验证。Requests 提供了其他现成的身份验证方法<font style="color:rgb(34, 34, 34);">HTTPDigestAuth</font>
,例如和<font style="color:rgb(34, 34, 34);">HTTPProxyAuth</font>
。
需要身份验证的 API 的一个真实示例是 GitHub 的经过身份验证的用户API。此端点提供有关经过身份验证的用户个人资料的信息。
如果您尝试发出没有凭证的请求,那么您会看到状态代码是<font style="color:rgb(34, 34, 34);">401 Unauthorized</font>
:
Python
>>> requests.get("https://api.github.com/user")
<Response [401]>
如果您在访问需要身份验证凭据的服务时不提供它们,那么您将收到 HTTP 错误代码作为响应。
要向 GitHub 的已验证用户 API 发出请求,首先需要生成具有read:user范围的个人访问令牌。然后,您可以将此令牌作为元组中的第二个元素传递给:<font style="color:rgb(34, 34, 34);">get()</font>
Python
>>> import requests
>>> token = "<YOUR_GITHUB_PA_TOKEN>"
>>> response = requests.get(
... "https://api.github.com/user",
... auth=("", token)
... )
>>> response.status_code
200
正如您之前所了解的,这种方法将凭证传递给<font style="color:rgb(34, 34, 34);">HTTPBasicAuth</font>
,它需要用户名和密码,并将凭证作为带有前缀的 Base64 编码字符串发送<font style="color:rgb(34, 34, 34);">"Basic "</font>
:
Python
>>> response.request.headers["Authorization"]
'Basic OmdocF92dkd...WpremM0SGRuUGY='
这是可行的,但这不是使用 Bearer 令牌进行身份验证的正确方法- 并且使用空字符串输入多余的用户名很尴尬。
使用 Requests,您可以提供自己的身份验证机制来解决此问题。要尝试此操作,请创建一个子类<font style="color:rgb(34, 34, 34);">AuthBase</font>
并实现<font style="color:rgb(34, 34, 34);">.__call__()</font>
:
Python<font style="background-color:rgb(216, 227, 235);">custom_token_auth.py</font>
from requests.auth import AuthBase
class TokenAuth(AuthBase):
"""Implements a token authentication scheme."""
def __init__(self, token):
self.token = token
def __call__(self, request):
"""Attach an API token to the Authorization header."""
request.headers["Authorization"] = f"Bearer {self.token}"
return request
在这里,您的自定义<font style="color:rgb(34, 34, 34);">TokenAuth</font>
机制接收一个令牌,然后将该令牌包含在<font style="color:rgb(34, 34, 34);">Authorization</font>
您的请求的标头中,同时将推荐的<font style="color:rgb(34, 34, 34);">"Bearer "</font>
前缀设置为字符串。
您现在可以使用此自定义令牌身份验证来调用 GitHub 的经过身份验证的用户 API:
Python
>>> import requests
>>> from custom_token_auth import TokenAuth
>>> token = "<YOUR_GITHUB_PA_TOKEN>"
>>> response = requests.get(
... "https://api.github.com/user",
... auth=TokenAuth(token)
... )
>>> response.status_code
200
>>> response.request.headers["Authorization"]
'Bearer ghp_b...Tx'
您的自定义<font style="color:rgb(34, 34, 34);">TokenAuth</font>
为标头创建了一个格式良好的字符串<font style="color:rgb(34, 34, 34);">Authorization</font>
。现在,您可以使用这种更直观的方式与基于令牌的身份验证方案(例如 GitHub 的 API 部分所需的方案)进行交互。
注意:虽然您可以在自定义身份验证类之外构建身份验证字符串并直接将其传递,但不建议<font style="color:rgb(34, 34, 34);background-color:rgb(223, 235, 245);">headers</font>
使用这种方法,因为它可能导致意外行为。
当您尝试使用 直接设置身份验证凭据时<font style="color:rgb(34, 34, 34);background-color:rgb(223, 235, 245);">headers</font>
,Requests 可能会在内部覆盖您的输入。例如,如果您有一个提供身份验证凭据的.netrc文件,就会发生这种情况。如果您没有使用 提供身份验证方法,Requests 将尝试从该文件中获取凭据.netrc<font style="color:rgb(34, 34, 34);background-color:rgb(223, 235, 245);">auth=</font>
。
不良的身份验证机制会导致安全漏洞。除非服务出于某种原因需要自定义身份验证机制,否则您始终希望使用久经考验的身份验证方案,例如内置的基本身份验证或OAuth,例如通过Requests-OAuthlib。
在考虑安全性时,请考虑使用请求处理 SSL 证书。
SSL 证书验证
无论您尝试发送或接收的数据是敏感数据,安全性都很重要。通过 HTTP 与安全站点通信的方式是使用 SSL 建立加密连接,这意味着验证目标服务器的 SSL 证书至关重要。好消息是,Requests 默认会为您执行此操作。但是,在某些情况下,您可能想要更改此行为。
如果要禁用SSL证书验证,则传递<font style="color:rgb(34, 34, 34);">False</font>
给<font style="color:rgb(34, 34, 34);">verify</font>
请求函数的参数:
Python
>>> import requests
>>> requests.get("https://api.github.com", verify=False)
InsecureRequestWarning: Unverified HTTPS request is being made to host
⮑ 'api.github.com'. Adding certificate verification is strongly advised.
⮑ See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
⮑ warnings.warn(
<Response [200]>
当您发出不安全的请求时,Requests 甚至会向您发出警告,以帮助您保证数据安全!
注意: Requests 使用一个名为 的包certifi来提供证书颁发机构。这让 Requests 知道它可以信任哪些颁发机构。因此,您应该<font style="color:rgb(34, 34, 34);background-color:rgb(223, 235, 245);">certifi</font>
经常更新以尽可能保证您的连接安全。
现在您知道了如何使用 Requests 发出各种 HTTP 请求(无论是否经过身份验证),您可能想知道如何确保您的程序尽快运行。
在下一部分中,您将了解一些借助请求来提高性能的方法。
表现
使用请求时,尤其是在生产应用程序环境中,考虑性能影响非常重要。超时控制、会话和重试限制等功能可以帮助您保持应用程序平稳运行。超时
当您向外部服务发出内联请求时,您的系统需要等待响应才能继续。如果您的应用程序等待响应的时间过长,则对您服务的请求可能会积压,您的用户体验可能会受到影响,或者您的后台作业可能会挂起。默认情况下,请求将无限期地等待响应,因此您几乎应该始终指定超时持续时间以防止发生这些问题。要设置请求的超时,请使用参数<font style="color:rgb(34, 34, 34);">timeout</font>
。<font style="color:rgb(34, 34, 34);">timeout</font>
可以是整数或浮点数,表示在超时之前等待响应的秒数:
Python
>>> requests.get("https://api.github.com", timeout=1)
<Response [200]>
>>> requests.get("https://api.github.com", timeout=3.05)
<Response [200]>
第一次请求,1秒后请求超时;第二次请求,3.05秒后请求超时。
您还可以传递包含<font style="color:rgb(34, 34, 34);">timeout</font>
以下两个元素的元组:
- 连接超时:允许客户端与服务器建立连接的时间
- 读取超时:客户端建立连接后等待响应的时间
<font style="color:rgb(34, 34, 34);">int</font>
这两个元素都应该是数字,并且可以是以下类型<font style="color:rgb(34, 34, 34);">float</font>
:
Python
>>> requests.get("https://api.github.com", timeout=(3.05, 5))
<Response [200]>
如果请求在 3.05 秒内建立连接,并在建立连接后 5 秒内收到数据,则响应将像以前一样返回。如果请求超时,则该函数将引发异常<font style="color:rgb(34, 34, 34);">Timeout</font>
:
Python<font style="background-color:rgb(216, 227, 235);">timeout_catcher.py</font>
import requests
from requests.exceptions import Timeout
try:
response = requests.get("https://api.github.com", timeout=(3.05, 5))
except Timeout:
print("The request timed out")
else:
print("The request did not time out")
您的程序可以捕获Timeout异常并做出相应的响应。
会话对象
` requests` 到目前为止,您一直在处理诸如` get()` 和 之类的 高级API ` post()` 。这些函数是您发出请求时所发生情况的抽象。它们隐藏了实现细节,例如如何管理连接,这样您就不必担心它们。这些抽象之下是一个名为的类<font style="color:rgb(34, 34, 34);">Session</font>
。如果您需要微调对请求方式的控制或提高请求的性能,则可能需要<font style="color:rgb(34, 34, 34);">Session</font>
直接使用实例。
会话用于在请求之间持久保存参数。例如,如果您想在多个请求中使用相同的身份验证,则可以使用会话:
Python<font style="background-color:rgb(216, 227, 235);">persist_info_with_session.py</font>
1import requests
2from custom_token_auth import TokenAuth
3
4TOKEN = "<YOUR_GITHUB_PA_TOKEN>"
5
6with requests.Session() as session:
7 session.auth = TokenAuth(TOKEN)
8
9 first_response = session.get("https://api.github.com/user")
10 second_response = session.get("https://api.github.com/user")
11
12print(first_response.headers)
13print(second_response.json())
在此代码示例中,您使用上下文管理器来确保会话在不再需要资源时释放这些资源。
在第 7 行中,您使用自定义的 登录<font style="color:rgb(34, 34, 34);">TokenAuth</font>
。每个会话只需登录一次,然后您可以发出多个经过身份验证的请求。在会话存在期间,请求将保留凭据。
<font style="color:rgb(34, 34, 34);">session.get()</font>
然后在第 9 行和第 10 行使用而不是 向经过身份验证的用户 API 发出两个请求<font style="color:rgb(34, 34, 34);">get()</font>
。
会话的主要性能优化体现在持久连接上。当您的应用使用 连接到服务器时<font style="color:rgb(34, 34, 34);">Session</font>
,它会将该连接保留在连接池中。当您的应用想要再次连接到同一台服务器时,它将重用池中的连接,而不是建立新连接。