基础库httpx的使用
urllib 库和 requests 库的使用,已经可以爬取绝大多数网站的数据,但对于某些网站依然无能为力。什么情况?这些网站强制使用HTTP/2.0协议访问,这时 urllib 和requests 是无法爬取数据的,因为它们只支持 HTTP/1.1,不支持 HTTP/2.0。那这种情况下应该怎么办呢?
还是有办法的,只需要使用一些支持 HTTP/2.0的请求库就好了,目前来说,比较有代表性的是hyper 和 httpx,后者使用起来更加方便,功能也更强大,requests 已有的功能它几乎都支持。
示例
下面我们来看一个案例,https://spa16.scrape.center/ 就是强制使用 HTTP/2.0访问的一个网站,用浏览器打开此网站,查看 Network面板,可以看到 Protocol 一列都是 h2,证明请求所用的协议是HTTP/2.0,如下图所示。
这个网站用requests 是无法爬取的,不妨来尝试一下:
import requestsurl = 'https://spa16.scrape.center/'
response = requests.get(url)
print(response.text)
运行结果如下:
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(10054, '远程主机强迫关闭了一个现有的连接。', None, 10054, None))
可能有人认为这是没有设置请求头导致的,其实不是,真实原因是requests 这个库是使用 HTTP/1.1访问的目标网站,而目标网站会检测请求使用的协议是不是 HTTP/2.0,如果不是就拒绝返回任何结果。
安装
httpx 可以直接使用 pip3 工具安装,所需的 Python 版本是 3.6及以上,安装命令如下:
pip3 install httpx
但这样安装完的 httpx 是不支持 HTTP/2.0的,如果想支持,可以这样安装:
pip3 install 'httpx[http2]'
这样就既安装了 httpx,又安装了 httpx 对 HTTP/2.0 的支持模块。
基本使用
httpx 和 requests 的很多 API存在相似之处,我们先看下最基本的 GET 请求的用法:
import httpxresponse = httpx.get('https://www.httpbin.org/get')
print(response.status_code)
print(response.headers)
print(response.text)
这里我们还是请求之前的测试网站,直接使用htpx的get方法即可,用法和requests 里的一模一样,将返回结果赋值为response 变量,然后打印出它的status code、headers、text 等属性,运行结果如下:
200
Headers({'date': 'Thu, 19 Dec 2024 14:27:23 GMT', 'content-type': 'application/json', 'content-length': '312', 'connection': 'keep-alive', 'server': 'gunicorn/19.9.0', 'access-control-allow-origin': '*', 'access-control-allow-credentials': 'true'})
{"args": {}, "headers": {"Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Host": "www.httpbin.org", "User-Agent": "python-httpx/0.28.1", "X-Amzn-Trace-Id": "Root=1-67642d4b-31795bb819573e2e7516a357"}, "origin": "36.163.154.16", "url": "https://www.httpbin.org/get"
}
输出结果包含三项内容,status code 属性对应状态码,为 200;headers 属性对应响应头,是一Headers 对象,类似于一个字典;text 属性对应响应体,可以看到其中的 User-Agent 是个、python-httpx/0.18.1,代表我们是用 httpx 请求的。
下面换一个 User-Agent 再请求一次,代码改写如下:
import httpxheaders = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac 0s X 10 15 7)AppleWebKit/537.36 (KHTML, like Gecko)Chrome/90.0.4430.93 Safari/537.36"}response = httpx.get('https://www.httpbin.org/get', headers=headers)
print(response.text)
这里我们换了一个 User-Agent重新请求,并将其赋值为 headers 变量,然后传递给headers 参数,运行结果如下:
{"args": {}, "headers": {"Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Host": "www.httpbin.org", "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac 0s X 10 15 7)AppleWebKit/537.36 (KHTML, like Gecko)Chrome/90.0.4430.93 Safari/537.36", "X-Amzn-Trace-Id": "Root=1-67642df8-64d00406369b3f1b3660c57c"}, "origin": "36.163.154.16", "url": "https://www.httpbin.org/get"
}
可以发现更换后的 User-Agent 生效了。
回到本节开头提到的示例网站,我们试着用httpx请求一下这个网站,看看效果如何,代码如下:
import httpxresponse = httpx.get('https://spa16.scrape.center')
print(response.text)
运行结果如下:
httpx.ReadError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
可以看到,抛出了和使用 requests 请求时类似的错误,不是说好支持 HTTP/2.0吗?其实,httpx 默认是不会开启对 HTTP/2.0的支持的,默认使用的是 HTTP/1.1,需要手动声明一下才能使用 HTTP/2.9,代码改写如下:
import httpxclient = httpx.Client(http2=True)
response = client.get('https://spa16.scrape.center/')
print(response.text)
运行结果如下:
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><meta name=referrer content=no-referrer><link rel=icon href=/favicon.ico><title>Scrape | Book</title><link href=/css/chunk-50522e84.e4e1dae6.css rel=prefetch><link href=/css/chunk-f52d396c.4f574d24.css rel=prefetch><link href=/js/chunk-50522e84.6b3e24aa.js rel=prefetch><link href=/js/chunk-f52d396c.f8f41620.js rel=prefetch><link href=/css/app.ea9d802a.css rel=preload as=style><link href=/js/app.b93891e2.js rel=preload as=script><link href=/js/chunk-vendors.a02ff921.js rel=preload as=script><link href=/css/app.ea9d802a.css rel=stylesheet></head><body><noscript><strong>We're sorry but portal doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.a02ff921.js></script><script src=/js/app.b93891e2.js></script></body></html>
这里我们声明了一个 Client 对象,赋值为 client 变量,同时显式地将 http2 参数设置为 True,这样便开启了对 HTTP/2.0的支持,之后就会发现可以成功获取 HTML代码了。这也就印证了这个示例网站只能使用 HTTP/2.0 访问。
刚才我们也提到了,httpx和requests有很多相似的API,上面实现的是 GET请求,对于POST请求、PUT请求和DELETE请求来说,实现方式是类似的:
import httpxr = httpx.get('https://www.httpbin.org/get', params={'name': 'germey'})
r = httpx.post('https://www.httpbin.org/post', data={'name': 'germey'})
r = httpx.put('https://www.httpbin.org/put')
r = httpx.delete('https://www.httpbin.org/delete')
r = httpx.patch('https://www.httpbin.org/patch')
基于得到的 Response 对象,可以使用如下属性和方法获取想要的内容。
- status code:状态码:
- text:响应体的文本内容。
- content:响应体的二进制内容,当请求的目标是二进制数据(如图片)时,可以使用此属性
获取。 - headers:响应头,是Headers 对象,可以用像获取字典中的内容一样获取其中某个 Header
的值。 - json:方法,可以调用此方法将文本结果转化为JSON对象。
除了这些,htpx还有一些基本用法也和requests极其类似,这里就不再赘述了,可以参考官方文档:https://www.python-httpx.org/quickstart/。
Client对象
httpx 中有一些基本的 API和 requests 中的非常相似,但也有一些 API是不相似的,例如 htpx 中有一个 Client 对象,就可以和 requests 中的 Session 对象类比学习。
下面我们介绍 client 对象的使用。官方比较推荐的使用方式是withas语句,示例如下:
import httpxwith httpx.Client() as client:response = client.get('https://www.httpbin.org/get')print(response)
运行结果如下:
<Response [200 OK]>
这个用法等价于:
import httpxclient = httpx.Client()
try:response = client.get('https://www.httpbin.org/get')
finally:client.close()
两种方式的运行结果是一样的,只不过这里需要我们在最后显式地调用 close 方法来关闭 client对象。
另外,在声明 Client 对象时可以指定一些参数,例如 headers,这样使用该对象发起的所有请求都会默认带上这些参数配置,示例如下:
import httpxurl = "http://www.httpbin.org/headers"
headers = {'User-Agent': 'my-app/0.0.1'}
with httpx.Client(headers=headers) as client:r = client.get(url)print(r.json()['headers']['User-Agent'])
这里我们声明了一个 headers 变量,内容为 User-Agent 属性,然后将此变量传递给 headers 参数初始化了一个 client 对象,并赋值为 client 变量,最后用 client 变量请求了测试网站,并打印返回结果中的 User-Agent 的内容:
my-app/0.0.1
可以看到,headers 成功赋值了。
关于 Client 对象的更多高级用法可以参考官方文档:https://www.python-httpx.org/advanced/。
支持 HTTP/2.0
现在是要在客户端上开启对 HTTP/2.0的支持,就像“基本使用”小节所说的那样,同样是声明Client 对象,然后将 http2 参数设置为True,如果不设置,那么默认支持 HTTP/1.1,即不开启对HTTP/2.0 的支持。
写法如下:
import httpxclient = httpx.Client(http2=True)
response = client.get('https://www.httpbin.org/get')
print(response.text)
print(response.http_version)
这里我们输出了 response 变量的 http_version 属性,这是 requests 中不存在的属性,其结果可能为:
HTTP/2
这里输出的 http_version 属性值是 HTTP/2,代表使用了 HTTP/2.0 协议传输。
注意:在客户端的 httpx 上启用对 HTTP/2.0的支持并不意味着请求和响应都将通过 HTTP/2.0 传输这得客户端和服务端都支持 HTTP/2.0 才行。如果客户端连接到仅支持 HTTP/1.1 的服务器那么它也需要改用 HTTP/1.1。
支持异步请求
httpx 还支持异步客户端请求(即 AsyncClient ),支持 Python的 async 请求模式,写法如下:
import httpx
import asyncioasync def fetch(url):async with httpx.AsyncClient(http2=True) as client:response = await client.get(url)print(response.text)if __name__ == '__main__':asyncio.get_event_loop().run_until_complete(fetch('https://www.httpbin.org/get'))
关于异步请求,目前仅了解一下即可,后面章节也会专门对异步请求进行讲解。大家也可以参考官方文档:https://www.python-httpx.org/async/。
总结
本篇博客介绍了 httpx的基本用法,该库的 API与requests的非常相似,简单易用,同时支持 HTTP/2.0.
推荐大家使用。
相关文章:

基础库httpx的使用
urllib 库和 requests 库的使用,已经可以爬取绝大多数网站的数据,但对于某些网站依然无能为力。什么情况?这些网站强制使用HTTP/2.0协议访问,这时 urllib 和requests 是无法爬取数据的,因为它们只支持 HTTP/1.1,不支持…...
c++中如何保持结构体的线程安全?3D坐标的线程安全:从理论到最优解
使用mutex的困扰 struct Point3d {std::mutex mtx;double x, y, z;void set(double nx, double ny, double nz) {std::lock_guard<std::mutex> lock(mtx);x nx; y ny; z nz;} };这种方案虽然安全,但性能开销确实不小。每次访问都需要加锁解锁,…...

Zabbix6.0升级为6.4
为了体验一些新的功能,比如 Webhook 和问题抑制等,升级个小版本。 一、环境信息 1. 版本要求 一定要事先查看官方文档,确认组件要求的版本,否则版本过高或者过低都会出现问题。 2. 升级前后信息 环境升级前升级后操作系统CentOS…...

答题考试系统v1.6.1高级版源码分享+uniapp+搭建测试环境
一.系统介绍 一款基于FastAdminThinkPHPUniapp开发的小程序答题考试系统,支持多种试题类型、多种试题难度、练题、考试、补考模式,提供全部前后台无加密源代码,支持私有化部署 二.测试环境 系统环境:CentOS、 运行环境&#x…...

【Lua热更新】下篇 -- 更新中
上篇链接:【Lua热更新】上篇 文章目录 三、xLua热更新📖1.概述📚︎2.导入xLua框架🔖3. C#调用Lua3.1Lua解析器3.2Lua文件夹的重定向3.3Lua解析器管理器3.4全局变量获取3.5全局函数获取3.6映射到List和Dictionary3.7映射到类3.8映…...
射频测试入门学习(三)——程控仪器是怎样和电脑连接通信的
目录 一、程控仪器需要哪些条件 二、可程控仪器 三、专业的仪器通信软件、驱动 四、编程语言 五、电脑控制仪器条件汇总 六、仪器指令查询 七、结语 一、程控仪器需要哪些条件 1、需要具备硬件条件(可程控的仪器、个人计算机(PC)) 2、专业的仪器通信软件、驱动 3、…...
并发控制之Semaphore
Semaphore 作用 信号量,用于控制同时访问特定资源的线程数量,通过协调各个线程,以确保对共享资源的访问不会导致冲突或数据不一致等问题,有点类似令牌桶,内部维护一组许可证, acquire获取许可证…...

第R3周:RNN-心脏病预测
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 🍺要求: 1 本地读取并加载数据。 2 了解循环神经网络(RNN)的构建过程 3 测试集accuracy到达87% 🍻拔…...
【数值特性库】入口文件
数值特性库入口文件为lib.rs。该文件定义一系列数字特性的trait(特征),这些特性可以被不同的数字类型实现,从而提供一套通用的数值操作方法。下面是对代码中关键部分的解释: 一、基础设置 #
GIT区域介绍及码云+GIt配置仓库
GIT区域介绍 创建文件夹git init 1、git有3个区域 工作区(working directory):项目的根目录,不包 括.git在内的其他文件暂存区(stage area):是一个看不见的区域,git add 命令就是将文…...

网络安全怎么学习
当我们谈论网络安全时,我们正在讨论的是保护我们的在线空间,这是我们所有人的共享责任。网络安全涉及保护我们的信息,防止被未经授权的人访问、披露、破坏或修改。 一、网络安全的基本概念 网络安全是一种保护:它涉及保护我们的设…...
PugiXML,一个高效且简单的 C++ XML 解析库!
嗨,大家好!我是一行。今天要给大家介绍 PugiXML,这可是 C 里处理 XML 数据的得力助手。它能轻松地读取、修改和写入 XML 文件,就像一个专业的 XML 小管家,不管是解析配置文件,还是处理网页数据,…...
Linux设备树的驱动开发
概述 本文介绍了platform框架下的设备驱动开发流程和方法,主要包括设备树、驱动程序和应用程序的开发。以随机数驱动为例,实现了应用程序调用库函数,通过系统调用陷入内核,最后执行硬件驱动,获取真随机数的过程。 添…...

连锁?下沉?AI?2025年餐饮新活力!
如果要用几个词来形容 2024 年的餐饮业,这些词大概率会是「卷、难、惨」,用著名商业顾问刘润的话来说就是「卷到极致」。虽然餐饮人在社交平台上叫苦连天,但当我们查看餐饮大盘数据时发现,大盘在涨,与个体餐饮人的实感…...
Javascript中如何实现函数缓存?函数缓存有哪些应用场景?
今天要聊的一个很经典的问题——如何在JavaScript中实现函数缓存,以及它有哪些应用场景。 我们先来明确一下,函数缓存是什么。简单来说,函数缓存是将函数的运算结果存储起来,以便下次用到相同的输入时,可以直接返回结…...
子页面访问父页面
子页面访问父页面的方式主要依赖于页面之间的关系,特别是它们是否处于同一域、是否是嵌套在 <iframe> 中、或者通过弹出窗口打开。下面是几种常见的子页面访问父页面的方法: 1. 通过 window.parent 访问父页面(适用于嵌套的 iframe&am…...

芯片级IO (Pad) Ring IP Checklist
SoC top顶层数字后端实现都会涉及到IO Ring (PAD Ring)的设计。这里面包括VDD IO,VDDIO IO, Signal IO, Corner IO,Filler IO,IO power cut cell等等。 数字后端零基础入门系列 | Innovus零基础LAB学习Day2 数字IC后端实现TOP F…...

计算机毕业设计论文指导
计算机毕业设计论文指导 计算机毕业设计辅导一站式!太香了💪 [赞R][赞R][赞R]嗨喽!计算机专业的宝子们! 计算机毕设辅导专业靠谱的他来了!! 是不是还在为选题程序不会做而感到苦难? 论文没思路赶…...

Electron-Vue 开发下 dev/prod/webpack server各种路径设置汇总
背景 在实际开发中,我发现团队对于这几个路径的设置上是纯靠猜的,通过一点点地尝试来找到可行的路径,这是不应该的,我们应该很清晰地了解这几个概念,以下通过截图和代码进行细节讲解。 npm run dev 下的路径如何处理&…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...

使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...

算法—栈系列
一:删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...
前端工具库lodash与lodash-es区别详解
lodash 和 lodash-es 是同一工具库的两个不同版本,核心功能完全一致,主要区别在于模块化格式和优化方式,适合不同的开发环境。以下是详细对比: 1. 模块化格式 lodash 使用 CommonJS 模块格式(require/module.exports&a…...