更多内容在
Python的Requests库是一个简单而强大的HTTP库,用于发送各种HTTP请求。它由Kenneth Reitz创建,旨在使HTTP请求变得简单、直观,同时提供丰富的功能来处理网络请求和响应。
github地址:https://github.com/psf/requests
首先,导入Requests模块:
import requests
现在,尝试获取一个网页。在这个例子中,获取GitHub的公共时间线:
r = requests.get('https://api.github.com/events')
现在,我们有一个名为r
的响应对象。我们可以从这个对象中获取我们所需的所有信息。
Requests的简单API意味着所有形式的HTTP请求都同样直观。例如,这是你发起HTTP POST请求的方式:
requests.post('https://httpbin.org/post', data={'key': 'value'})
那么其他HTTP请求类型:PUT、DELETE、HEAD和OPTIONS呢?这些也都同样简单:
requests.put('https://httpbin.org/put')
requests.delete('https://httpbin.org/delete')
requests.head('https://httpbin.org/get')
requests.options('https://httpbin.org/get')
在URL中传递参数 你经常想要在URL的查询字符串中发送一些数据。如果你手工构造URL,这些数据会在URL后面以问号后跟键/值对的形式给出,例如httpbin.org/get?key=val
。
Requests允许你使用字符串字典的形式提供这些参数,使用params
关键字参数。例如,如果你想传递key1=value1
和key2=value2
到httpbin.org/get
,你会使用以下代码:
requests.get('https://httpbin.org/get', params={'key1': 'value1', 'key2': 'value2'})
你可以看到URL已经被正确编码,通过打印URL:
print(r.url) # 输出:https://httpbin.org/get?key2=value2&key1=value1
注意,任何值为None
的字典键都不会被添加到URL的查询字符串中。
你也可以将列表作为值传递:
requests.get('https://httpbin.org/get', params={'key1': ['value1']})
响应内容 我们可以读取服务器响应的内容。再次考虑GitHub时间线:
r.text # 输出:[{"repository": {"open_issues": 0, "url": "https://github.com/...}}
Requests会自动解码服务器的内容。大多数Unicode字符集都会被无缝解码。
当你发起请求时,Requests会根据HTTP头猜测响应的编码。你可以通过r.encoding
属性找到Requests猜测的编码,并更改它:
r.encoding # 输出:'utf-8'
如果你更改了编码,Requests将在你调用r.text
时使用新的值。你可能希望在任何情况下都这样做,特别是在你可以应用特殊逻辑来确定内容编码的情况下。例如,HTML和XML有能力在它们的主体中指定它们的编码。在这种情况下,你应该使用r.content
来找到编码,然后设置r.encoding
。这将让你能够使用正确的编码与r.text
一起使用。
Requests也会在需要时使用自定义编码。如果你已经创建了自己的编码并注册了codecs模块,你可以直接使用编解码器名称作为r.encoding
的值,Requests将为你处理解码。
二进制响应内容 你也可以将响应体作为字节访问,用于非文本请求:
r.content # 输出:b'[{"repository": {"open_issues": 0, "url": "https://github.com/...}}
如果安装了像brotli或brotlicffi这样的Brotli库,gzip
和deflate
传输编码将自动为你解码。例如,要从请求返回的二进制数据创建图像,你可以使用以下代码:
from PIL import Image, ImageIO
i = Image.open(BytesIO(r.content))
JSON响应内容 还有一个内置的JSON解码器,以防你正在处理JSON数据:
r.json() # 输出:[{"repository": {"open_issues": 0, "url": "https://github.com/...}}
如果JSON解码失败,r.json()
会引发异常。例如,如果响应得到204(无内容),或者响应包含无效的JSON,尝试r.json()
会引发requests.exceptions.JSONDecodeError
。这个包装异常为可能由不同Python版本和json序列化库抛出的多个异常提供了互操作性。
请注意,调用的成功并不表示响应的成功。一些服务器可能在失败的响应中返回JSON对象(例如,HTTP 500的错误详情)。这样的JSON将被解码并返回。要检查请求是否成功,请使用r.raise_for_status()
或检查r.status_code
是否是你期望的。
原始响应内容 在极少数情况下,如果你想从服务器获取原始套接字响应,你可以访问r.raw
。如果你想这样做,请确保你在初始请求中设置了stream=True
。一旦你这样做了,你可以这样做:
r.raw # 输出:<http.client.HTTPResponse object at 0x101194810> read 10 b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
然而,通常你应该使用这样的模式来保存正在流式传输的内容:
with open(filename, 'wb') as fd:
for chunk in iter_content(chunk_size=128):
fd.write(chunk)
使用Response.iter_content
将处理许多你在使用Response.raw
时本来需要处理的事情。当流式下载时,上述是推荐和首选的方式来检索内容。请注意,chunk_size
可以自由调整到可能更适合你用例的数字。
注意 关于使用r.text
与r.content
的一个重要注意事项。r.text
会自动解码transfer-encodings
。r.content
是原始字节流——它不会转换响应内容。如果你真的需要访问返回的字节,使用r.content
。
自定义头部 如果你想在请求中添加HTTP头部,只需将字典传递给headers
参数。例如,我们在之前的例子中没有指定我们的用户代理:
requests.get('https://api.github.com/some/endpoint', headers={'user-agent': 'my-app/0.0.1'})
注意:自定义头部的优先级低于更具体的信息来源。例如:
-
使用
headers=
设置的Authorization
头部将被.netrc
中指定的凭据覆盖,这又会被子URL中提供的代理凭据覆盖。 -
如果你被重定向到其他主机,
Authorization
头部将被移除。 -
Proxy-Authorization
头部将被URL中提供的代理凭据覆盖。 -
当我们能够确定内容长度时,
Content-Length
头部将被覆盖。
此外,Requests根本不会根据指定的自定义头部改变其行为。头部只是被传递到最终请求中。
注意:所有头部值必须是字符串、字节串或Unicode。虽然允许,但建议避免传递Unicode头部值。
更复杂的POST请求 通常,你想要发送一些表单编码的数据——就像HTML表单一样。要做到这一点,只需传递一个字典到data
参数。你的数据字典将在请求时自动进行表单编码:
requests.post('https://httpbin.org/post', data={'key1': 'value1', 'key2': 'value2'})
data
参数还可以为每个键有多个值。这可以通过使data
既不是列表的元组也不是字典的列表值来完成。这在表单有多个使用相同键的元素时特别有用:
requests.post('https://httpbin.org/post', data=[('key1', 'value1'), ('key1', 'value2')])
或者
requests.post('https://httpbin.org/post', data={'key1': ['value1', 'value2']})
有时,你可能想要发送不是表单编码的数据。如果你传递的是files
而不是data
,那么数据将直接发布。例如,GitHub API v3接受JSON编码的POST/PATCH数据:
import json
requests.post('https://api.github.com/some/endpoint', data=json.dumps({'some': 'data'})
请注意,上述代码不会添加Content-Type
头部(特别是不会将其设置为application/json
)。如果你需要设置该头部并且不想自己编码,你也可以直接使用json
参数(在版本2.4.2中添加):
requests.post('https://api.github.com/some/endpoint', json={'some': 'data'})
注意,如果传递了files
,则会忽略json
参数。
POST一个Multipart编码的文件 Requests使得上传Multipart编码的文件变得简单:
requests.post('https://httpbin.org/post', files={'file': open('report.xls', 'rb')})
你可以明确设置文件名、内容类型和头部:
requests.post('https://httpbin.org/post', files={'file': ('report.xls', open('report.xls', 'rb
Requests库的更多功能参考官方文档:https://requests.readthedocs.io/en/lates