文章目录
- Requests库简介
- 提出请求
- 响应内容
- 二进制响应内容
- JSON 响应内容
- 原始响应内容
- 自定义标头
- 更复杂的 POST 请求
- POST 多部分编码的文件
- 响应状态代码
- 响应标头
- Cookie
- 重定向和历史记录
- 超时
- 错误和异常
- Ending
Requests库简介
什么是Requests库
Requests是一个简单易用的HTTP库,用于Python编程语言。它允许你发送各种HTTP请求来与服务器进行交互。Requests库以其简洁的API和人性化的设计而广受开发者喜爱,使得进行网络请求变得直观和容易。
Requests库最初由Kenneth Reitz开发,现在已经成为Python标准库之外最流行的HTTP客户端库之一。它建立在Python的urllib3
库之上,提供了一个更高层次的接口来处理HTTP请求。
Requests库的主要特点和优势
-
人性化的API:Requests库的API设计直观,易于理解和使用。例如,发送一个GET请求只需要一行代码。
-
国际化支持:Requests支持国际域名和非ASCII字符,可以无缝处理Unicode URL。
-
连接保持和复用:Requests使用
urllib3
的连接池功能,可以自动重用HTTP连接,提高请求效率。 -
会话管理:通过
requests.Session
对象,可以跨请求保持某些参数和Cookie,实现会话管理。 -
JSON支持:Requests提供了便捷的JSON请求和响应处理功能,可以自动将JSON响应解析为Python字典。
-
表单和文件上传:可以轻松地上传文件和表单数据,支持多文件上传。
-
流式下载:支持流式上传和下载,适合处理大文件。
-
SSL/TLS支持:Requests支持HTTPS请求,可以验证服务器SSL证书。
-
自动内容解码:自动处理gzip和deflate压缩的响应内容。
-
异常处理:Requests定义了一套自己的异常体系,可以捕获并处理连接错误、超时错误等。
-
Cookie处理:可以自动处理Cookie,也可以手动设置和发送Cookie。
-
代理支持:支持设置HTTP代理和SOCKS代理。
-
自定义请求头:可以方便地添加或修改请求头。
-
社区活跃:拥有活跃的社区和丰富的文档,易于获取帮助和资源。
-
跨平台:Requests库可以在多种操作系统上运行,包括Windows、macOS和Linux。
Requests库的这些特点和优势使其成为Python开发者进行网络请求的首选工具之一。无论是简单的数据抓取任务,还是复杂的API交互,Requests都能提供强大而灵活的支持。
import requests
r = requests.get('https://api.github.com/user', auth=('user', 'pass'))
print(r.status_code)
print(r.headers['content-type'])
print(r.encoding)
print(r.text)
print(r.json())
提出请求
使用 Requests 发出请求非常简单。
首先导入 Requests 模块:
import requests
现在,让我们尝试获取一个网页。对于此示例,让我们获取 GitHub 的公共 时间线:
r = requests.get('https://api.github.com/events')
现在,我们有一个名为 .我们可以 从这个对象中获取我们需要的所有信息。r
Requests 的简单 API 意味着所有形式的 HTTP 请求都是显而易见的。为 例如,以下是您发出 HTTP POST 请求的方式:
r = requests.post('https://httpbin.org/post', data={'key': 'value'})
很好,对吧?其他 HTTP 请求类型呢:PUT、DELETE、HEAD 和 选项?这些都同样简单:
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')
这一切都很好,但这也只是 Requests 可以做什么的开始 做。
在 URL 中传递参数
您经常希望在 URL 的查询字符串中发送某种数据。如果 您正在手动构建 URL,此数据将作为键/值给出 URL 中的问号后面的对,例如 . Requests 允许您将这些参数作为字符串字典提供, 使用 Keyword 参数。例如,如果要将 和 传递给 ,则可以使用 以下代码:httpbin.org/get?key=valparamskey1=value1key2=value2httpbin.org/get
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('https://httpbin.org/get', params=payload)
通过打印 URL,您可以看到 URL 已正确编码:
print(r.url)
https://httpbin.org/get?key2=value2&key1=value1
请注意,任何值为None 的字典键都不会被添加到 URL 的查询字符串。
您还可以将项目列表作为值传递:
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.get('https://httpbin.org/get', params=payload)
print(r.url)
https://httpbin.org/get?key1=value1&key2=value2&key2=value3
响应内容
我们可以读取服务器响应的内容。考虑 GitHub 时间线 再:
import requests
r = requests.get('https://api.github.com/events')
r.text
'[{"repository":{"open_issues":0,"url":"https://github.com/...
请求将自动解码来自服务器的内容。大多数 unicode 字符集被无缝解码。
当发出请求时,Requests 会对 基于 HTTP 标头的响应。Requests 猜测的文本编码 在访问 时使用。您可以了解 Requests 是什么编码 使用并更改它,使用属性:r.textr.encoding
r.encoding
'utf-8'
r.encoding = 'ISO-8859-1'
如果更改编码,则 Requests 将使用 whenever 调用 的新值。在以下情况下,可能希望执行此操作 可以应用特殊逻辑来计算内容的编码方式 是。例如,HTML 和 XML 能够在 他们的身体。在这种情况下,我们应该使用它来查找 编码,然后设置 .这将使您能够与 正确的编码。r.encodingr.textr.contentr.encodingr.text
如果需要,请求还将使用自定义编码。如果 您已经创建了自己的编码并将其注册到模块中,您可以简单地使用编解码器名称作为 和 的值 请求将为您处理解码。codecsr.encoding
二进制响应内容
对于非文本请求,还可以以字节的形式访问响应正文:
r.content
b'[{"repository":{"open_issues":0,"url":"https://github.com/...
和传输编码会自动为您解码。gzipdeflate
如果 Brotli 库,则会自动解码传输编码 像 brotli 或 brotlicffi 一样已安装。br
例如,要从请求返回的二进制数据创建图像,您可以 使用以下代码:
from PIL import Image
from io import BytesIO
i = Image.open(BytesIO(r.content))
i.show()
报错:PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x000002A935536130>
这里一般指的是找不到对应资源,后续我换了一个能爬取的图片,结果是这样的:
JSON 响应内容
还有一个内置的 JSON 解码器,以防您正在处理 JSON 数据:
import requests
r = requests.get('https://api.github.com/events')
r.json()
[{'repository': {'open_issues': 0, 'url': 'https://github.com/...
如果 JSON 解码失败,则会引发异常。例如,如果 响应获取 204(无内容),或者如果响应包含无效的 JSON, 尝试提高 。此包装器异常 为可能由不同 Python 版本和 JSON 序列化库。r.json()r.json()requests.exceptions.JSONDecodeError
需要注意的是,呼叫成功并不表示响应成功。某些服务器可能会在 响应失败(例如,HTTP 500 的错误详细信息)。这样的 JSON 将被解码 并返回。要检查请求是否成功,请使用 or check 是您期望的。r.json() r.raise_for_status() r.status_code
原始响应内容
在极少数情况下,您希望从 服务器,您可以访问 .如果要执行此操作,请确保在初始请求中进行设置。一旦你这样做了,你可以这样做:r.raw stream=True
r = requests.get('https://api.github.com/events', stream=True)
r.raw
<urllib3.response.HTTPResponse object at 0x101194810>
r.raw.read(10)
b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
但是,一般来说,您应该使用这样的模式来保存正在发生的内容 流式传输到文件:
with open(filename, 'wb') as fd:
for chunk in r.iter_content(chunk_size=128):
fd.write(chunk)
使用将处理很多我们本来会处理的事情 直接使用时必须处理。当流式传输 下载,以上是首选和推荐的检索方式 内容。请注意,可以自由调整为一个数字可能更适合的用例。Response.iter_content Response.rawchunk_size
注意
关于使用 versus 的重要说明。 将自动解码 和 传输编码。 是字节的原始流 – 它不是 转换响应内容。如果您确实需要访问字节,因为它们 被退回,使用。Response.iter_contentResponse.rawResponse.iter_contentgzipdeflateResponse.rawResponse.raw
自定义标头
如果您想将 HTTP 标头添加到请求中,只需将 a 传入参数即可。dic theaders
例如,我们在前面的示例中没有指定我们的 user-agent:
url = 'https://api.github.com/some/endpoint'
headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get(url, headers=headers)
注意:与更具体的信息源相比,自定义标题的优先级较低。例如:
如果凭据,则使用 headers= 设置的授权标头将被覆盖 在 中指定,而 又将被参数覆盖。请求将在 /.netrc、/_netrc 处搜索 netrc 文件。 或在 NETRC 环境变量指定的路径处。.netrcauth=
如果被重定向到主机外,则授权标头将被删除。
Proxy-Authorization 标头将被 URL 中提供的代理凭据覆盖。
当我们可以确定内容的长度时,Content-Length 标头将被覆盖。
此外,Requests 根本不会根据指定的自定义标头更改其行为。标头只是传递到最终请求中。
注意:所有标头值都必须是 、bytestring 或 unicode。虽然允许,但建议避免传递 unicode 标头值。string
更复杂的 POST 请求
通常,您希望发送一些表单编码的数据,就像 HTML 表单一样。 为此,只需将字典传递给参数即可。你发出请求时,数据字典将自动进行表单编码:data
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post('https://httpbin.org/post', data=payload)
print(r.text)
{
...
"form": {
"key2": "value2",
"key1": "value1"
},
...
}
咱也不知道这是个啥,那个网址甚至没有这个方法。可能只是作为演示吧。
对于每个键,该参数还可以有多个值。这可以是 通过创建元组列表或带有列表的字典来完成 作为值。当表单具有多个元素时,这尤其有用 使用相同的密钥:data data
payload_tuples = [('key1', 'value1'), ('key1', 'value2')]
r1 = requests.post('https://httpbin.org/post', data=payload_tuples)
payload_dict = {'key1': ['value1', 'value2']}
r2 = requests.post('https://httpbin.org/post', data=payload_dict)
print(r1.text)
{
...
"form": {
"key1": [
"value1",
"value2"
]
},
...
}
r1.text == r2.text
True
有时,您可能希望发送未进行表单编码的数据。如果 您传入 a 而不是 a,该数据将直接发布。string dict
import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))
例如,GitHub API v3 接受 JSON 编码的 POST/PATCH 数据:
请注意,上述代码不会添加标题 (所以特别是它不会将其设置为 )。Content-Typeapplication/json
如果您需要设置该标头,并且不想自己进行编码, 您也可以直接使用参数(在版本 2.4.2 中添加)传递它 它将被自动编码:dict json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, json=payload)
请注意,如果传递了 OR 任一参数,则忽略该参数。json datafiles
POST 多部分编码的文件
Requests 使上传 Multipart-encoded 文件变得简单:
url = 'https://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
您可以明确设置文件名、content_type和标题:
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)
r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
如果需要,可以将字符串作为文件发送以接收:
url = 'https://httpbin.org/post'
files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}
r = requests.post(url, files=files)
r.text
{
...
"files": {
"file": "some,data,to,send\\nanother,row,to,send\\n"
},
...
}
如果您将一个非常大的文件作为请求发布,您可能希望流式传输该请求。默认情况下,不会 支持这个,但有一个单独的包可以做 - 。您应该阅读工具带的文档,了解有关如何使用它的更多详细信息。multipart/form-datarequestsrequests-toolbelt
警告!!!
强烈建议您以二进制文件打开文件 模式。这是因为请求可能会尝试提供 您的标头,以及它是否执行此值 将设置为文件中的字节数。可能会出现错误 如果以文本模式打开文件。Content-Length
响应状态代码
我们可以检查响应状态代码:
r = requests.get('https://httpbin.org/get')
r.status_code
200
Requests 还带有一个内置的状态代码查找对象,以便于使用 参考:
r.status_code == requests.codes.ok
True
如果我们发出了错误的请求(4XX 客户端错误或 5XX 服务器错误响应),我们将 可以通过以下方式提出:
bad_r = requests.get('https://httpbin.org/status/404')
bad_r.status_code
404
bad_r.raise_for_status()
Traceback (most recent call last):
File "requests/models.py", line 832, in raise_for_status
raise http_error
requests.exceptions.HTTPError: 404 Client Error
但是,由于我们的 for 是 ,当我们调用时,我们得到:status_coder 200 raise_for_status()
r.raise_for_status()
None
一切都很好。
响应标头
我们可以使用 Python 字典查看服务器的响应头:
print(r.headers)
for header, value in r.headers.items():
print(f"{header}: {value}\n")
{
'content-encoding': 'gzip',
'transfer-encoding': 'chunked',
'connection': 'close',
'server': 'nginx/1.0.4',
'x-runtime': '148ms',
'etag': '"e1ca502697e5c9317743dc078f67693f"',
'content-type': 'application/json'
}
不过,这个字典很特别:它只为HTTP头文件制作。根据 RFC 7230,HTTP 标头名称 不区分大小写。
因此,我们可以使用我们想要的任何大小写来访问标题:
r.headers['Content-Type']
'application/json'
r.headers.get('content-type')
'application/json'
它的另一个特殊之处在于服务器可以多次发送相同的标头 具有不同值的次数,但 requests 将它们组合在一起,因此它们可以 根据 RFC 7230,在字典中的单个映射中表示:
接收者可以合并具有相同字段名称的多个标题字段 变成一对“字段-名称:字段-值”,而不改变语义 通过将每个后续字段值附加到组合的 字段值按顺序排列,用逗号分隔。
Cookie
如果响应包含一些 Cookie,您可以快速访问它们:
url = 'http://example.com/some/cookie/setting/url'
r = requests.get(url)
r.cookies['example_cookie_name']
'example_cookie_value'
要将您自己的 cookie 发送到服务器,您可以使用以下参数:cookies
url = 'https://httpbin.org/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies)
r.text
'{"cookies": {"cookies_are": "working"}}'
Cookie 以 、 形式返回 它的作用类似于一个,但也提供了一个更完整的界面, 适合在多个域或路径上使用。饼干罐可以 也被传递给请求:dict
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)
r.text
'{"cookies": {"tasty_cookie": "yum"}}'
在 ‘init.pyi’ 中找不到引用 ‘cookies’
File “D:\Python-project\pachong\xinwen\imagepa.py”, line 80, in
jar.set(‘tasty_cookie’, ‘yum’, domain=‘httpbin.org’, path=‘/cookies’)
TypeError: set() missing 1 required positional argument: ‘value’ 这里要注意呀朋友们我调用的时候把括号漏啦!!!!
重定向和历史记录
默认情况下,Requests 将对除 Requests 以外的所有谓词执行位置重定向 头。
我们可以使用 Response 对象的属性来跟踪重定向。history
该列表包含为以下目的而创建的对象: 完成请求。该列表按从最早到最新的顺序排序 响应。
例如,GitHub 将所有 HTTP 请求重定向到 HTTPS:
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
r = requests.get('http://github.com/', allow_redirects=False)
r.status_code
301
r.history
[]
如果您使用的是 HEAD,也可以启用重定向:
r = requests.head('http://github.com/', allow_redirects=True)
r.url
'https://github.com/'
r.history
[<Response [301]>]
超时
您可以告诉请求在给定数量的响应后停止等待响应 秒与参数。几乎所有的产品级代码都应该使用 此参数在几乎所有请求中。如果不这样做,可能会导致您的程序 无限期挂起:timeout
requests.get('https://github.com/', timeout=0.001)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
注意
timeout不是对整个响应下载的时间限制; 相反,如果服务器未发出 秒的响应(更准确地说,如果没有字节 在底层套接字上接收了几秒钟)。如果未明确指定超时,则请求会这样做不超时。timeout timeout
错误和异常
如果出现网络问题(例如DNS故障、连接被拒绝等), 请求将引发异常。
将 引发 if HTTP 请求返回了不成功的状态代码。
如果请求超时,则会出现异常提出。
如果请求超过配置的最大重定向次数,则会引发异常。
Requests 显式引发的所有异常都继承 。
结束~,这就是快速入门的全部内容啦