用户指南

安装

可以安装ULLIb3 pip

$ python -m pip install urllib3

提出请求

首先,导入urllib3模块:

>>> import urllib3

你需要一个 PoolManager 实例发出请求。此对象处理连接池和线程安全的所有详细信息,因此您不必:

>>> http = urllib3.PoolManager()

请求使用 request()

>>> r = http.request('GET', 'http://httpbin.org/robots.txt')
>>> r.data
b'User-agent: *\nDisallow: /deny\n'

request() 返回A HTTPResponse 对象 响应内容 部分说明如何处理各种响应。

你可以使用 request() 要使用任何HTTP谓词发出请求,请执行以下操作:

>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     fields={'hello': 'world'}
... )

这个 请求数据 本节介绍发送其他类型的请求数据,包括json、文件和二进制数据。

响应内容

这个 HTTPResponse 对象提供 statusdataheaders 属性:

>>> r = http.request('GET', 'http://httpbin.org/ip')
>>> r.status
200
>>> r.data
b'{\n  "origin": "104.232.115.37"\n}\n'
>>> r.headers
HTTPHeaderDict({'Content-Length': '33', ...})

JSON内容

JSON内容可以通过解码和反序列化来加载。 data 请求的属性:

>>> import json
>>> r = http.request('GET', 'http://httpbin.org/ip')
>>> json.loads(r.data.decode('utf-8'))
{'origin': '127.0.0.1'}

二进制内容

这个 data 响应的属性始终设置为表示响应内容的字节字符串:

>>> r = http.request('GET', 'http://httpbin.org/bytes/8')
>>> r.data
b'\xaa\xa5H?\x95\xe9\x9b\x11'

注解

对于更大的响应,有时最好是 stream 反应。

对响应内容使用io包装器

有时候你想用 io.TextIOWrapper 或类似的对象,如直接使用 HTTPResponse 数据。要使这两个接口很好地结合在一起,需要使用 auto_close 通过将其设置为 False . 默认情况下,读取所有字节后关闭HTTP响应,这将禁用该行为:

>>> import io
>>> r = http.request('GET', 'https://example.com', preload_content=False)
>>> r.auto_close = False
>>> for line in io.TextIOWrapper(r):
>>>     print(line)

请求数据

报头

您可以在 headers 论点 request()

>>> r = http.request(
...     'GET',
...     'http://httpbin.org/headers',
...     headers={
...         'X-Something': 'value'
...     }
... )
>>> json.loads(r.data.decode('utf-8'))['headers']
{'X-Something': 'value', ...}

查询参数

为了 GETHEADDELETE 请求,您可以简单地将参数作为字典传递到 fields 参数 request()

>>> r = http.request(
...     'GET',
...     'http://httpbin.org/get',
...     fields={'arg': 'value'}
... )
>>> json.loads(r.data.decode('utf-8'))['args']
{'arg': 'value'}

为了 POSTPUT 请求时,需要在URL中手动编码查询参数:

>>> from urllib.parse import urlencode
>>> encoded_args = urlencode({'arg': 'value'})
>>> url = 'http://httpbin.org/post?' + encoded_args
>>> r = http.request('POST', url)
>>> json.loads(r.data.decode('utf-8'))['args']
{'arg': 'value'}

表单数据

为了 PUTPOST 请求时,urllib3将在 fields 参数提供给 request()

>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     fields={'field': 'value'}
... )
>>> json.loads(r.data.decode('utf-8'))['form']
{'field': 'value'}

JSON

可以通过指定编码数据作为JSON请求发送 body 参数和设置 Content-Type 呼叫时的标题 request()

>>> import json
>>> data = {'attribute': 'value'}
>>> encoded_data = json.dumps(data).encode('utf-8')
>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     body=encoded_data,
...     headers={'Content-Type': 'application/json'}
... )
>>> json.loads(r.data.decode('utf-8'))['json']
{'attribute': 'value'}

文件和二进制数据

用于使用 multipart/form-data 编码可以使用相同的方法 表单数据 并将文件字段指定为 (file_name, file_data)

>>> with open('example.txt') as fp:
...     file_data = fp.read()
>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     fields={
...         'filefield': ('example.txt', file_data),
...     }
... )
>>> json.loads(r.data.decode('utf-8'))['files']
{'filefield': '...'}

虽然不严格要求指定文件名,但建议您使用该文件名以匹配浏览器行为。您也可以传递元组中的第三个项来显式指定文件的MIME类型:

>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     fields={
...         'filefield': ('example.txt', file_data, 'text/plain'),
...     }
... )

对于发送原始二进制数据,只需指定 body 争论。也建议设置 Content-Type 标题:

>>> with open('example.jpg', 'rb') as fp:
...     binary_data = fp.read()
>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     body=binary_data,
...     headers={'Content-Type': 'image/jpeg'}
... )
>>> json.loads(r.data.decode('utf-8'))['data']
b'...'

证书验证

注解

版本1.25中的新增功能:

现在默认情况下验证https连接 (cert_reqs = 'CERT_REQUIRED'

而您可以通过设置来禁用证书验证 cert_reqs = 'CERT_NONE' ,强烈建议保持开启状态。

除非另有规定,否则urllib3将尝试加载默认的系统证书存储。最可靠的跨平台方法是使用 certifi 提供Mozilla根证书捆绑包的包:

$ python -m pip install certifi

还可以使用UrLIb3安装证书。 secure 额外费用:

$ python -m pip install urllib3[secure]

警告

如果您使用的是python 2,那么可能需要额外的包。见 section below 了解更多详细信息。

一旦有证书,就可以创建一个 PoolManager 在发出请求时验证证书:

>>> import certifi
>>> import urllib3
>>> http = urllib3.PoolManager(
...     cert_reqs='CERT_REQUIRED',
...     ca_certs=certifi.where()
... )

这个 PoolManager 将自动处理证书验证并引发 SSLError 如果验证失败:

>>> http.request('GET', 'https://google.com')
(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 .

python2中的证书验证

python 2的旧版本是用 ssl 缺少的模块 SNI support 而且可能落后于安全更新。出于这些原因,建议使用 pyOpenSSL .

如果使用 secure 另外,将安装Python 2上证书验证所需的所有包:

$ python -m pip install urllib3[secure]

如果要手动安装软件包,则需要 pyOpenSSLcryptographyidnacertifi .

注解

如果您不使用MacOS或Windows,请注意 cryptography 需要其他系统包才能编译。见 building cryptography on Linux 需要的包列表。

一旦安装,您可以告诉ULLIb3使用PyopSSL使用 urllib3.contrib.pyopenssl

>>> import urllib3.contrib.pyopenssl
>>> urllib3.contrib.pyopenssl.inject_into_urllib3()

最后,您可以创建一个 PoolManager 在执行请求时验证证书:

>>> import certifi
>>> import urllib3
>>> http = urllib3.PoolManager(
...     cert_reqs='CERT_REQUIRED',
...     ca_certs=certifi.where()
... )

如果您不希望使用PyopSSL,则可以省略调用 urllib3.contrib.pyopenssl.inject_into_urllib3() . urllib3将返回标准库 ssl 模块。你可能会经历 several warnings 做这个的时候。

警告

如果不使用pyopenssl,则必须使用ssl支持编译python,以使证书验证生效。这是不常见的,但是可以在没有ssl支持的情况下编译python。看到这个 StackOverflow thread 了解更多详细信息。

如果您使用的是Google应用程序引擎,则必须在 app.yaml

libraries:
- name: ssl
  version: latest

使用超时

超时允许您控制在中止请求之前允许运行的时间(秒)。在简单情况下,可以指定超时为 floatrequest()

>>> http.request(
...     'GET', 'http://httpbin.org/delay/3', timeout=4.0
... )
<urllib3.response.HTTPResponse>
>>> http.request(
...     'GET', 'http://httpbin.org/delay/3', timeout=2.5
... )
MaxRetryError caused by ReadTimeoutError

对于更细粒度的控件,可以使用 Timeout 实例,允许您指定单独的连接和读取超时:

>>> http.request(
...     'GET',
...     'http://httpbin.org/delay/3',
...     timeout=urllib3.Timeout(connect=1.0)
... )
<urllib3.response.HTTPResponse>
>>> http.request(
...     'GET',
...     'http://httpbin.org/delay/3',
...     timeout=urllib3.Timeout(connect=1.0, read=2.0)
... )
MaxRetryError caused by ReadTimeoutError

如果您希望所有请求都受到相同的超时,则可以在 PoolManager 水平:

>>> http = urllib3.PoolManager(timeout=3.0)
>>> http = urllib3.PoolManager(
...     timeout=urllib3.Timeout(connect=1.0, read=2.0)
... )

您仍然可以通过指定 timeoutrequest() .

正在重试请求

URLILB3可以自动重试幂等请求。同样的机制也处理重定向。您可以使用 retries 参数到 request() . 默认情况下,urllib3将重试请求3次,并跟踪3次重定向。

要更改重试次数,只需指定一个整数:

>>> http.requests('GET', 'http://httpbin.org/ip', retries=10)

要禁用所有重试和重定向逻辑,请指定 retries=False

>>> http.request(
...     'GET', 'http://nxdomain.example.com', retries=False
... )
NewConnectionError
>>> r = http.request(
...     'GET', 'http://httpbin.org/redirect/1', retries=False
... )
>>> r.status
302

要禁用重定向但保留重试逻辑,请指定 redirect=False

>>> r = http.request(
...     'GET', 'http://httpbin.org/redirect/1', redirect=False
... )
>>> r.status
302

对于更细粒度的控件,可以使用 Retry 实例。这个类允许您更大程度地控制请求的重试方式。

例如,要执行总共3次重试,但仅限于2次重定向:

>>> http.request(
...     'GET',
...     'http://httpbin.org/redirect/3',
...     retries=urllib3.Retry(3, redirect=2)
... )
MaxRetryError

您也可以禁用太多重定向的异常,只返回 302 回应:

>>> r = http.request(
...     'GET',
...     'http://httpbin.org/redirect/3',
...     retries=urllib3.Retry(
...         redirect=2, raise_on_redirect=False)
... )
>>> r.status
302

如果希望所有请求都受同一重试策略的约束,则可以在 PoolManager 水平:

>>> http = urllib3.PoolManager(retries=False)
>>> http = urllib3.PoolManager(
...     retries=urllib3.Retry(5, redirect=2)
... )

您仍然可以通过指定 retriesrequest() .

错误和异常

urllib3包装较低级别的异常,例如:

>>> try:
...     http.request('GET', 'nx.example.com', retries=False)
... except urllib3.exceptions.NewConnectionError:
...     print('Connection failed.')

exceptions 所有异常的完整列表。

登录中

如果您使用的是标准库 logging urllib3模块将发出多个日志。在某些情况下,这可能是不可取的。您可以使用标准记录器界面更改urllib3的记录器的日志级别:

>>> logging.getLogger("urllib3").setLevel(logging.WARNING)