python爬虫04 | Reuqests库快速入门,干穿urllib

Requests库简介

什么是Requests库

Requests是一个简单易用的HTTP库,用于Python编程语言。它允许你发送各种HTTP请求来与服务器进行交互。Requests库以其简洁的API和人性化的设计而广受开发者喜爱,使得进行网络请求变得直观和容易。

Requests库最初由Kenneth Reitz开发,现在已经成为Python标准库之外最流行的HTTP客户端库之一。它建立在Python的urllib3库之上,提供了一个更高层次的接口来处理HTTP请求。

Requests库的主要特点和优势

  1. 人性化的API:Requests库的API设计直观,易于理解和使用。例如,发送一个GET请求只需要一行代码。

  2. 国际化支持:Requests支持国际域名和非ASCII字符,可以无缝处理Unicode URL。

  3. 连接保持和复用:Requests使用urllib3的连接池功能,可以自动重用HTTP连接,提高请求效率。

  4. 会话管理:通过requests.Session对象,可以跨请求保持某些参数和Cookie,实现会话管理。

  5. JSON支持:Requests提供了便捷的JSON请求和响应处理功能,可以自动将JSON响应解析为Python字典。

  6. 表单和文件上传:可以轻松地上传文件和表单数据,支持多文件上传。

  7. 流式下载:支持流式上传和下载,适合处理大文件。

  8. SSL/TLS支持:Requests支持HTTPS请求,可以验证服务器SSL证书。

  9. 自动内容解码:自动处理gzip和deflate压缩的响应内容。

  10. 异常处理:Requests定义了一套自己的异常体系,可以捕获并处理连接错误、超时错误等。

  11. Cookie处理:可以自动处理Cookie,也可以手动设置和发送Cookie。

  12. 代理支持:支持设置HTTP代理和SOCKS代理。

  13. 自定义请求头:可以方便地添加或修改请求头。

  14. 社区活跃:拥有活跃的社区和丰富的文档,易于获取帮助和资源。

  15. 跨平台: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

项目列表作为值传递的python代码运行结果

响应内容

我们可以读取服务器响应的内容。考虑 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 显式引发的所有异常都继承 。

结束~,这就是快速入门的全部内容啦

Ending

  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值