用户指南#
安装#
可以安装ULLIb3 pip
$ python -m pip install urllib3
提出请求#
首先,导入urllib3模块:
import urllib3
你需要一个 PoolManager
实例发出请求。此对象处理连接池和线程安全的所有详细信息,因此您不必:
http = urllib3.PoolManager()
要发出请求,请使用 request()
:
import urllib3
# Creating a PoolManager instance for sending requests.
http = urllib3.PoolManager()
# Sending a GET request and getting back response as HTTPResponse object.
resp = http.request("GET", "https://httpbin.org/robots.txt")
# Print the returned data.
print(resp.data)
# b"User-agent: *\nDisallow: /deny\n"
request()
返回A HTTPResponse
对象 响应内容 部分说明如何处理各种响应。
您可以使用 request()
要使用任何HTTP谓词发出请求,请执行以下操作:
import urllib3
http = urllib3.PoolManager()
resp = http.request(
"POST",
"https://httpbin.org/post",
fields={"hello": "world"} # Add custom form fields
)
print(resp.data)
# b"{\n "form": {\n "hello": "world"\n }, ... }
这个 请求数据 本节介绍发送其他类型的请求数据,包括json、文件和二进制数据。
备注
对于快速脚本和实验,您还可以使用顶级 urllib3.request()
。它使用一个模块-全局 PoolManager
举个例子。正因为如此,它的副作用可以在依赖它的依赖项之间共享。若要避免副作用,请创建新的 PoolManager
实例,并改用它。此外,该方法不接受低级别的 **urlopen_kw
关键字参数。默认情况下加载系统CA证书。
响应内容#
这个 HTTPResponse
对象提供 status
, data
和 headers
属性:
import urllib3
# Making the request (The request function returns HTTPResponse object)
resp = urllib3.request("GET", "https://httpbin.org/ip")
print(resp.status)
# 200
print(resp.data)
# b"{\n "origin": "104.232.115.37"\n}\n"
print(resp.headers)
# HTTPHeaderDict({"Content-Length": "32", ...})
JSON内容#
JSON内容可以通过 json()
回复方式:
import urllib3
resp = urllib3.request("GET", "https://httpbin.org/ip")
print(resp.json())
# {"origin": "127.0.0.1"}
或者,自定义JSON库,如 orjson 可用于编码数据、通过解码和反序列化 data
请求的属性:
import orjson
import urllib3
encoded_data = orjson.dumps({"attribute": "value"})
resp = urllib3.request(method="POST", url="http://httpbin.org/post", body=encoded_data)
print(orjson.loads(resp.data)["json"])
# {'attribute': 'value'}
二进制内容#
这个 data
响应的属性始终设置为表示响应内容的字节字符串:
import urllib3
resp = urllib3.request("GET", "https://httpbin.org/bytes/8")
print(resp.data)
# b"\xaa\xa5H?\x95\xe9\x9b\x11"
备注
对于更大的响应,有时最好是 stream 反应。
对响应内容使用io包装器#
有时候你想用 io.TextIOWrapper
或类似的对象,如直接使用 HTTPResponse
数据。要使这两个接口很好地结合在一起,需要使用 auto_close
通过将其设置为 False
. 默认情况下,读取所有字节后关闭HTTP响应,这将禁用该行为:
import io
import urllib3
resp = urllib3.request("GET", "https://example.com", preload_content=False)
resp.auto_close = False
for line in io.TextIOWrapper(resp):
print(line)
# <!doctype html>
# <html>
# <head>
# ....
# </body>
# </html>
请求数据#
报头#
中将标头指定为词典。 headers
中的论点 request()
:
import urllib3
resp = urllib3.request(
"GET",
"https://httpbin.org/headers",
headers={
"X-Something": "value"
}
)
print(resp.json()["headers"])
# {"X-Something": "value", ...}
或者,您可以使用 HTTPHeaderDict
类以创建多值HTTP头:
import urllib3
# Create an HTTPHeaderDict and add headers
headers = urllib3.HTTPHeaderDict()
headers.add("Accept", "application/json")
headers.add("Accept", "text/plain")
# Make the request using the headers
resp = urllib3.request(
"GET",
"https://httpbin.org/headers",
headers=headers
)
print(resp.json()["headers"])
# {"Accept": "application/json, text/plain", ...}
查询参数#
为 GET
, HEAD
,以及 DELETE
请求时,只需将参数作为字典传递到 fields
参数为 request()
:
import urllib3
resp = urllib3.request(
"GET",
"https://httpbin.org/get",
fields={"arg": "value"}
)
print(resp.json()["args"])
# {"arg": "value"}
为了 POST
和 PUT
请求时,需要在URL中手动编码查询参数:
from urllib.parse import urlencode
import urllib3
# Encode the args into url grammar.
encoded_args = urlencode({"arg": "value"})
# Create a URL with args encoded.
url = "https://httpbin.org/post?" + encoded_args
resp = urllib3.request("POST", url)
print(resp.json()["args"])
# {"arg": "value"}
表单数据#
为 PUT
和 POST
请求时,urllib3将自动对 fields
参数提供给 request()
:
import urllib3
resp = urllib3.request(
"POST",
"https://httpbin.org/post",
fields={"field": "value"}
)
print(resp.json()["form"])
# {"field": "value"}
JSON#
要在请求正文中发送JSON,请在 json
参数为 request()
Urllib3将使用 json
模块,带 UTF-8
编码。此外,当 json
是提供的,则 "Content-Type"
在标头中设置为 "application/json"
未另有说明的。
import urllib3
resp = urllib3.request(
"POST",
"https://httpbin.org/post",
json={"attribute": "value"},
headers={"Content-Type": "application/json"}
)
print(resp.json())
# {'headers': {'Content-Type': 'application/json', ...},
# 'data': '{"attribute":"value"}', 'json': {'attribute': 'value'}, ...}
文件和二进制数据#
用于使用 multipart/form-data
编码可以使用相同的方法 表单数据 并将文件字段指定为 (file_name, file_data)
:
import urllib3
# Reading the text file from local storage.
with open("example.txt") as fp:
file_data = fp.read()
# Sending the request.
resp = urllib3.request(
"POST",
"https://httpbin.org/post",
fields={
"filefield": ("example.txt", file_data),
}
)
print(resp.json()["files"])
# {"filefield": "..."}
虽然不严格要求指定文件名,但建议您使用该文件名以匹配浏览器行为。您也可以传递元组中的第三个项来显式指定文件的MIME类型:
resp = urllib3.request(
"POST",
"https://httpbin.org/post",
fields={
"filefield": ("example.txt", file_data, "text/plain"),
}
)
对于发送原始二进制数据,只需指定 body
争论。也建议设置 Content-Type
标题:
import urllib3
with open("/home/samad/example.jpg", "rb") as fp:
binary_data = fp.read()
resp = urllib3.request(
"POST",
"https://httpbin.org/post",
body=binary_data,
headers={"Content-Type": "image/jpeg"}
)
print(resp.json()["data"])
# data:application/octet-stream;base64,...
证书验证#
备注
版本1.25中的新增功能:
现在默认情况下会验证HTTPS连接 (cert_reqs = "CERT_REQUIRED"
)。
而您可以通过设置禁用证书验证 cert_reqs = "CERT_NONE"
,强烈建议您将其保持打开状态。
除非另有规定,否则urllib3将尝试加载默认的系统证书存储。最可靠的跨平台方法是使用 certifi 提供Mozilla根证书捆绑包的包:
$ python -m pip install certifi
一旦有证书,就可以创建一个 PoolManager
在发出请求时验证证书:
import certifi
import urllib3
http = urllib3.PoolManager(
cert_reqs="CERT_REQUIRED",
ca_certs=certifi.where()
)
这个 PoolManager
将自动处理证书验证并引发 SSLError
如果验证失败:
import certifi
import urllib3
http = urllib3.PoolManager(
cert_reqs="CERT_REQUIRED",
ca_certs=certifi.where()
)
http.request("GET", "https://httpbin.org/")
# (No exception)
http.request("GET", "https://expired.badssl.com")
# urllib3.exceptions.SSLError ...
备注
如果需要,可以使用OS提供的证书。只需将证书捆绑包的完整路径指定为 ca_certs
参数而不是 certifi.where()
. 例如,大多数linux系统将证书存储在 /etc/ssl/certs/ca-certificates.crt
. 其他操作系统可以 difficult .
使用超时#
超时允许您控制在中止请求之前允许运行多长时间(以秒为单位)。在简单的情况下,您可以将超时指定为 float
至 request()
:
import urllib3
resp = urllib3.request(
"GET",
"https://httpbin.org/delay/3",
timeout=4.0
)
print(type(resp))
# <class "urllib3.response.HTTPResponse">
# This request will take more time to process than timeout.
urllib3.request(
"GET",
"https://httpbin.org/delay/3",
timeout=2.5
)
# MaxRetryError caused by ReadTimeoutError
对于更细粒度的控件,可以使用 Timeout
实例,允许您指定单独的连接和读取超时:
import urllib3
resp = urllib3.request(
"GET",
"https://httpbin.org/delay/3",
timeout=urllib3.Timeout(connect=1.0)
)
print(type(resp))
# <urllib3.response.HTTPResponse>
urllib3.request(
"GET",
"https://httpbin.org/delay/3",
timeout=urllib3.Timeout(connect=1.0, read=2.0)
)
# MaxRetryError caused by ReadTimeoutError
如果您希望所有请求都受到相同的超时,则可以在 PoolManager
水平:
import urllib3
http = urllib3.PoolManager(timeout=3.0)
http = urllib3.PoolManager(
timeout=urllib3.Timeout(connect=1.0, read=2.0)
)
您仍然可以通过指定以下内容来覆盖此池级别超时 timeout
至 request()
。
正在重试请求#
Urllib3可以自动重试幂等请求。同样的机制也可以处理重定向。您可以使用 retries
参数设置为 request()
。默认情况下,urllib3会重试3次请求,最多跟踪3次重定向。
要更改重试次数,只需指定一个整数:
import urllib3
urllib3.request("GET", "https://httpbin.org/ip", retries=10)
要禁用所有重试和重定向逻辑,请指定 retries=False
:
import urllib3
urllib3.request(
"GET",
"https://nxdomain.example.com",
retries=False
)
# NewConnectionError
resp = urllib3.request(
"GET",
"https://httpbin.org/redirect/1",
retries=False
)
print(resp.status)
# 302
要禁用重定向但保留重试逻辑,请指定 redirect=False
:
resp = urllib3.request(
"GET",
"https://httpbin.org/redirect/1",
redirect=False
)
print(resp.status)
# 302
对于更细粒度的控件,可以使用 Retry
实例。这个类允许您更大程度地控制请求的重试方式。
例如,要执行总共3次重试,但仅限于2次重定向:
urllib3.request(
"GET",
"https://httpbin.org/redirect/3",
retries=urllib3.Retry(3, redirect=2)
)
# MaxRetryError
您也可以禁用太多重定向的异常,只返回 302
回应:
resp = urllib3.request(
"GET",
"https://httpbin.org/redirect/3",
retries=urllib3.Retry(
redirect=2,
raise_on_redirect=False
)
)
print(resp.status)
# 302
如果希望所有请求都受同一重试策略的约束,则可以在 PoolManager
水平:
import urllib3
http = urllib3.PoolManager(retries=False)
http = urllib3.PoolManager(
retries=urllib3.Retry(5, redirect=2)
)
您仍然可以通过指定以下内容来覆盖此池级别重试策略 retries
至 request()
。
错误和异常#
urllib3包装较低级别的异常,例如:
import urllib3
try:
urllib3.request("GET","https://nx.example.com", retries=False)
except urllib3.exceptions.NewConnectionError:
print("Connection failed.")
# Connection failed.
见 exceptions
所有异常的完整列表。
登录中#
如果您使用的是标准库 logging
urllib3模块将发出多个日志。在某些情况下,这可能是不可取的。您可以使用标准记录器界面更改urllib3的记录器的日志级别:
logging.getLogger("urllib3").setLevel(logging.WARNING)