PYPI官网
github官网
官网文档
Requests允许您非常轻松地发送 HTTP/1.1 请求。无需手动将查询字符串添加到您的 URL,或对您的 POST 数据进行表单编码。Keep-alive 和 HTTP 连接池是 100% 自动的,基于urllib3。
安装
快速入门
发出请求
1
2
3
4
5
6
|
r = requests.get('https://api.github.com/events')
r = requests.post('https://httpbin.org/post', data={'key': 'value'})
r = requests.put('https://httpbin.org/put', data={'key': 'value'})
r = requests.delete('https://httpbin.org/delete')
r = requests.head('https://httpbin.org/get')
r = requests.options('https://httpbin.org/get')
|
在 URL 中传递参数
针对httpbin.org/get?key=val
类型参数
1
2
|
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('https://httpbin.org/get', params=payload)
|
打印url
任何值为None的字典键都不会添加到 URL 的查询字符串中
响应内容
读取服务器响应的内容
1
|
r.text#'[{"repository":{"open_issues":0,"url":"https://github.com/...
|
默认提交给服务器的编码类型是unicode,可以修改服务器编码类型
1
2
|
r.encoding#'utf-8'
r.encoding = 'ISO-8859-1'
|
二进制响应内容
非文本请求,以字节形式访问响应主体
1
|
r.content#b'[{"repository":{"open_issues":0,"url":"https://github.com/...
|
默认解码格式是gzip
如果安装了像brotli或brotlicffi这样的 Brotli 库,br 传输编码会自动为您解码
例如,要从请求返回的二进制数据创建图像
1
2
3
4
|
from PIL import Image
from io import BytesIO
i = Image.open(BytesIO(r.content))
|
JSON 响应内容
requests 内置了 JSON 解码器
1
|
r.json()#[{'repository': {'open_issues': 0, 'url': 'https://github.com/...
|
如果解码失败,r.json()引发异常,抛出requests.exceptions.JSONDecodeError。例如,如果响应获得 204(无内容),或者如果响应包含无效的 JSON。
原始响应内容
从服务器获取原始套接字响应,进行流式传输,设置stream=True
1
2
3
|
r = requests.get('https://api.github.com/events', stream=True)
r.raw#<urllib3.response.HTTPResponse object at 0x101194810>
r.raw.read(10)
|
保存流式传输到文件
1
2
3
|
with open(filename, 'wb') as fd:
for chunk in r.iter_content(chunk_size=128):
fd.write(chunk)
|
自定义标题
1
2
3
4
|
url = 'https://api.github.com/some/endpoint'
headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get(url, headers=headers)
|
更复杂的 POST 请求
1
2
3
|
payload_dict = {'key1': ['value1', 'value2']}
r2 = requests.post('https://httpbin.org/post', data=payload_dict)
print(r1.text)
|
data 可以传入 字符串 和 字典。字典将自动编码为json字符串
添加文件
1
2
3
4
|
url = 'https://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
|
显式设置文件名、内容类型和标题
1
2
3
4
|
url = 'https://httpbin.org/post'
files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
r = requests.post(url, files=files)
|
发送要作为文件接收的字符串
1
2
3
4
|
url = 'https://httpbin.org/post'
files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}
r = requests.post(url, files=files)
|
非常大的文件作为multipart/form-data 请求发送需要流式传输该请求。默认情况下,requests不支持这个,但是有一个单独的包 requests-toolbelt支持。
响应状态代码
1
2
|
r = requests.get('https://httpbin.org/get')
r.status_code#200
|
内置的状态码查找对象
1
|
r.status_code == requests.codes.ok#True
|
判断状态码是否正常的工具函数,如果错误将抛出requests.exceptions.HTTPError异常,否则返回None
响应头
返回一个字典
cookie
响应的cookie
将自己的 cookie 发送到服务器
1
2
3
4
|
url = 'https://httpbin.org/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies)
|
使用cookieJar管理cookie
1
2
3
4
5
|
jar = requests.cookies.RequestsCookieJar()
jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
url = 'https://httpbin.org/cookies'
r = requests.get(url, cookies=jar)
|
重定向和历史
可以通过历史重定向的请求
1
2
3
4
|
r = requests.get('http://github.com/')
r.url#'https://github.com/
r.status_code#200
r.history#[<Response [301]>]
|
GET、OPTIONS、POST、PUT、PATCH 或 DELETE默认启用重定向,使用allow_redirects参数禁用重定向处理
1
2
3
|
r = requests.get('http://github.com/', allow_redirects=False)
r.status_code#301
r.history#[]
|
HEAD默认禁用重定向,使用allow_redirects参数启用重定向处理
1
2
3
4
|
r = requests.head('http://github.com/', allow_redirects=True)
r.url#'https://github.com/
r.status_code#200
r.history#[<Response [301]>]
|
超时
几乎所有生产代码都应在几乎所有请求中使用此参数。不这样做可能会导致您的程序无限期挂起。这个超时不是整个交互过程超时,而是接收第一个字节超时
1
|
requests.get('https://github.com/', timeout=0.001)
|
错误和异常
Requests 显式引发的所有异常都继承自 requests.exceptions.RequestException.
- 出现网络问题(例如 DNS 故障、拒绝连接等),引发ConnectionError异常
- HTTP 请求返回不成功的状态代码,引发HTTPError异常
- 请求超时,引发Timeout异常
- 请求超过配置的最大重定向数, 引发TooManyRedirects异常
高级用法
会话对象
Session 对象允许您跨请求保留某些参数。它还会在 Session 实例发出的所有请求中保留 cookie,并将使用urllib3的连接池。底层的 TCP 连接将被重用,这可能会显着提高性能。
1
2
3
4
|
s = requests.Session()
s.get('https://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get('https://httpbin.org/cookies')
|
会话也可用于向请求方法提供默认数据:
1
2
|
s.auth = ('user', 'pass')
s.headers.update({'x-test': 'true'})
|
传递给请求方法级字典都将与设置的会话级值合并,方法级参数覆盖会话参数
会话也可以用作上下文管理器:
1
2
|
with requests.Session() as s:
s.get('https://httpbin.org/cookies/set/sessioncookie/123456789')
|
从字典参数中删除一个值:在单次请求中会话级字典的键,只需在方法级参数中将该键的值设置为None
请求和响应对象
1
2
|
r.headers#响应头
r.request.headers#请求头
|
准备好的请求
每次API 调用或会话调用发送的请求其实就是一个PreparedRequest对象,r.request也是这个对象。所以通过在发送前修改这个对象能够实现对正文或标头(或其他任何内容)做一些额外的工作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
req = Request('POST', url, data=data, headers=headers)
prepped = req.prepare()
# do something with prepped.body
prepped.body = 'No, I want exactly this as the body.'
# do something with prepped.headers
del prepped.headers['Content-Type']
resp = s.send(prepped,
stream=stream,
verify=verify,
proxies=proxies,
cert=cert,
timeout=timeout
)
|
上面的代码无法使用session对象配置的会话级属性,使用Session.prepare_request()替换Request.prepare()
1
|
prepped = s.prepare_request(req)
|
SSL 证书验证
默认情况下,启用 SSL 验证,如果无法验证证书,Requests 将抛出 SSLError:
1
|
requests.get('https://requestb.in')#requests.exceptions.SSLError: hostname 'requestb.in' doesn't match either of '*.herokuapp.com', 'herokuapp.com'
|
可以将verify路径传递给带有受信任 CA 证书的 CA_BUNDLE 文件或目录
1
2
3
4
|
requests.get('https://github.com', verify='/path/to/certfile')
s = requests.Session()
s.verify = '/path/to/certfile'
|
如果verify设置为目录路径,则必须使用 OpenSSL 提供的实用程序c_rehash处理该目录。
当verify设置为时False,请求将接受服务器提供的任何 TLS 证书,并将忽略主机名不匹配和/或过期的证书
客户端证书
指定本地证书用作客户端证书,使用单个文件(包含私钥和证书)或两个文件路径的元组
1
2
3
4
5
|
requests.get('https://kennethreitz.org', cert=('/path/client.cert', '/path/client.key'))
<Response [200]>
s = requests.Session()
s.cert = '/path/client.cert'
|
指定错误的路径或无效的证书,抛出 SSLError
本地证书的私钥必须未加密。目前,Requests 不支持使用加密密钥
CA 证书
Requests 使用包certifi中的证书。当certifi未安装时,这会导致在使用明显较旧版本的 Requests 时出现极其过时的证书包。为了安全起见,我们建议经常升级 certifi!
正文内容工作流程
默认情况下,当您发出请求时,会立即下载响应正文。
覆盖此行为并推迟下载响应主体,直到您使用stream参数访问Response.content 属性:
1
2
|
tarball_url = 'https://github.com/psf/requests/tarball/main'
r = requests.get(tarball_url, stream=True)
|
此时只有响应标头已被下载并且连接保持打开状态,可以根据响应头信息决定下载正文:
1
2
3
|
if int(r.headers['content-length']) < TOO_LONG:
content = r.content
...
|
可以使用Response.iter_content() 和Response.iter_lines()方法进一步控制工作流
如果您在发出请求时设置stream为True,除非您消耗所有数据或调用Response.close,否则 Requests 无法将连接释放回池中 。这可能导致连接效率低下。在使用stream=True时部分阅读了请求正文(或根本没有阅读),您应该在with声明中发出请求以确保它始终关闭:
1
2
|
with requests.get('https://httpbin.org/get', stream=True) as r:
# Do things with the response here.
|
保持活动
keep-alive 在一个会话中是 100% 自动的
流媒体上传
Requests 支持流式上传,这允许您发送大型流或文件而无需将它们读入内存。要流式传输和上传,只需为您的身体提供一个类似文件的对象:
1
2
|
with open('massive-body', 'rb') as f:
requests.post('http://some.url/streamed', data=f)
|
块编码请求
Requests 还支持传出和传入请求的分块传输编码,要发送块编码的请求,只需为您的正文提供一个生成器(或任何没有长度的迭代器)
1
2
3
4
5
|
def gen():
yield 'hi'
yield 'there'
requests.post('http://some.url/chunked', data=gen())
|
对于分块编码的响应,最好使用 Response.iter_content()并设置stream=True
发送多个多部分编码文件
将文件设置为(form_field_name, file_info)元组列表:
1
2
3
4
5
|
url = 'https://httpbin.org/post'
multiple_files = [
('images', ('foo.png', open('foo.png', 'rb'), 'image/png')),
('images', ('bar.png', open('bar.png', 'rb'), 'image/png'))]
r = requests.post(url, files=multiple_files)
|
事件挂钩Hook
Requests 有一个挂钩系统,您可以使用它来操作部分请求过程或信号事件处理
您可以通过将字典传递给请求参数来为每个请求分配一个挂钩函数。回调函数必须处理自己的异常。如果回调函数返回一个值,将替换传入的数据。如果函数不返回任何内容,则没有影响。可以向单个请求添加多个挂钩。
1
2
3
4
5
6
7
8
|
def print_url(r, *args, **kwargs):
print(r.url)
def record_hook(r, *args, **kwargs):
r.hook_called = True
return r
r = requests.get('https://httpbin.org/', hooks={'response': [print_url, record_hook]})
|
可以向Session实例添加挂钩
1
2
3
|
s = requests.Session()
s.hooks['response'].append(print_url)
s.get('https://httpbin.org/')
|
自定义认证
Requests 允许指定自己的身份验证机制
身份验证实现是AuthBase的子类。Requests 在requests.auth中提供了两种常见的身份验证方案实现:HTTPBasicAuth和HTTPDigestAuth
- class requests.auth.HTTPBasicAuth(username, password):Attaches HTTP Basic Authentication to the given Request object.
- lass requests.auth.HTTPDigestAuth(username, password):Attaches HTTP Digest Authentication to the given Request object.
自定义身份认证:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
from requests.auth import AuthBase
class PizzaAuth(AuthBase):
"""Attaches HTTP Pizza Authentication to the given Request object."""
def __init__(self, username):
# setup any auth-related data here
self.username = username
def __call__(self, r):
# modify and return the request
r.headers['X-Pizza'] = self.username
return r
requests.get('http://pizzabin.org/admin', auth=PizzaAuth('kenneth'))
|
其实就是在__call__方法里面修改请求头
流媒体请求
Response.iter_lines()您可以轻松地迭代流式 API。只需设置stream True并迭代响应 iter_lines:
1
2
3
4
5
6
7
8
9
10
11
|
import json
import requests
r = requests.get('https://httpbin.org/stream/20', stream=True)
for line in r.iter_lines():
# filter out keep-alive new lines
if line:
decoded_line = line.decode('utf-8')
print(json.loads(decoded_line))
|
将decode_unicode=True与 Response.iter_lines()或Response.iter_content() 一起使用时,如果服务器不提供后备编码,需要指定编码:
1
2
3
4
5
6
7
8
|
r = requests.get('https://httpbin.org/stream/20', stream=True)
if r.encoding is None:
r.encoding = 'utf-8'
for line in r.iter_lines(decode_unicode=True):
if line:
print(json.loads(line))
|
代理
使用proxies参数配置单独的请求或Session:
1
2
3
4
5
6
7
8
9
10
|
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
}
requests.get('http://example.org', proxies=proxies)
session = requests.Session()
session.proxies.update(proxies)
session.get('http://example.org')
|
session.proxies的行为可能与预期不同。提供的值将被环境代理(由urllib.request.getproxies返回的那些)覆盖。为确保在存在环境代理的情况下使用代理,请明确指定proxies所有单独请求的参数。
代理有HTTP Basic Auth时,需要使用账号密码配置proxy为如下形式:
1
2
|
# http://user:password@host/
proxies = {'http': 'http://user:pass@10.10.1.10:3128/'}
|
要为特定方案和主机提供代理,请使用 scheme://hostname形式作为键。这将匹配对给定方案和确切主机名的任何请求。
1
|
proxies = {'http://10.20.1.128': 'http://10.10.1.10:5323'}
|
使用代理进行 https 连接通常需要您的本地计算机信任代理的根证书,请求信任的证书列表可以通过以下方式找到
1
|
print(DEFAULT_CA_BUNDLE_PATH)
|
将REQUESTS_CA_BUNDLE (或CURL_CA_BUNDLE)环境变量设置为另一个文件路径来覆盖此默认证书包
1
|
export REQUESTS_CA_BUNDLE="/usr/local/myproxy_info/cacert.pem"
|
SOCKS
Requests 还支持使用 SOCKS 协议的代理
需要安装第三方库
1
|
python -m pip install requests[socks]
|
安装这些依赖项后,使用 SOCKS 代理就像使用 HTTP 代理一样简单:
1
2
3
4
|
proxies = {
'http': 'socks5://user:pass@host:port',
'https': 'socks5://user:pass@host:port'
}
|
阻塞还是非阻塞
Requests 不提供任何类型的非阻塞 IO
超时
默认只配置connect超时,但是也可以通过第二个参数配置read超时
1
|
r = requests.get('https://github.com', timeout=(3.05, 27))
|