最近发现一个很6的东西。这个问题是在差不多半个月前,在技术群里一个老哥发现的问题,然后在群里跟大家讨论。
这个网站,请求的时候,requests正常:
原始的curl也可以
aiohttp,直接报错
httpx,也直接报错:
不过httpx的报错要明显点,这就进入了有意思的环节
看到这里,估计就有朋友开始冷笑了:搞爬虫大部分不都用requests的吗,谁会用httpx和aiohttp这些啊,感觉这个是不是没啥用啊。
别急,朋友,在文章的下面会说这个,当然如果你赶时间或者觉得没啥意思,那就没必要浪费时间继续看了
拿着上面的报错,去网上搜,找到如下issues:
看完里面各位大佬的一顿分析,说是hyper库的问题:
然后hyper库的开发者,如下链接回复:
大概意思是这个不是一个问题,而是http请求的严格性判断问题,请求头的协议,按国际标准,是不能出现 “[Cache-Control]” 这种带有特殊符号作为响应头的键名的,所以报错
而requests却可以,或许是因为requests的校验不严格,直接就放过了:
而,浏览器访问也是可以的:
那么我个人就有理由认为
这是一个bug,httpx和aiohttp都存在的bug
httpx的作者,对这个问题那段时间确实在尝试解决,github机器人都想关闭了,httpx作者还不想放弃:
且至今没解决,遇到的人还不少,至少,上个月都还有人在说这个问题
卧槽,这时间,上周都还有人在问啊:
其中也有说解决办法,看到有个老哥说改h11的源码,改成这样:
但是报错依然在
另外有个老哥说了这个方法:
我把这个代码直接放我代码里,报错了,根本没有这个属性
经过一顿查阅,他换了个属性名,是这个:
但是我试了,换成了新的报错:
也许是正则表达式写的不完美:
正则表达式通用匹配一下,然后就可以了:
但是,我换了一个网站,也就是那个issue里某华某为的社区地址,不出正常的结果:
所以,修改正则表达式并不是一个通用的方案。
插一句,在请求的时候,就不要开代理或者抓包软件了,不然他报错更奇怪:
综上所述,也就是,只要服务器的返回头埋的坑够多,这个方法根本无法完美解决
那么这个问题,httpx作者就给了个这个解释就没下文了
就这么不了了之了。。。
因为根据http协议的响应头原理,确实不会出现这种不标准的字段
更官方的解释可以去查查http协议原理,或者看看以下资料:
我的理解如下:
客户端需要先解析响应头,通过响应头的一些规范来解析返回的响应体的,既然你响应头都报错了,那后续的响应体解析自然也不会往下走了,直接报错退出。
对于aiohttp来说,像上面那么加正则表达式是无效的:
改完发现并没有用
这还有说,改成1,也试了,不行
更多的就不演示了
反正就是一顿查找,发现aiohttp上并没有合理方案解决
上面有了,这里就不展示了
但是requests我们知道,它是不支持http2.0协议的
上面也有了,这里不贴了
但是不能完美覆盖后续的响应头特殊参数
这个库用的倒不多,但可以直接请求:
但是他也是个可以直接拿来请求的库,相比requets,那很多功能还是没有。
其实requests本质就是借助了urllib3库的
所以,这个库,不出意外应该也是不支持http2.0的
既然目前的方法,除了requests/urllib3,其他都不行,那我在这个基础之上,强制http2,是不是就可以干掉requets库了,python的常规请求库直接无可用的,直接干死这些爬虫?
想的挺美的,哈哈
虽然他是用来对抗tls的,试试呢:
可行。为啥,因为他原理就是完全模拟浏览器,大概看了它的源码,用curl_impersonate库,打包成了一个dll(具体怎么打包的不可知,这部分没开源,插一句,据群友反馈,也是因为这个dll,会导致内存泄漏),然后可以直接用,上面说过了,浏览器可以访问,那这个库肯定也可以访问了
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2023-4-3 17:58
被geekbyte编辑
,原因: 调整排版