Python Requets库学习总结1

简介: Python Requets库学习总结1

快速开始

发送请求

>>> import requests
>>> r = requests.get('https://api.github.com/events') # GET
>>> r = requests.post('https://httpbin.org/post', data={'key': 'value'}) # POST
>>> r = requests.put('https://httpbin.org/put', data={'key': 'value'}) # PUT
>>> r = requests.delete('https://httpbin.org/delete') # DELETE
>>> r = requests.head('https://httpbin.org/get') # HEAD 
>>> r = requests.options('https://httpbin.org/get') # OPTIONS

URL传参

可以使用params字典参数为URL提供查询字符串参数,例如,访问 https://httpbin.org/get?key1=value1&key2=value2,可使用以下代码:

>>> import requests
>>> payload = {'key1': 'value1', 'key2': 'value2', 'key3':'', 'key4':None}
>>> r = requests.get('https://httpbin.org/get', params=payload)
>>> r.url
https://httpbin.org/get?key2=value2&key1=value1&key3=

需要注意的是,如果字典参数中key值(即URL参数的值为None),则该参数不会添加到URL的查询字符串中。

如果URL查询字符串中,存在重复参数(参数名称相同,参数值不同),则需要将key值设置为由参数值组成的列表,如下:

>>> import requests
>>> payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
>>> r = requests.get('https://httpbin.org/get', params=payload)
>>> r.url
https://httpbin.org/get?key1=value1&key2=value2&key2=value3

响应内容

读取服务器响应内容

>>> import requests
>>> r = requests.get('https://api.github.com/events')
>>> r.text
<class 'str'> [{"id":"27579847062","type":"PushEvent","actor":{"...

requests 将自动解码来自服务器的内容。大多数unicode字符集都是无缝解码的。

当你发出请求时,requests会根据HTTP头对响应的编码进行有依据的猜测。当你访问r.text时,将使用requests猜测的文本编码。可以使用r.encoding属性查找请求使用的编码,并对其进行更改:

>>> r.encoding # 输出:utf-8
r.encoding = 'ISO-8859-1'

如果更改编码,则每当调用r.text时,requests都将使用新的r.encoding的值。在任何情况下,你都可以应用特殊逻辑来确定内容的编码。例如,HTML和XML可以在其正文中指定其编码。在这种情况下,你应该使用r.content查找编码,然后设置r.encoding。这将允许你使用具有正确编码的r.text

requests还将在需要时使用自定义编码。如果你已经创建了自己的编码并将其注册到codecs模块,则可以简单地使用codec名称作为r.encoding的值,而requests将为你处理解码。

二进制响应内容

对于非文本请求,还可以以字节的形式访问响应体(当然,文本请求也可以):

>>> r.content
b'[{"id":"27581220674","type":"IssueCommentEvent","actor":{"id":327807...

requests会自动解码gzipdeflate传输编码。

如果安装了类似 brotlibrotlicffi的Brotil类库,Requets也会自动界面br传输编码

如果Brotli库(如[Brotli])为您自动解码br传输编码(https://pypi.org/project/brotli)或brotliffi已安装。

例如,可以使用以下代码,从请求返回的二进制数据创建图像:

from PIL import Image
from io import BytesIO
img = Image.open(BytesIO(r.content))

JSON响应内容

可使用内置的JSON解码器,处理JSON数据:

>>> import requests
>>> r = requests.get('https://api.github.com/events')
>>> r.json() # JSON
[{'id': '27609416600', 'type': 'PushEvent', ...

如果JSON解码失败,r.json()将抛出异常。例如,如果响应得到一个204(无内容),或者如果响应包含无效的JSON,则r.json()会抛出requests.exceptions.JSONDecodeError。此封装的异常可能会因为不同python版本和JSON序列化库可能引发的多个异常提供互操作性。

需要注意的是,调用r.json()的成功调用并不表示响应的成功。一些服务器可能会在失败的响应中返回JSON对象(例如,HTTP 500的错误详细信息)。这样的JSON将被解码并返回。要检查请求是否成功,请使用r.raise_for_status()或检查r.status_code

原始响应内容

可以通过访问r.raw访问服务器返回的原始socket响应。如果希望这样做,确保在初始请求中设置 stream=True:

>>> import requests
>>> r = requests.get('https://api.github.com/events', stream=True)
>>> r.raw
<urllib3.response.HTTPResponse object at 0x0000018DB1704D30>
>>> 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将处理很多你在直接使用Resort.raw时需要处理的事情。当流式传输下载时,以上是检索内容的首选和推荐方法。请注意,chunk_size可以自由调整为更适合你使用场景的数字。

注意

关于使用 Response.iter_contentResponse.raw的重要注意事项。 Response.iter_content将自动解码gzipdeflate传输编码。Response.raw是一个原始字节流--它不会转换响应内容。如果确实需要访问返回的字节,请使用Response.raw

自定义请求头

如果您想向请求中添加HTTP头,只需向headers参数传递一个dict即可,例如:

>>> url = 'https://api.github.com/some/endpoint'
>>> headers = {'user-agent': 'my-app/0.0.1'}
>>> r = requests.get(url, headers=headers)

注意:自定义请求头的优先级低于更具体的信息源。例如:

  • 如果在.netrc中指定了凭据,则使用headers=设置的Authorization请求头将被覆盖,而凭据又将被auth=参数覆盖。请求将在~/.netrc~/_netrcNETRC环境变量指定的路径处中搜索netrc文件。
  • 如果从主机重定向,将删除Authorization请求头。
  • Proxy-Authorization请求头将被URL中提供的代理凭据覆盖。
  • 当我们可以确定内容的长度时,将覆盖Content-Length请求头。

此外,请求根本不会根据指定的自定义请求头更改其行为。请求头仅是简单的传递到最终请求中。

注意:所有请求头值必须是字符串、字节字符串或unicode。虽然允许,但建议避免传递unicode请求头值。

更复杂的POST请求More complicated POST requests

通常,如果发送一些表单编码(form-encoded)的数据--就像一个HTML表单。为此,只需将字典传递给data参数即可。发送请求时,将自动对字典数据进行表单编码:

>>> import requests
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("https://httpbin.org/post", data=payload)
>>> r.text
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "key1": "value1", 
    "key2": "value2"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "23", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.27.1", 
    "X-Amzn-Trace-Id": "Root=1-6409fe3b-0cb4118319f09ab3187402bc"
  }, 
  "json": null, 
  "origin": "183.62.127.25", 
  "url": "https://httpbin.org/post"
}

data参数中,为每个键可以具有多个值。这可以通过将data设置为元组列表或以列表为值的字典来实现。当表单中有多个元素使用相同的键时,这特别有用:

>>> import requests
>>> 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)
>>> r1.text
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "key1": [
      "value1", 
      "value2"
    ]
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "23", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.27.1", 
    "X-Amzn-Trace-Id": "Root=1-6409ff49-11b8232a7cc81fc0290ec4c4"
  }, 
  "json": null, 
  "origin": "183.62.127.25", 
  "url": "https://httpbin.org/post"
}
>>> re.text == r2.text
True

有时,你可能想发送未经表单编码的数据,则需要传入string类型的数据,而不是dictstring数据将被直接提交。

例如,GitHub API v3接受JSON编码的POST/PATCH数据:

>>> import requests
>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(payload))

请注意,上述代码不会添加Content-Type请求头(特别是不会将其设置为application/json)。如果需要设置那个请求头('Content-Type': 'application/json,发送json请求体),并且不想自己对dict进行编码,你也可以直接使用json参数传递它,它将自动被编码:

>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, json=payload)

注意,如果提供了data,或者file参数,json 参数将被自动忽略。

提交Multipart-Encoded文件

Request让上传Multipart编码文件变得简单:

>>> import requests
>>> url = 'https://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')}
>>> r = requests.post(url, files=files)
>>> r.text
{
  "args": {}, 
  "data": "", 
  "files": {
    "file": "#!/usr/bin/env python\r\n# -*- coding:utf-8 -*-\r\n\r\n#!/usr/bin/env python\r\n# -*- coding:utf-8 -*-\r\n\r\nfrom multiprocessing import Pool\r\nfrom threading import Thread\r\nfrom concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor..."
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "3035", 
    "Content-Type": "multipart/form-data; boundary=9ef4437cb1e14427fcba1c42943509cb", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.27.1", 
    "X-Amzn-Trace-Id": "Root=1-640a03df-1a0a5ce972ce410378cda7a2"
  }, 
  "json": null, 
  "origin": "183.62.127.25", 
  "url": "https://httpbin.org/post"
}

可以显示的设置文件名称,内容类型,请求头:

>>> 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
{
  "args": {}, 
  "data": "", 
  "files": {
    "file": "data:application/vnd.ms-excel;base64,UEsDBBQAAAAAAHy8iFMAAAAAAA...=="
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "9667", 
    "Content-Type": "multipart/form-data; boundary=ff85e1018eb5232f7dcab2b2bc5ffa50", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.27.1", 
    "X-Amzn-Trace-Id": "Root=1-640def51-43cc213e33437a0e60255add"
  }, 
  "json": null, 
  "origin": "183.62.127.25", 
  "url": "https://httpbin.org/post"
}

如果想发送一些字符串,以文件的方式被接收:

>>> 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
{
  "args": {}, 
  "data": "", 
  "files": {
    "file": "some,data,to,send\nanother,row,to,send\n"
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "184", 
    "Content-Type": "multipart/form-data; boundary=2bfe430e025860528e29c893a09f1198", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.27.1", 
    "X-Amzn-Trace-Id": "Root=1-640df132-247947ca699e9da35c588f2d"
  }, 
  "json": null, 
  "origin": "183.62.127.25", 
  "url": "https://httpbin.org/post"
}

如果你将一个非常大的文件作为multipart/form-data请求提交,你可能需要流式传输该请求。默认情况下,requests不支持此功能,但有一个单独的包支持此功能——requests toolbelt。阅读toolbelt文档获取有关如何使用它的详细信息。

要在一个请求中发送多个文件,请参阅高级章节。

警告

强烈建议以二进制模式打开文件。这是因为requests可能会尝试为你提供Content-Length请求头,如果这样做,该请求头值将被设置为文件中的字节数。如果以文本模式打开文件,可能会发生错误。

响应状态码

>>> import requests
>>> r = requests.get('https://httpbin.org/get')
>>> r.status_code
200

以便于参考,requests还附带一个内置的状态代码查找对象:

>>> r = requests.get('https://httpbin.org/get')
>>> r.status_code == requests.codes.ok
True

如果请求出错4XX客户端错误或5XX服务器错误响应),我们可以使用response.raise_for_status()抛出错误:

>>> import requests
>>> 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 "D:/codePojects/test.py", line 12, in <module>
    bad_r.raise_for_status()
  File "D:\Program Files (x86)\python36\lib\site-packages\requests\models.py", line 960, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url: https://httpbin.org/status/404

但是,如果r.status_code200, raise_for_status() 将返回None

>>> r.raise_for_status()
None

响应头

>>> r.headers
{
    'content-encoding': 'gzip',
    'transfer-encoding': 'chunked',
    'connection': 'close',
    'server': 'nginx/1.0.4',
    'x-runtime': '148ms',
    'etag': '"e1ca502697e5c9317743dc078f67693f"',
    'content-type': 'application/json'
}

根据RFC 7230, HTTP请求头大小写不敏感,所以,我们可以使用任何大写。因此,我们可以使用任意大小写来访问请求头:

>>> r.headers['Content-Type']
'application/json'
>>> r.headers.get('content-type')
'application/json'

Cookies

如果响应包含Cookie,可以快速访问它们:

>>> url = 'http://example.com/some/cookie/setting/url'
>>> r = requests.get(url)
>>> r.cookies['example_cookie_name'] # 如果存在名为 example_cookie_name的cookie的话
'example_cookie_value'

可以使用cookies 参数将cookie发送给服务器:

>>> url = 'https://httpbin.org/cookies'
>>> cookies = dict(cookies_are='working')
>>> r = requests.get(url, cookies=cookies)
>>> r.text
'{\n  "cookies": {\n    "cookies_are": "working"\n  }\n}\n'

Cookies are returned in a RequestsCookieJar, which acts like a dict but also offers a more complete interface, suitable for use over multiple domains or paths. Cookie jars can also be passed in to requests:

返回的Cookie存储在RequestsCookieJar中,其作用类似于dict,同时提供了一个更完整的接口,适合在多个域或路径上使用。Cookie jar也可以传递给请求:

>>> jar = requests.cookies.RequestsCookieJar()
>>> jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
Cookie(version=0, name='tasty_cookie', value='yum', port=None, port_specified=False, domain='httpbin.org', domain_specified=True, domain_initial_dot=False, path='/cookies', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False)
>>> jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
Cookie(version=0, name='gross_cookie', value='blech', port=None, port_specified=False, domain='httpbin.org', domain_specified=True, domain_initial_dot=False, path='/elsewhere', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False)
>>> url = 'https://httpbin.org/cookies'
>>> r = requests.get(url, cookies=jar)
>>> r.text
'{"cookies": {"tasty_cookie": "yum"}}'

重定向与history

默认情况下,requests将对除HEAD之外的所有请求执行位置重定向(如果需要重定向的话)。

我们可以使用Response对象的history属性来跟踪重定向。

Response.history列表包含为完成请求而创建的Response对象。列表按响应的先后顺序排序。

例如,Gitee将所有HTTP请求重定向到HTTPS:

>>> r = requests.get('http://gitee.com/')
>>> r.url
'https://gitee.com/'
>>> r.status_code
200
>>> r.history
[<Response [302]>]

如果使用HEAD,GET, OPTIONSPOSTPUTPATCH 或者DELETE,可以使用 allow_redirects参数禁止重定向:

>>> r = requests.get('http://gitee.com/', allow_redirects=False)
>>> r.status_code
302
>>> r.history
[]
>>> r = requests.head('http://gitee.com/', allow_redirects=False)
>>> r.url
'http://gitee.com/'
>>> r.status_code
302
>>> r.history
[]
>>> r = requests.head('http://gitee.com/', allow_redirects=True)
>>> r.status_code
200
>>> r.url
'https://gitee.com/'
>>> r.history
[<Response [302]>]
目录
相关文章
|
1天前
|
SQL 并行计算 API
Dask是一个用于并行计算的Python库,它提供了类似于Pandas和NumPy的API,但能够在大型数据集上进行并行计算。
Dask是一个用于并行计算的Python库,它提供了类似于Pandas和NumPy的API,但能够在大型数据集上进行并行计算。
19 9
|
1天前
|
机器学习/深度学习 人工智能 数据挖掘
Numba是一个Python库,用于对Python代码进行即时(JIT)编译,以便在硬件上高效执行。
Numba是一个Python库,用于对Python代码进行即时(JIT)编译,以便在硬件上高效执行。
20 9
|
1天前
|
网络协议 安全 Shell
`nmap`是一个开源的网络扫描工具,用于发现网络上的设备和服务。Python的`python-nmap`库允许我们在Python脚本中直接使用`nmap`的功能。
`nmap`是一个开源的网络扫描工具,用于发现网络上的设备和服务。Python的`python-nmap`库允许我们在Python脚本中直接使用`nmap`的功能。
22 7
|
1天前
|
机器人 Shell 开发者
`roslibpy`是一个Python库,它允许非ROS(Robot Operating System)环境(如Web浏览器、移动应用等)与ROS环境进行交互。通过使用`roslibpy`,开发者可以编写Python代码来远程控制ROS节点,发布和订阅话题,以及调用服务。
`roslibpy`是一个Python库,它允许非ROS(Robot Operating System)环境(如Web浏览器、移动应用等)与ROS环境进行交互。通过使用`roslibpy`,开发者可以编写Python代码来远程控制ROS节点,发布和订阅话题,以及调用服务。
18 8
|
1天前
|
自然语言处理 程序员 编译器
`pylatex`是一个Python库,用于生成LaTeX文档。LaTeX是一种用于高质量排版和打印的文档准备系统,特别适用于科学、技术和数学文档。
`pylatex`是一个Python库,用于生成LaTeX文档。LaTeX是一种用于高质量排版和打印的文档准备系统,特别适用于科学、技术和数学文档。
11 2
|
1天前
|
存储 搜索推荐 算法
`surprise`是一个用于构建和分析推荐系统的Python库。
`surprise`是一个用于构建和分析推荐系统的Python库。
11 0
|
1天前
|
机器学习/深度学习 PyTorch TensorFlow
在深度学习中,数据增强是一种常用的技术,用于通过增加训练数据的多样性来提高模型的泛化能力。`albumentations`是一个强大的Python库,用于图像增强,支持多种图像变换操作,并且可以与深度学习框架(如PyTorch、TensorFlow等)无缝集成。
在深度学习中,数据增强是一种常用的技术,用于通过增加训练数据的多样性来提高模型的泛化能力。`albumentations`是一个强大的Python库,用于图像增强,支持多种图像变换操作,并且可以与深度学习框架(如PyTorch、TensorFlow等)无缝集成。
8 0
|
1天前
|
Python
确保你已经安装了`python-barcode`库。如果没有,可以通过pip来安装:
确保你已经安装了`python-barcode`库。如果没有,可以通过pip来安装:
6 0
|
26天前
|
开发工具 git Python
安装和使用`libnum`是一个用于数字理论函数的Python库
【6月更文挑战第19天】`libnum`是Python的数字理论函数库。安装可通过`git clone`,进入目录后运行`python setup.py install`,也可用`pip install libnum`。示例:使用`int_to_hex`将十进制数42转换为十六进制字符串&#39;2a&#39;。注意,信息可能已过时,应查最新文档以确保准确性。如遇问题,参考GitHub仓库或寻求社区帮助。
24 1
|
Linux Python
不可出外网的主机如何快速、方便、优雅的安装Python库?
不可出外网的主机如何快速、方便、优雅的安装Python库?
479 0
不可出外网的主机如何快速、方便、优雅的安装Python库?