httpx 是一个可以支持 HTTP/2.0 的库
还有一个是: hyper 库
这里有一个由HTTP/2.0的网站: https://spa16.scrape.center/
使用 requests 库 进行爬取
import requests
url = 'https://spa16.scrape.center/'
response = requests.get(url)
print(response.text)
报错:
ConnectionError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
安装: httpx
pip3 install httpx
这样安装并不能支持 HTTP/2.0
如果想要支持,需要这样安装:
pip3 install httpx[http2]
基本使用:
import httpx
response = httpx.get('https://www.httpbin.org/get')
print(response.status_code)
print(response.headers)
print(response.text)
输出:
这里访问的HTTP/1.0的网站,并且依次打印除了 , 响应状态码(status_code),
响应头信息(headers) , 响应体(text) 我们可以看到 User-Agent 对应的是 python-httpx/0.27.0 代表我们用的是 httpx请求的
这里换一下 User-Agent 再试一次
import httpx
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36'
}
response = httpx.get('https://www.httpbin.org/get', headers= headers)
print(response.text)
输出:
使用httpx 请求 HTTP/2.0 的网站
import httpx
url = 'https://spa16.scrape.center/'
response = httpx.get(url)
print(response.text)
报错:
RemoteProtocolError: Server disconnected without sending a response.
httpx 要想支持 HTTP/2.0的访问 需要手动声明
import httpx
url = 'https://spa16.scrape.center/'
client = httpx.Client(http2=True)
response = client.get(url)
print(response.text)
输出:
这里我们声明了一个 Client 对象 复制给 client 变量, 同时显示的将 http2 参数设置为 True,这样便开启了 HTTP/2.0 的支持
对于不同类型的请求的写法其实都是大同小异的
import httpx
r = 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')
基于获取到 Reponse 对象 可以用如下属性和方法 获取想要的内容
status_code : 状态码
text : 响应体内容
content : 响应体二进制内容,当请求目标是二进制数据(如图片,视频)可以使用此属性获取
headers ; 响应头。 是 Headers 对象, 可以像获取字典内容一样获取某个 Header 的值
json : 方法 . 可以调用此方法将文本结果转化为 JSON 对象
具体其他用法参考官网: QuickStart - HTTPX
Client 对象
官方比较推荐的使用方式是 with as
import httpx
with httpx.Client() as client:
response = client.get('https://www.httpbin.org/get')
print(response)
等价于:
import httpx
client = httpx.Client()
try:
response = client.get('https://www.httpbin.org/get')
print(response)
finally:
client.close()
输出:
<Response [200 OK]>
两种方式的运行结果是一样的,不过后一种需要显示的调用 close 方法来关闭Client对象
另外,再声明Client 对象时可以指定一些参数, 例如headers
import httpx
url = 'https://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'])
输出:
my-app/0.0.1
我们声明了一个 headers 变量, 内容为User-Agent 属性, 然后将此变量传递给 headers 参数初始化了一个 Client 对象, 并复制给了 client 变量, 最后用 client 变量请求了测试网站, 并打印返回结果中的 User-Agent 的内容
更多的用法参考官网: https://www.python-httpx.org/advanced/
支持 HTTP/2.0
就像前面小节里面说的一样,需要显示的开启对HTTP/2.0的支持,不然默认是不支持的
import httpx
url = 'https://www.httpbin.org/get'
client = httpx.Client(http2=True)
response = client.get(url)
print(response.text)
print(response.http_version)
输出:
{"args": {}, "headers": {"Accept": "*/*", "Accept-Encoding": "gzip, deflate, br", "Host": "www.httpbin.org", "User-Agent": "python-httpx/0.27.0", "X-Amzn-Trace-Id": "Root=1-6694ce46-2ececd2f69066e9336840987"}, "origin": "117.152.25.76", "url": "https://www.httpbin.org/get" }HTTP/2
注意: 在客户端的 httpx 上启用对 HTTP/2.0 的支持, 并不意味着请求和响应都将通过HTTP/2.0传输, 这得客户端和服务端都支持HTTP/2.0才行。 如果客户端链接到仅支持HTTP/1.0的服务端, 那么也要改用 HTTP/1.0
支持异步请求
httpx 还支持异步客户端请求 (AsyncClient), 支持python的 async 请求模式
import httpx
import asyncio
import nest_asyncionest_asyncio.apply()
async 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'))
输出:
{"args": {}, "headers": {"Accept": "*/*", "Accept-Encoding": "gzip, deflate, br", "Host": "www.httpbin.org", "User-Agent": "python-httpx/0.27.0", "X-Amzn-Trace-Id": "Root=1-6694d0ef-779505ae5e5b42715b76c643"}, "origin": "117.152.25.76", "url": "https://www.httpbin.org/get" }
说明:
import nest_asyncio
nest_asyncio.apply()
这两行代码是因为 报错:
RuntimeError: This event loop is already running
才加上的
关于异步请求可以参考 https://www.python-httpx.org/async/