Python爬虫(二)- Requests 高级使用教程

文章目录

  • 前言
  • 一、Session 对象
    • 1. 简介
    • 2. 跨请求保持 Cookie
    • 3. 设置缺省数据
    • 4. 方法级别参数不被跨请求保持
    • 5. 会话作为上下文管理器
    • 6. 移除字典参数中的值
  • 二、请求与响应
    • 1. 请求与响应对象
      • 1.1 获取响应头信息
      • 1.2 获取发送到服务器的请求头信息
  • 三、SSL 证书验证
    • 1. 忽略 SSL 证书验证
  • 四、流式上传和请求
    • 1. 流式上传
    • 2. 流式请求
      • 2.1 流式请求和普通请求的区别
      • 2.2 示例
        • 2.2.1 iter_lines() 使用
        • 2.2.2 iter_content() 使用
  • 五、代理
    • 1. 获取免费代理地址
    • 2. 使用代理配置单个请求
    • 3. 使用代理池
    • 4. 使用 HTTP Basic Auth 的代理
    • 5. 针对特定主机或连接方式设置代理
  • 六、编码方式
    • 1. 编码方式处理
      • 1.1 自动检测编码
      • 1.2 手动设置编码
      • 1.3 使用原始字节数据
  • 七、身份认证
    • 1. 基本身份认证 (HTTP Basic Auth)


前言

在现代网络应用中,HTTP 请求和响应的处理是至关重要的。Python 的 requests 库以其简洁易用的接口,成为了开发者进行网络请求的首选工具。无论是简单的 GET 请求,还是复杂的身份认证、会话管理、代理设置,requests 都能轻松应对。本文将深入探讨 requests 库的各个方面,包括 Session 对象的使用、请求与响应的处理、SSL 证书验证、流式上传和请求、代理配置、编码方式处理以及身份认证等。


一、Session 对象

1. 简介

Session 对象允许跨多个请求保持某些参数不变。它在同一个 Session 实例发出的所有请求之间保持 cookie,并利用 urllib3 的连接池功能来重用底层的 TCP 连接,从而为向同一主机发送的多个请求提供显著的性能提升。

主要特性:

  • 所有 Requests API 方法:Session 对象拥有主要的 Requests API 的所有方法。
  • 持久性 Cookie 和 Headers:可以跨请求保持某些数据,如认证信息和自定义头部。
  • 连接池复用:对于同一主机的多次请求,能够复用TCP连接,提高效率。

2. 跨请求保持 Cookie

import requests# 创建一个会话对象
session = requests.session()# 设置 Cookie:通过会话发送 GET 请求,设置一个名为 sessioncookie 的 cookie,值为 123456789。
session.get('http://httpbin.org/cookies/set/sessioncookie/123456789')# 获取 Cookie:再次使用同一个会话发送 GET 请求,获取当前会话中的所有 cookies。
response = session.get("http://httpbin.org/cookies")# 打印服务器返回的 cookie 信息
print(response.text)

打印的结果为:

{"cookies": {"sessioncookie": "123456789"}
}

3. 设置缺省数据

通过为 Session 对象的属性提供数据,可以为请求方法提供缺省数据,例如认证信息或头部信息。

import requests# 创建一个会话对象
session = requests.session()# 设置会话的认证信息,用户名为 'user',密码为 'pass'
session.auth = ('user', 'pass')# 更新会话头部信息,添加自定义头 'x-test',其值为 'true'
session.headers.update({'x-test': 'true'})# 发送 GET 请求到 http://httpbin.org/headers,同时在此请求中添加另一个自定义头 'x-test2'
response = session.get('http://httpbin.org/headers', headers={'x-test2': 'true'})# 打印服务器返回的响应内容,以查看请求头和其他信息
print(response.text)

打印的结果为:

在这里插入图片描述

任何传递给请求方法的字典都会与已设置会话层数据合并,方法层的参数覆盖会话的参数。

4. 方法级别参数不被跨请求保持

就算使用了 Session,方法级别的参数也不会被跨请求保持。

import requests# 创建一个会话对象
session = requests.session()# 只有第一个请求发送 cookie
response = session.get('http://httpbin.org/cookies', cookies={'from-my': 'browser'})
print(response.text)# 第二个请求没有 cookie
response = session.get('http://httpbin.org/cookies')
print(response.text)

打印的结果为:

{"cookies": {"from-my": "browser"}
}{"cookies": {}
}

从打印的结果可以看出,重复对同一个地址发起访问,第一个请求设置的 cookie 并没有被保存,所以第二个请求中没有 cookie,也就是说就算使用了 Session,方法级别的参数也不会被跨请求保持。

5. 会话作为上下文管理器

为了确保会话在完成后能被正确关闭,可以使用它作为上下文管理器。这样就能确保 with 区块退出后会话能被关闭,即使发生了异常也一样。

import requestswith requests.session() as session:response = session.get('http://httpbin.org/cookies/set/sessioncookie/123456789')print(response.text)

打印的结果为:

{"cookies": {"sessioncookie": "123456789"}
}

6. 移除字典参数中的值

可以通过在方法级别的参数中将键的值设置为 None 来移除会话层字典参数中的某个键,从而让该键不会被发送。


二、请求与响应

1. 请求与响应对象

任何时候当你调用 requests.get() 或其他类似方法时,实际上你在执行两个主要操作:构建一个 Request 对象以向服务器请求或查询资源;以及接收一个从服务器返回的 Response 对象。这个 Response 对象包含了来自服务器的所有信息,并且也包含了你最初创建的 Request 对象。

1.1 获取响应头信息

import requestsurl = 'http://www.baidu.com'response = requests.get(url)print(response.headers)

打印的结果为:

在这里插入图片描述

1.2 获取发送到服务器的请求头信息

import requestsurl = 'http://www.baidu.com'response = requests.get(url)print(response.request.headers)

打印的结果为:

{'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

三、SSL 证书验证

Requests 可以为 HTTPS 请求验证 SSL 证书,就像 web 浏览器一样。SSL 验证默认是开启的,如果证书验证失败,Requests 会抛出 SSLError

1. 忽略 SSL 证书验证

在某些特殊情况下,比如在测试环境中或者你信任但证书不受信任的情况下,你可能想要忽略 SSL 证书验证。

import requests
from urllib3.exceptions import InsecureRequestWarningurl = 'https://example.com'# 禁用不安全请求警告
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)# 忽略 SSL 证书验证
response = requests.get(url, verify=False)
print(response.status_code)

四、流式上传和请求

1. 流式上传

Requests支持流式上传,这允许你发送大的数据流或文件而无需先把它们读入内存。要使用流式上传,仅需为你的请求体提供一个类文件对象即可。

with open('massive-body', 'rb') as f:requests.post('http://some.url/streamed', data=f)

data=f:这里将文件对象 f 直接赋值给了 data 参数。这意味着 requests 将会逐块读取文件内容,并通过 HTTP 请求进行流式传输。这样做的好处是,即使文件非常大,也不会占用过多的内存,因为数据是一部分一部分地发送出去的。

2. 流式请求

2.1 流式请求和普通请求的区别

流式请求(Streaming Requests)和普通请求(Non-streaming Requests)是使用 requests 库进行 HTTP 请求的两种不同方式,它们在处理响应内容时有着显著的区别。下面我们将详细介绍这两种请求类型,并说明其适用场景。

普通请求

  • 一次性读取:当发起一个普通的 GET 或 POST 请求时,requests 会立即将整个响应体下载到内存中。这意味着如果响应体很大,可能会占用大量的内存。

  • 简单易用:对于小文件或轻量级的数据交换,这种方式非常方便,因为它不需要额外的配置就可以直接获取完整的响应内容。

流式请求

  • 逐块读取:通过设置参数 stream=True,你可以告诉 requests 不要立即下载整个响应体。相反,它会在需要时逐步从网络流中读取数据。这允许你处理超大文件或长时间运行的数据流,而不会一次性占用大量内存。

  • 节省资源:流式请求非常适合于处理大型文件、长连接 API 响应或者实时数据流,因为你可以一边接收数据一边处理,从而有效管理资源。

  • 更复杂的逻辑:由于数据是分块到达的,你需要编写额外的代码来处理这些数据块,例如将它们写入文件或进行增量处理。

流式请求迭代器方法

  • iter_content():以字节为单位返回响应内容的迭代器。可以指定 chunk_size 参数来控制每次读取的大小。

  • iter_lines():以行为单位返回响应内容的迭代器,适用于按行处理的文本响应。

2.2 示例

2.2.1 iter_lines() 使用
import json
import requests# 发送 GET 请求到指定的 URL,使用 stream=True 以便逐行读取响应内容
response = requests.get('http://httpbin.org/stream/20', stream=True)# 检查响应的编码,如果未设置,则将其设置为 'utf-8'
if response.encoding is None:response.encoding = 'utf-8'# 逐行迭代响应内容,使用 decode_unicode=True 将内容解码为字符串
for line in response.iter_lines(decode_unicode=True):# 检查当前行是否非空if line:# 将 JSON 格式的字符串解析为 Python 对象并打印print(json.loads(line))

iter_lines 不保证重进入时的安全性。多次调用该方法 会导致部分收到的数据丢失。如果要在多处调用它,应该使用生成的迭代器对象。

import json
import requests# 发送 GET 请求到指定的 URL,使用 stream=True 以便逐行读取响应内容
response = requests.get('http://httpbin.org/stream/20', stream=True)# 检查响应的编码,如果未设置,则将其设置为 'utf-8'
if response.encoding is None:response.encoding = 'utf-8'# 使用 iter_lines() 方法创建一个可迭代的行生成器
lines = response.iter_lines()# 使用 next() 函数获取并跳过第一行,first_line 存储的是第一行的内容
first_line = next(lines)# 逐行处理剩余的响应内容
for line in lines:# 打印当前行的内容print(json.loads(line))
2.2.2 iter_content() 使用
import requests# 定义要请求的 URL
url = 'https://api.github.com/events'# 发送 GET 请求到指定的 URL,使用 stream=True 以便逐块下载内容
response = requests.get(url=url, stream=True)# 打开一个文件以写入二进制数据,路径为 'D:\\demo.txt'
with open('D:\\demo.txt', 'wb') as fd:# 遍历响应内容,按块读取数据,块大小为 8192 字节for chunk in response.iter_content(chunk_size=8192):# 将读取的块写入文件fd.write(chunk)

五、代理

1. 获取免费代理地址

点击连接访问快代理网站:https://www.kuaidaili.com/free/inha/

如下图所示,可以获取免费的代理。

在这里插入图片描述

2. 使用代理配置单个请求

如果需要使用代理,可以通过为任意请求方法提供 proxies 参数来配置单个请求。

import requestsurl = 'http://www.baidu.com'proxies = {"http": "47.119.22.92:8008"
}# 发送 GET 请求,并使用指定的代理
response = requests.get(url=url, proxies=proxies)print(response.status_code)

打印的结果为:

200

3. 使用代理池

在进行网络请求时,特别是当你需要频繁地访问某个网站或希望隐藏自己的真实 IP 地址时,使用代理池可以提高请求的成功率和匿名性。通过每次发送请求时从多个代理服务器中随机选择一个来发送,可以分散请求源,减少被目标网站封禁的风险。

import randomimport requestsurl = 'http://www.baidu.com'# 使用代理池
proxies_pool = [{'http': '47.122.65.254:8080'},{'http': '8.130.34.44:8800'},{'http': '47.121.183.107:8443'},{'http': '111.1.61.50:3128'},{'http': '47.119.164.33:3128'}
]proxies = random.choice(proxies_pool)# 发送 GET 请求,并使用指定的代理
response = requests.get(url=url, proxies=proxies)print(response.status_code)

打印的结果为:

200

4. 使用 HTTP Basic Auth 的代理

如果代理需要使用 HTTP Basic Auth,可以使用 username:password@host 的语法来配置代理。

# 定义代理字典,包含用户名和密码
proxies = {"http": "username:password@10.10.1.10:3128",
}

5. 针对特定主机或连接方式设置代理

要为某个特定的连接方式或主机设置代理,可以使用 scheme://hostname 作为键。这种方式将针对指定的主机和连接方式进行匹配。

import requestsurl = 'http://www.baidu.com'# 针对特定主机设置代理
proxies = {"http://127.0.0.1": "http://47.121.183.107:8443"
}# 发送 GET 请求,并使用指定的代理
response = requests.get(url=url, proxies=proxies)print(response.status_code)

打印的结果为:

200

六、编码方式

1. 编码方式处理

当你收到一个 HTTP 响应时,requests 库会猜测响应内容的编码方式,以便在你调用 Response.text 方法时能够正确解码响应内容。以下是 requests 处理编码方式的具体机制。

1.1 自动检测编码

  1. 优先检查 HTTP 头部requests 首先会在 HTTP 响应头部查找 Content-Type 字段中的字符集声明。如果存在明确指定的字符集(例如 charset=UTF-8),则使用该字符集进行解码。

  2. 使用 charade 猜测编码:如果 HTTP 头部没有明确指定字符集,并且 Content-Type 包含 text 类型,则 requests 会使用内置的 chardet 库(原名为 charade)来推测最可能的编码方式。

  3. 默认编码:根据 RFC 2616 的规定,当 Content-Typetext 类型但没有指定字符集时,默认字符集应该是 ISO-8859-1requests 遵循这一规范并默认采用 ISO-8859-1 进行解码。

1.2 手动设置编码

如果你知道正确的编码方式并且希望覆盖 requests 的自动检测结果,可以通过直接设置 Response.encoding 属性来实现。

import requestsurl = 'https://api.github.com/events'response = requests.get(url=url)# 查看推测的文本编码
print("自动推测的编码方式:" + response.encoding)# 手动指定编码为 ISO-8859-1
response.encoding = 'ISO-8859-1'
# 打印编码方式
print("手动指定的编码方式:" + response.encoding)

打印的结果为:

自动推测的编码方式:utf-8
手动指定的编码方式:ISO-8859-1

1.3 使用原始字节数据

如果你不确定编码或者不想依赖于 requests 的自动解码功能,可以直接访问 Response.content 属性以获取未经解码的原始字节数据。然后根据需要自行解码。

import requestsurl = 'https://api.github.com/events'response = requests.get(url=url)# 获取未经解码的原始字节数据,返回的是服务器返回的二进制内容
raw_data = response.content# 使用 UTF-8 编码方式对原始字节数据进行解码,转换为字符串
decoded_text = raw_data.decode('utf-8')
print(decoded_text)

七、身份认证

1. 基本身份认证 (HTTP Basic Auth)

HTTP Basic Authentication 是一种简单的认证机制,广泛用于需要认证的 Web 服务中。requests 库对这种认证方式提供了直接的支持。

可以通过导入 HTTPBasicAuth 类来使用 HTTP Basic Auth。

import requests
from requests.auth import HTTPBasicAuthurl = 'https://api.github.com/user'
auth = HTTPBasicAuth('user', 'pass')
# 发送带有基本身份认证的 GET 请求
response = requests.get(url=url, auth=auth)print(response.status_code)

简写形式:由于 HTTP Basic Auth 非常常见,requests 提供了一种更为简洁的方式来传递认证信息——直接在 auth 参数中提供一个元组。

import requestsurl = 'https://api.github.com/user'
# 发送带有基本身份认证的 GET 请求
response = requests.get(url=url, auth=('user', 'pass'))print(response.status_code)

参考链接:

  • requests 官方文档:http://cn.python-requests.org/zh_CN/latest/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/65580.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java-38 深入浅出 Spring - AOP切面增强 核心概念 相关术语 Proxy配置

点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatis&#xff…

【算法】复杂性理论初步

六、算法复杂性初步 重要的复杂性类 P P P 的定义 多项式时间内可解的问题 若 L ∈ P L∈P L∈P,则存在确定性多项式时间的图灵机 M M M,使得 M ( x ) 1 ⟺ x ∈ L M(x)1⟺x∈L M(x)1⟺x∈L N P NP NP 的定义 多项式时间内可验证验证解的正确性 &…

hive中的四种排序类型

1、Order by 全局排序 ASC(ascend): 升序(默认) DESC(descend): 降序 注意 :只有一个 Reducer,即使我们在设置set reducer的数量为多个,但是在执行了order by语句之后,当前此次的运算还是只有…

Mysql(MGR)和ProxySQL搭建部署-Docker版本

项目路径:D:\study\backend\mysql\mgr 一、Mysql(MGR) 1.1 docker-compose.yaml volumes: # MySQL配置文件目录 - "./mysql-1/conf.d/my.cnf:/etc/mysql/my.cnf" # MySQL工作目录 - "./mysql-1/data:/var/lib/mysql" …

智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之1

本文要点 这一次我们先把抛开前面对“智能工厂的软件设计”的考虑--其软件智能 产品就是 应用程序。直接看看应用程序。例如,在现在各种AI聊天工具层出不穷的今天,我觉得特别需要一个通用的AI聊天工具的图形界面能够为每个聊天者(或一个利益…

科技快讯 | 水滴筹成为民政部指定个人求助网络服务平台;小米超级小爱首次向正式版用户开放;腾讯发布全球首个重症医疗大模型

本地 AI 开发利器,初探微软 Win11 AI Dev Gallery 功能 12月27日,科技媒体Windows Latest报道,微软推出AI Dev Gallery功能,助力开发者集成端侧AI。该功能支持Windows 10/11,提供25个示例模型,涵盖多领域。…

python爬虫----爬取视频实战

python爬虫-爬取视频 本次爬取,还是运用的是requests方法 首先进入此网站中,选取你想要爬取的视频,进入视频页面,按F12,将网络中的名称栏向上拉找到第一个并点击,可以在标头中,找到后续我们想要…

大数据面试笔试宝典之Flink面试

1.Flink 是如何支持批流一体的? F link 通过一个底层引擎同时支持流处理和批处理. 在流处理引擎之上,F link 有以下机制: 1)检查点机制和状态机制:用于实现容错、有状态的处理; 2)水印机制:用于实现事件时钟; 3)窗口和触发器:用于限制计算范围,并定义呈现结果的…

AR 模型的功率谱

功率谱密度(Power Spectral Density, PSD)的表达式是从信号的自相关函数和系统的频率响应推导出来的,特别是对于 AR(Auto-Regressive,自回归)模型。以下是推导的过程: 1. AR 模型的定义&#xf…

leetcode------mysql

177. 第N高的薪水 - 力扣(LeetCode) 表: Employee ------------------- | Column Name | Type | ------------------- | id | int | | salary | int | ------------------- 在 SQL 中,id 是该表的主键。 该表的每一行都包含…

coturn docker 项目 搭建【一切正常】

业务需求:需要coturn这个服务 定制语音视频连线 请参考"小红的逃脱外星人追踪计划" coturn项目 本地测试连接服务 turnutils_stunclient -p 3478 127.0.0.1turnutils_stunclient -p 3478 -L 127.0.0.1 127.0.0.1telnet localhost 3478turnutils_uclient …

Linux 笔记 /etc 目录有什么用?

在 Linux 系统中,/etc 目录的全称是 "et cetera",中文可以翻译为“其他”或“杂项”。这个目录用于存放系统的配置文件和一些启动脚本。名称来源于早期的 Unix 系统设计,当时它被用来存放那些不属于其他特定类别的系统文件。 随着…

Android 学习小记1

目录 先介绍一下Android Studio 看看常见的模板 1. No Activity 2. Empty Activity 3. Gemini API Starter 4. Basic View Activity 5. Bottom Navigation Activity 6. Empty Views Activity 7. Navigation Drawer Views Activity 8. Responsive Views Activity 9. G…

【Compose multiplatform教程06】用IDEA编译Compose Multiplatform常见问题

当我们从Kotlin Multiplatform Wizard | JetBrains 下载ComposeMultiplatform项目时 会遇到无法正常编译/运行的情况,一般网页和桌面是可以正常编译的, 我这里着重解决如下问题 1:Gradle版本不兼容或者Gradle连接超时 2:JDK版本不兼容 3:Gradle依赖库连…

Python + 深度学习从 0 到 1(02 / 99)

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦 欢迎关注、订阅专栏 【深度学习从 0 到 1】谢谢你的支持! ⭐ Keras 快速入门: 神经网络的基本数据结…

MySQL 数据库基础

目录 什么是数据库 数据库分类 关系型数据库 非关系型数据库 SQL子语言 MySQL MySQL 存储数据的组织方式 数据库操作 显示当前数据库 创建数据库 使用数据库 删除数据库 什么是数据库 数据库 是一个用于存储、管理和检索数据的系统,可以组织和保存大量…

《Vue3 二》Vue 的模板语法

在 React 中,想要编写 HTML,是使用 JSX,之后通过 Babel 将 JSX 编译成 React.createElement 函数调用;在 Vue 中,也支持 JSX 的开发模式,但大多数情况下都是使用基于 HTML 的模板语法,在模板中允…

江科大学习笔记之——标准库点亮一个LED灯

控制GPIO就三步 1.RCC时钟使能 2.结构体配置GPIO寄存器 3.控制GPIO值 gpio.c #include "stm32f10x.h" // Device headervoid gpio_Init(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//1.RCC时钟使能GPIO_InitTypeDef GPIO_I…

高级技巧-使用Mysql 实现根据条件过滤整个分组数据

博客-mysql exists实现过滤所属条件对应分组的全部数据 在数据查询中,有时需要根据某一条件来过滤整个分组的数据,尤其是当某条记录满足特定条件时,需要将该组内的所有记录排除。本文将介绍如何使用 MySQL 的 EXISTS 关键字来实现这种分组过滤…

游戏引擎学习第67天

reviewing “apron”概念以更新区域 我们正在进行模拟区域的扩展工作,目标是通过增加一个更大的区域来支持更丰富的互动,尤其是那些可能超出摄像机视野的内容。现有的模拟区域包括摄像机能看到的区域和其周围的环境区域,但为了保证更高效的游…