Python requests在HTTP2.0下的问题

今天在用Python中的requests包爬数据时,发现了一个很特殊的请求头,其中有:authority:method:path:scheme这几个参数,这些参数说明这个网站用了HTTP2.0。然后我发现我们不能用requests包直接构造请求头进行爬取了。本文简单分析并解决这个问题。

HTTP2.0:请求/响应首部的定义基本没有改变,只是所有首部键必须全部小写,而且请求行要独立为:method:scheme:host:path这些键值对。

如果我们按照以前的设置构造headers进行爬取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
url = "https://xxxxxx.com/tag/xxxx/page/1.html"
headers = {':authority': 'xxxxxx.com',
':method': 'GET',
':path': '/tag/xxxx/page/1',
':scheme': 'https',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Sec-Fetch-Mode':'navigate',
'Sec-Fetch-Site':'none',
'Sec-Fetch-User':'?1',
'Upgrade-Insecure-Requests':'1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36'}

requests.get(url = url, headers = headers)

会报出以下错误:

1
ValueError: Invalid header name b':authority'

这是因为HTTP的请求头不能以分号开头。源码不能解析这样的请求头,具体可以见源码

我们可以使用hyper这个第三方包来解决这个问题,我们将代码改写为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from hyper.contrib import HTTP20Adapter

url = "https://xxxxxx.com/tag/xxxx/page/1.html"
headers = {':authority': 'xxxxxx.com',
':method': 'GET',
':path': '/tag/xxxx/page/1',
':scheme': 'https',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Sec-Fetch-Mode':'navigate',
'Sec-Fetch-Site':'none',
'Sec-Fetch-User':'?1',
'Upgrade-Insecure-Requests':'1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36'}

sessions = requests.session()
sessions.mount('https://xxxx.com', HTTP20Adapter())
response = sessions.get(url = url,headers = headers)

OK,问题解决!

参考


----------- 本文结束啦感谢您阅读 -----------

赞赏一杯咖啡

欢迎关注我的其它发布渠道