• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

在 Python 中使用请求模块

Requests是一个 python 模块,可用于发送各种 HTTP 请求。它是一个易于使用的库,具有许多功能,从在 URL 中传递参数到发送自定义标头和 SSL 验证。在本教程中,您将学习如何使用此库在 Python 中发送简单的 HTTP 请求。

您可以将 Requests 与 Python 版本 2.6–2.7 和 3.3–3.6 一起使用。在继续之前,您应该知道 Requests 是一个外部模块,因此您必须先安装它才能尝试本教程中的示例。您可以通过在终端中运行以下命令来安装它:

pip install requests

安装模块后,您可以使用以下命令导入它来验证它是否已成功安装:

import requests

如果安装成功,您将不会看到任何错误消息。

发出 GET 请求

使用 Requests 发送 HTTP 请求非常容易。您首先导入模块,然后发出请求。这是一个例子:

import requests
req = requests.get('https://weixiaolive.com/')

关于我们请求的所有信息现在都存储在一个名为 的 Response 对象中req。例如,您可以使用该req.encoding属性获取网页的编码。您还可以使用该req.status_code属性获取请求的状态代码。

req.encoding     # returns 'utf-8' 
req.status_code  # returns 200

您可以使用 访问服务器发回的 cookie req.cookies。同样,您可以使用req.headers. 该req.headers属性返回不区分大小写的响应标头字典。这意味着req.headers['Content-Length'],req.headers['content-length']和req.headers['CONTENT-LENGTH']都会返回'Content-Length'响应头的值。

您可以检查响应是否是可以使用该req.is_redirect属性自动处理的格式正确的 HTTP 重定向。它将返回True或False基于响应。req.elapsed您还可以使用该属性获取发送请求和取回响应之间经过的时间。

get()由于各种原因(包括重定向),您最初传递给函数的 URL 可能与响应的最终 URL 不同。要查看最终响应 URL,您可以使用该req.url属性。

import requests
req = requests.get('https://www.weixiaolive.com/')
req.encoding      # returns 'utf-8' 
req.status_code   # returns 200 
req.elapsed       # returns datetime.timedelta(0, 1, 666890) 
req.url           # returns 'https://weixiaolive.com/' 
req.history      
# returns [<Response [301]>, <Response [301]>] 
req.headers['Content-Type']
# returns 'text/html; charset=utf-8'

获取有关您正在访问的网页的所有这些信息很好,但您很可能想要访问实际内容。如果您正在访问的内容是文本,您可以使用该req.text属性来访问它。然后将内容解析为 unicode。您可以使用该req.encoding属性传递用于解码文本的编码。

对于非文本响应,您可以使用req.content. 该模块将自动解码gzip和deflate传输编码。当您处理媒体文件时,这会很有帮助。同样,您可以访问响应的 json 编码内容(如果存在),使用req.json().

您还可以使用从服务器获取原始响应req.raw。请记住,您必须传递stream=True请求才能获得原始响应。

您使用 Requests 模块从 Internet 下载的某些文件可能非常大。在这种情况下,一次将整个响应或文件加载到内存中是不明智的。iter_content(chunk_size = 1, decode_unicode=False)您可以使用该方法分段或分块下载文件。

此方法一次迭代以chunk_size字节数为单位的响应数据。当stream=True已根据请求设置时,此方法将避免一次将整个文件读入内存以进行大量响应。该chunk_size参数可以是整数或None. 当设置为整数值时,chunk_size确定应读入内存的字节数。

当chunk_size设置为None和stream设置为True时,数据将在到达时以接收到的任何大小的块读取。当chunk_size设置为None和stream设置为 时False,所有数据将作为单个块返回。

让我们使用 Requests 模块下载一些蘑菇的图片。这是实际图像:

在 Python 中使用请求模块  第1张

这是您需要的代码:

import requests
req = requests.get('path/to/mushrooms.jpg', stream=True)
req.raise_for_status()
with open('mushrooms.jpg', 'wb') as fd:
    for chunk in req.iter_content(chunk_size=50000):
        print('Received a Chunk')
        fd.write(chunk)

这'path/to/mushrooms.jpg'是实际的图像 URL。您可以将任何其他图像的 URL 放在这里以下载其他内容。给定的图像文件大小为 162kb,您已将其设置chunk_size为 50,000 字节。这意味着“Received a Chunk”消息应该在终端中打印四次。最后一个块的大小将仅为 32350 字节,因为在前三个迭代之后仍要接收的文件部分是 32350 字节。

您也可以用类似的方式下载视频。chunk_size我们可以简单地将它的值设置为 ,而不是指定一个固定值,None然后视频将以交付的任何块大小下载。以下代码片段将从 Mixkit下载高速公路的这段视频:

import requests
req = requests.get('path/to/highway/video.mp4', stream=True)
req.raise_for_status()
with open('highway.mp4', 'wb') as fd:
    for chunk in req.iter_content(chunk_size=None):
        print('Received a Chunk')
        fd.write(chunk)

尝试运行代码,您会看到视频作为单个块下载。

stream如果您决定使用该参数,则应记住几件事。响应主体的下载被推迟,直到您使用该content属性实际访问它的值。这样,您可以避免在某个标头值似乎不正确时下载文件。

还请记住,您在将流的值设置为 时启动的任何连接True都不会关闭,除非您使用所有数据或使用该close()方法。一种确保连接始终关闭的更好方法,即使您只阅读了部分响应,也就是在with如下所示的语句中发出您的请求:

import requests
with requests.get('path/to/highway/video.mp4', stream=True) as rq:
    with open('highway.mp4', 'wb') as fd:
        for chunk in rq.iter_content(chunk_size=None):
            print('Received a Chunk')
            fd.write(chunk)

由于我们之前下载的镜像文件比较小,您也可以使用以下代码一次性下载:

import requests
req = requests.get('path/to/mushrooms.jpg')
req.raise_for_status()
with open('mushrooms.jpg', 'wb') as fd:
    fd.write(req.content)

我们跳过了参数值的设置,stream因此它已被False默认设置为。这意味着将立即下载所有响应内容。在属性的帮助下,响应的内容被捕获为二进制数据content。

Requests 还允许您在 URL 中传递参数。当您在网页上搜索特定图像或教程等某些结果时,这会很有帮助。params您可以使用GET 请求中的关键字将这些查询字符串作为字符串字典提供。这是一个例子:

import requests
query = {'q': 'Forest', 'order': 'popular', 'min_width': '800', 'min_height': '600'}
req = requests.get('https://pixabay.com/en/photos/', params=query)
req.url
# returns 'https://pixabay.com/en/photos/?order=popular&min_height=600&q=Forest&min_width=800'

发出 post 请求

发出 POST 请求与发出 GET 请求一样简单。您只需使用该post()方法而不是get(). 当您自动提交表单时,这会很有用。例如,以下代码将向httpbin.org域发送 post 请求并将响应 JSON 输出为文本。

import requests
req = requests.post('https://httpbin.org/post', data = {'username': 'monty', 'password': 'something_complicated'})
req.raise_for_status()
print(req.text)
''' 
{ 
"args": {}, 
"data": "", 
"files": {}, 
"form": { 
"password": "something_complicated", 
"username": "monty" 
}, 
"headers": { 
"Accept": "*/*", 
"Accept-Encoding": "gzip, deflate", 
"Content-Length": "45", 
"Content-Type": "application/x-www-form-urlencoded", 
"Host": "httpbin.org", 
"User-Agent": "python-requests/2.28.1", 
"X-Amzn-Trace-Id": "Root=1-63ad437e-67f5db6a161314861484f2eb" 
}, 
"json": null, 
"origin": "YOUR.IP.ADDRESS", 
"url": "https://httpbin.org/post" 
} 
'''

您可以将这些 POST 请求发送到任何可以处理它们的 URL。例如,我的一个朋友创建了一个网页,用户可以在其中输入一个词并使用 api 获取其含义以及发音和其他信息。我们可以使用查询词向 URL 发出 POST 请求,然后将结果保存为.html页面,如下所示:

import requests
word = 'Pulchritudinous'
filename = word.lower() + '.html'
req = requests.post('https://tutorialio.com/tools/dictionary.php', data = {'query': word})
req.raise_for_status()
with open(filename, 'wb') as fd:
    fd.write(req.content)

执行上面的代码,它会返回一个包含单词信息的页面,如下图所示。

在 Python 中使用请求模块  第2张

发送 Cookie 和标头

如前所述,您可以使用 和 访问服务器发回给您的 cookie 和标req.cookies头req.headers。Requests 还允许您在请求中发送您自己的自定义 cookie 和标头。当您想要为您的请求设置自定义用户代理时,这会很有帮助。

要将 HTTP 标头添加到请求中,您只需将它们传递给dict参数即可headers。dict同样,您也可以使用传递给cookies参数的方式将自己的 cookie 发送到服务器。

import requests
url = 'http://some-domain.com/set/cookies/headers'
headers = {'user-agent': 'your-own-user-agent/0.0.1'}
cookies = {'visit-month': 'February'}
req = requests.get(url, headers=headers, cookies=cookies)

Cookie 也可以在 Cookie Jar 中传递。它们提供了一个更完整的界面,允许您通过多个路径使用这些 cookie。这是一个例子:

import requests
jar = requests.cookies.RequestsCookieJar()
jar.set('first_cookie', 'first', domain='httpbin.org', path='/cookies')
jar.set('second_cookie', 'second', domain='httpbin.org', path='/extra')
jar.set('third_cookie', 'third', domain='httpbin.org', path='/cookies')
url = 'http://httpbin.org/cookies'
req = requests.get(url, cookies=jar)
req.text
# returns '{ "cookies": { "first_cookie": "first", "third_cookie": "third" }}'

会话对象

有时在多个请求中保留某些参数很有用。Session 对象正是这样做的。例如,它将在使用同一会话发出的所有请求中保留 cookie 数据。Session 对象使用 urllib3 的连接池。这意味着底层 TCP 连接将被重复用于对同一主机发出的所有请求。这可以显着提高性能。您还可以将 Requests 对象的方法与 Session 对象一起使用。

以下是使用和不使用会话发送的多个请求的示例:

import requests
reqOne = requests.get('https://weixiaolive.com/')
reqOne.cookies['_tuts_session']
#returns 'cc118d94a84f0ea37c64f14dd868a175' 
reqTwo = requests.get('https://code.weixiaolive.com/tutorials')
reqTwo.cookies['_tuts_session']
#returns '3775e1f1d7f3448e25881dfc35b8a69a' 
ssnOne = requests.Session()
ssnOne.get('https://weixiaolive.com/')
ssnOne.cookies['_tuts_session']
#returns '4c3dd2f41d2362108fbb191448eab3b4' 
reqThree = ssnOne.get('https://code.weixiaolive.com/tutorials')
reqThree.cookies['_tuts_session']
#returns '4c3dd2f41d2362108fbb191448eab3b4'

可以看到,session cookie在第一次和第二次请求中有不同的值,但是当我们使用Session对象时它有相同的值。当您尝试此代码时,您将获得不同的值,但在您的情况下,使用会话对象发出的请求的 cookie 也将具有相同的值。

当您想在所有请求中发送相同的数据时,会话也很有用。例如,如果您决定将带有所有请求的 cookie 或用户代理标头发送到给定域,则可以使用 Session 对象。这是一个例子:

import requests
ssn = requests.Session()
ssn.cookies.update({'visit-month': 'February'})
reqOne = ssn.get('http://httpbin.org/cookies')
print(reqOne.text)
# prints information about "visit-month" cookie 
reqTwo = ssn.get('http://httpbin.org/cookies', cookies={'visit-year': '2017'})
print(reqTwo.text)
# prints information about "visit-month" and "visit-year" cookie 
reqThree = ssn.get('http://httpbin.org/cookies')
print(reqThree.text)
# prints information about "visit-month" cookie

如您所见,"visit-month"会话 cookie 随所有三个请求一起发送。但是,"visit-year"cookie 仅在第二次请求期间发送。第三个请求中也没有提到"vist-year"cookie。这证实了一个事实,即个人请求上的 cookie 或其他数据集不会与其他会话请求一起发送。

结论

本教程中讨论的概念应该可以帮助您通过传递特定的标头、cookie 或查询字符串来向服务器发出基本请求。当您尝试抓取某些网页以获取信息时,这将非常方便。现在,一旦您找出 URL 中的模式,您还应该能够从不同的网站自动下载音乐文件和壁纸。


文章目录
  • 发出 GET 请求
  • 发出 post 请求
  • 发送 Cookie 和标头
  • 会话对象
  • 结论
  • 发表评论