新一代的網(wǎng)絡(luò)請(qǐng)求庫(kù) Httpx
HTTPX 是最近 GitHub看的到一個(gè)比較火的一個(gè)項(xiàng)目,根據(jù)官網(wǎng)的描述,總結(jié)有如下特點(diǎn):
和使用 requests 一樣方便,requests 有的它都有
加入 HTTP/1.1 和 HTTP/2 的支持。
能夠直接向 WSGI 應(yīng)用程序或 ASGI 應(yīng)用程序發(fā)出請(qǐng)求。
到處都有嚴(yán)格的超時(shí)設(shè)置
全類型注釋
100% 的測(cè)試覆蓋率
比較不錯(cuò)的一個(gè)特點(diǎn)是全類型注解,這讓我想起了一個(gè)叫 Starlette 的庫(kù),它也是全類型注解的,類型注解主要方便IDE的智能提示,Java 等靜態(tài)類型的語言都有這個(gè)功能,Python 是近期新加的。其他的后面再說吧,我們還是看例子吧。
安裝
httpx 的安裝很簡(jiǎn)單,像其他的 Python 庫(kù)一樣,直接 pip 就完事了
python3?-m?pip?install?httpx
如果需要對(duì) HTTP/2 支持,我們需要額外安裝一個(gè)庫(kù)
python3?-m?pip?install?httpx[http2]
使用示例
import?httpx
r?=?httpx.get('https://www.example.org/')
r.text
r.content
r.json()
r.status_code
基本的用法直接導(dǎo)包然后 get 就行了。其他的和 requests 的使用類似
r?=?httpx.put('https://httpbin.org/put',?data={'key':?'value'})
r?=?httpx.delete('https://httpbin.org/delete')
r?=?httpx.head('https://httpbin.org/get')
r?=?httpx.options('https://httpbin.org/get')
Ok,這是基本用法。
如果需要做一個(gè)爬蟲項(xiàng)目,里面涉及到 Cookie 的傳遞這時(shí)候再這樣就不行了,
httpx 有個(gè) requests 的 Session 類型的使用方法.
import?httpx
client?=?httpx.Client()?#類似requests.Session()
try:
????do?somting
finally:
????client.close()?#關(guān)閉連接池
更優(yōu)雅的方法就是使用 with 上下文管理器的形式
with?httpx.Client()?as?client:
????headers?=?{'X-Custom':?'value'}
????r?=?client.get('https://example.com',?headers=headers)
這里有個(gè)地方需要強(qiáng)調(diào)下 Client 和 get 里面都可以添加 headers,
最后這兩個(gè)地方的 headers 可以合并到請(qǐng)求里,官方的例子
>>>?headers?=?{'X-Auth':?'from-client'}
>>>?params?=?{'client_id':?'client1'}
>>>?with?httpx.Client(headers=headers,?params=params)?as?client:
...?????headers?=?{'X-Custom':?'from-request'}
...?????params?=?{'request_id':?'request1'}
...?????r?=?client.get('https://example.com',?headers=headers,?params=params)
...
>>>?r.request.url
URL('https://example.com?client_id=client1&request_id=request1')
>>>?r.request.headers['X-Auth']
'from-client'
>>>?r.request.headers['X-Custom']
'from-request'
接下來說下大家比較關(guān)心的一點(diǎn)代理的使用,需要注意的是 httpx 的代理只能在 httpx.Client 創(chuàng)建 Client 的實(shí)例的時(shí)候使用,client.get 的時(shí)候沒這個(gè)參數(shù)。
有意思的是它這個(gè)代理可以指定規(guī)則,限制哪些請(qǐng)求使用代理哪些不使用,來個(gè)官方的例子
允許所有請(qǐng)求都走代理
proxies?=?{
????"all://":?"http://localhost:8030",
}
如果字典的值為 None 則表示不使用代理。
不同的協(xié)議走不用的代理
proxies?=?{
????"http://":?"http://localhost:8030",
????"https://":?"http://localhost:8031",
}
http 走 8030 的代理,https 走 8031 的代理,這里要注意和用 requests 使用代理的區(qū)別 requests 是下面這樣用的
proxies?=?{
????"http":?"http://localhost:8030",
????"https":?"http://localhost:8030",
}
綜合使用
你還可以配置多個(gè)規(guī)則像下面這
proxies?=?{
????#?Route?all?traffic?through?a?proxy?by?default...
????"all://":?"http://localhost:8030",
????#?But?don't?use?proxies?for?HTTPS?requests?to?"domain.io"...
????"https://domain.io":?None,
????#?And?use?another?proxy?for?requests?to?"example.com"?and?its?subdomains...
????"all://*example.com":?"http://localhost:8031",
????#?And?yet?another?proxy?if?HTTP?is?used,
????#?and?the?"internal"?subdomain?on?port?5550?is?requested...
????"http://internal.example.com:5550":?"http://localhost:8032",
}
代理就這些,下面看看它的鏈接池的問題
你可以使用 Client 的關(guān)鍵字參數(shù) limits 來控制連接池的大小。它需要以下實(shí)例httpx.Limits 來定義:
max_keepalive,允許的保持活動(dòng)連接數(shù)或 None 始終允許。(預(yù)設(shè)10)
max_connections,允許的最大連接數(shù)或 None 無限制。(默認(rèn)為100)
limits?=?httpx.Limits(max_keepalive_connections=5,?max_connections=10)
client?=?httpx.Client(limits=limits)
如果默認(rèn)鏈接數(shù)不夠用的就自己重新設(shè)置吧。(我感覺是不夠
我這邊只關(guān)注了爬蟲可能用到的部分,其他的大家可以看看官網(wǎng)。比如怎么搭配flask使用等。
好了關(guān)于httpx的同步請(qǐng)求的內(nèi)容大概就這些要提的。如果只講到這里,你肯定會(huì)說,"就這,用 requests 不香么?",emmm,如果這么想你就錯(cuò)了,要知道它不僅支持同步還支持異步的
,使用起來比 aiohttp 簡(jiǎn)單多了,這才是我推薦的目的。
httpx 之異步請(qǐng)求
要知道官網(wǎng)可是單獨(dú)把它拎出一節(jié)講的,可以看出里面應(yīng)該有點(diǎn)東西。
廢話少說,開整。
我們先看在 aiohttp 中是如何創(chuàng)建并發(fā)送請(qǐng)求的
import?aiohttp
import?asyncio
async?def?main():
????async?with?aiohttp.ClientSession()?as?client:
?????????async?with?client.get('http://httpbin.org/get')?as?resp:
??????????????assert?resp.status?==?200
??????????????html=?await?resp.text()
??????????????print(html)
我們需要使用兩個(gè) async with 來完成一個(gè)請(qǐng)求,然后我們看看 httpx 怎么實(shí)現(xiàn)的呢
async?with?httpx.AsyncClient()?as?client:
????resp?=?await?client.get('http://httpbin.org/get')
????assert?resp.status_code?==?200
????html?=?resp.text
感覺總體上比較 aiohttp 寫起來舒服多了,少寫很多異步代碼。
之前使用 aiohttp 中的 resp.status 來獲取狀態(tài)碼的時(shí)候?qū)懥藄tatus_code,應(yīng)該是使用 requests 習(xí)慣了吧,這下好了使用 httpx 不用擔(dān)心這個(gè)寫錯(cuò)的問題了。
后記
最近,我剛把我之前的那個(gè) discogs_aio_spider 的項(xiàng)目給改了,之前用的aiohttp,我現(xiàn)在改成 httpx,對(duì) httpx 感興趣的朋友,可以到上面研究下我這個(gè)項(xiàng)目,有問題歡迎提出。??
項(xiàng)目名:discogs_aio_spider
項(xiàng)目地址:https://github.com/cxapython/discogs_aio_spider
使用到的模塊:asyncio、httpx、motor、aio-pika、aioredis
往期熱門文章:
1、常用正則表達(dá)式速查手冊(cè),Python文本處理必備 2、為什么騰訊/阿里不去開發(fā)被卡脖子的工業(yè)軟件? 3、分析一波,中國(guó)月收入過萬的人真的很多嗎?
好文章需要您的點(diǎn)贊加在看~
↓↓↓↓
