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]>]
目录
相关文章
|
7天前
|
调度 开发者 Python
Python中的异步编程:理解asyncio库
在Python的世界里,异步编程是一种高效处理I/O密集型任务的方法。本文将深入探讨Python的asyncio库,它是实现异步编程的核心。我们将从asyncio的基本概念出发,逐步解析事件循环、协程、任务和期货的概念,并通过实例展示如何使用asyncio来编写异步代码。不同于传统的同步编程,异步编程能够让程序在等待I/O操作完成时释放资源去处理其他任务,从而提高程序的整体效率和响应速度。
|
4天前
|
数据库 Python
异步编程不再难!Python asyncio库实战,让你的代码流畅如丝!
在编程中,随着应用复杂度的提升,对并发和异步处理的需求日益增长。Python的asyncio库通过async和await关键字,简化了异步编程,使其变得流畅高效。本文将通过实战示例,介绍异步编程的基本概念、如何使用asyncio编写异步代码以及处理多个异步任务的方法,帮助你掌握异步编程技巧,提高代码性能。
13 4
|
4天前
|
API 数据处理 Python
探秘Python并发新世界:asyncio库,让你的代码并发更优雅!
在Python编程中,随着网络应用和数据处理需求的增长,并发编程变得愈发重要。asyncio库作为Python 3.4及以上版本的标准库,以其简洁的API和强大的异步编程能力,成为提升性能和优化资源利用的关键工具。本文介绍了asyncio的基本概念、异步函数的定义与使用、并发控制和资源管理等核心功能,通过具体示例展示了如何高效地编写并发代码。
12 2
|
9天前
|
数据采集 JSON 测试技术
Python爬虫神器requests库的使用
在现代编程中,网络请求是必不可少的部分。本文详细介绍 Python 的 requests 库,一个功能强大且易用的 HTTP 请求库。内容涵盖安装、基本功能(如发送 GET 和 POST 请求、设置请求头、处理响应)、高级功能(如会话管理和文件上传)以及实际应用场景。通过本文,你将全面掌握 requests 库的使用方法。🚀🌟
30 7
|
9天前
|
机器学习/深度学习 数据采集 算法
Python机器学习:Scikit-learn库的高效使用技巧
【10月更文挑战第28天】Scikit-learn 是 Python 中最受欢迎的机器学习库之一,以其简洁的 API、丰富的算法和良好的文档支持而受到开发者喜爱。本文介绍了 Scikit-learn 的高效使用技巧,包括数据预处理(如使用 Pipeline 和 ColumnTransformer)、模型选择与评估(如交叉验证和 GridSearchCV)以及模型持久化(如使用 joblib)。通过这些技巧,你可以在机器学习项目中事半功倍。
19 3
|
2天前
|
数据采集 数据可视化 数据挖掘
利用Python进行数据分析:Pandas库实战指南
利用Python进行数据分析:Pandas库实战指南
|
9天前
|
文字识别 自然语言处理 API
Python中的文字识别利器:pytesseract库
`pytesseract` 是一个基于 Google Tesseract-OCR 引擎的 Python 库,能够从图像中提取文字,支持多种语言,易于使用且兼容性强。本文介绍了 `pytesseract` 的安装、基本功能、高级特性和实际应用场景,帮助读者快速掌握 OCR 技术。
28 0
|
1月前
|
存储 算法 API
Python学习五:函数、参数(必选、可选、可变)、变量、lambda表达式、内置函数总结、案例
这篇文章是关于Python函数、参数、变量、lambda表达式、内置函数的详细总结,包含了基础知识点和相关作业练习。
24 0
|
5月前
|
存储 Python Windows
【Python学习篇】Python实验小练习——函数(十)
【Python学习篇】Python实验小练习——函数(十)
31 1
|
5月前
|
存储 Python
【Python学习篇】Python——函数(九)
【Python学习篇】Python——函数(九)
44 1