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,。
尝试使用request爬取
import requests url = 'https://spa16.scrape.center/' response = requests.get(url) print(response.text)
抛出RemoteDisconnected错误,请求失败。
安装
Python3.6及以上,httpx可以直接使用pip工具安装
pip3 install httpx
但是这样安装不支持HTTP/2.0,如果想支持可以这样安装
pip3 install "httpx[http2]"
这样即安装了httpx,又安装了HTTP/2.0支持模块
基本使用
httpx和requests的很多API存在相似之处,下面是GET请求
import httpx response = httpx.get(url='https://www.httpbin.org/get') print(response.status_code) print(response.headers) print(response.text)
可以看到User-Agent是python-httpx/0.27.0,表示使用httpx请求的
换一个User-Agent再请求一次
import httpx headers = { 'User-Agent' : 'Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.188 Safari/537.36 CrKey/1.54.250320' } response = httpx.get(url='https://www.httpbin.org/get', headers=headers) print(response.text)
User-Agent生效后,尝试用户httpx请求刚才的网站
import httpx headers = { 'User-Agent':'Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.188 Safari/537.36 CrKey/1.54.250320' } response = httpx.get(url='https://spa16.scrape.center', headers=headers) print(response.text)
抛出了和使用requests请求时类似的错误,httpx默认不会开启对HTTP/2.0的支持,默认使用的是HTTP/1.1,需要手动声明一下才能使用HTTP/2.0,改写代码:
import httpx client = httpx.Client(http2=True) headers = { 'User-Agent':'Mozilla/5.0 (X11; Linux aarch64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.188 Safari/537.36 CrKey/1.54.250320' } response = client.get(url='https://spa16.scrape.center', headers=headers) print(response.text)
声明了一个Client对象,赋值为client变量,同时显式地将http2参数设置为True,这样便开启了对HTTP/2.0的支持,就发现可以成功获取HTML代码。
httpx和requests有很多类似API,上面实现GET请求,对于POST请求、PUT请求和DELETE请求实现方式是一样的。
import httpx r = httpx.get('https://www.httpbin.org/get', params={'name':'germey'}) r = httpx.post('https://www.httpbin.org/post', params={'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对象
官方文档:https://www.python-httpx.org/quickstart/
Client对象
httpx中有一些基本的API和requests中的非常相似,但也有一些API不相似,例如httpx中的Client对象,就可以和Session对象类比学习
下面介绍Client的使用
import httpx with httpx.Client() as client: response = client.get(url='https://www.httpbin.org/get') print(response)
运行结果如下:
<Response [200 OK]>
该方法等价于:
import httpx client = httpx.Client() try: response = client.get('https://www.httpbin.org/get') finally: client.close()
两种方式运行结果一样,只不过需要再最后显式地调用close方法关闭Client对象。
在声明Client对象时可以指定一些参数,例如headers,这样使用该对象发起的所有请求都会默认带上这些参数配置。示例如下:
import httpx url = 'http://www.httpbin.org/headers' headers = {'User-Agent': 'Mozilla/5.0'} with httpx.Client(headers=headers) as client: r = client.get(url) print(r.json()['headers']['User-Agent'])
声明了一个headers变量,内容为User-Agent属性,然后将此变量传递给headers参数,初始化了一个Client对象,并赋值为client变量,最后用client变量请求了测试网站,并打印返回结果
Mozilla/5.0
官方文档:https://www.python-httpx.org/advanced/
支持HTTP/2.0
import httpx client = httpx.Client(http2=True) res = client.get(url='https://httpbin.org/get') print(res.text) print(res.http_version)
支持异步请求
httpx还支持异步客户端请求(即AsyncCkient)支持Python的async请求的模式:
import httpx import asyncio 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'))