首先,导入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()
返回一个HTTPResponse对象, 响应内容部分解释了如何处理各种响应。
您可以使用request()
任何HTTP动词来发出请求:
>>> r = http.request(
... 'POST',
... 'http://httpbin.org/post',
... fields={'hello': 'world'})
该请求数据部分涵盖发送其他类型的请求的数据,包括JSON,文件和二进制数据。
的HTTPResponse对象提供 status
,data和 header
属性:
>>> 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', ...})
可以通过解码和反序列data化请求的属性来加载JSON内容 :
>>> 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'
注意
对于更大的响应,有时更好地传输 响应。
您可以在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', ...}
对于GET
,HEAD
和DELETE
请求,您只需将参数作为参数中的字典传递fields
给request()
:
>>> r = http.request(
... 'GET',
... 'http://httpbin.org/get',
... fields={'arg': 'value'})
>>> json.loads(r.data.decode('utf-8'))['args']
{'arg': 'value'}
对于POST
和PUT
请求,您需要在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'}
对于PUT
和POST
请求,urllib3将自动对fields
提供的参数中 的字典进行格式编码request()
:
>>> r = http.request(
... 'POST',
... 'http://httpbin.org/post',
... fields={'field': 'value'})
>>> json.loads(r.data.decode('utf-8'))['form']
{'field': 'value'}
您可以通过将编码数据指定为body
参数并Content-Type
在调用时设置标头来 向JSON发送请求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'...'
强烈建议始终使用SSL证书验证。 默认情况下,urllib3不验证HTTPS请求。
为了启用验证,您需要一组根证书。最简单,最可靠的方法是使用提供Mozilla根证书包的certifi包:
pip install certifi
您还可以使用secure
额外的安装与urllib3一起安装certifi :
pip install urllib3[secure]
警告
如果您使用的是Python 2,则可能需要其他软件包。有关详细信息,请参阅以下部分。
获得证书后,您可以创建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
。其他操作系统可能很难。
较旧版本的Python 2使用ssl缺少SNI支持的模块 构建,并且可能落后于安全更新。由于这些原因,建议使用 pyOpenSSL。
如果你使用secure
额外的安装urllib3,将安装Python 2上所有必需的证书验证包:
pip install urllib3[secure]
如果您想要手动安装的软件包,您需要pyOpenSSL
, cryptography
,idna
,和certifi
。
注意
如果您不使用macOS或Windows,请注意加密需要额外的系统包进行编译。有关 所需软件包的列表,请参阅在Linux上构建加密。
安装完成后,您可以通过以下方式告诉urllib3使用pyOpenSSL 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())
如果你不想使用pyOpenSSL,你可以简单地省略对它的调用urllib3.contrib.pyopenssl.inject_into_urllib3()。urllib3将回退到标准库ssl模块。执行此操作时,您可能会遇到 几个警告。
警告
如果您不使用pyOpenSSL,则必须使用ssl支持编译Python以使证书验证起作用。这种情况并不常见,但可以在没有SSL支持的情况下编译Python。有关 更多详细信息,请参阅此 Stackoverflow线程。
如果您使用的是Google App Engine,则必须在以下位置明确启用SSL支持app.yaml
:
libraries:
- name: ssl
version: latest
超时允许您控制在中止之前允许运行的请求的时间。在简单的情况下,您可以将超时指定float
为request()
:
>>> 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))
您仍然通过指定timeout
to来 覆盖此池级超时request()
。
urllib3可以自动重试幂等请求。同样的机制也处理重定向。您可以使用retries
参数to 控制重试次数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))
您仍然通过指定retries
to来 覆盖此池级重试策略request()
。
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)