Python網絡請求庫httpx詳解


簡介

httpx是Python新一代的網絡請求庫,它包含以下特點

  • 基於Python3的功能齊全的http請求模塊
  • 既能發送同步請求,也能發送異步請求
  • 支持HTTP/1.1和HTTP/2
  • 能夠直接向WSGI應用程序或者ASGI應用程序發送請求

安裝

httpx需要Python3.6+(使用異步請求需要Python3.8+)

pip3 install httpx
或
python3 -m pip install httpx

如果需要使用HTTP/2,則需要安裝http2的相關依賴

pip3 install httpx[http2]
或
python3 -m pip install httpx[http2]

使用

簡單使用

httpx與requests庫的基本使用方法幾乎是一模一樣的

import httpx

r = httpx.get('https://httpbin.org/get')
print(r)  # <Response [200 OK]>

類似的,我們也可以使用POST, PUT, DELETE, HEADOPTIONS等請求方法,如下

r = httpx.post('https://httpbin.org/post', data={'key': 'value'})
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')

帶有請求頭和請求參數的請求

import httpx

headers = {'user-agent': 'my-app/1.0.0'}
params = {'key1': 'value1', 'key2': 'value2'}
url = 'https://httpbin.org/get'
r = httpx.get(url, headers=headers, params=params)
print(r)
print(r.status_code)  # 狀態碼
print(r.encoding)  # 文本編碼
print(r.text)
print(r.json())

結果如下

<Response [200 OK]>
200
ascii
{
  "args": {
    "key1": "value1", 
    "key2": "value2"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "my-app/1.0.0", 
    "X-Amzn-Trace-Id": "Root=1-6139b788-2fd67d5627a5f6de346e154a"
  }, 
  "origin": "113.110.227.200", 
  "url": "https://httpbin.org/get?key1=value1&key2=value2"
}

{'args': {'key1': 'value1', 'key2': 'value2'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'my-app/1.0.0', 'X-Amzn-Trace-Id': 'Root=1-6139b788-2fd67d5627a5f6de346e154a'}, 'origin': '113.110.227.200', 'url': 'https://httpbin.org/get?key1=value1&key2=value2'}

請求帶有cookies

import httpx

url = 'http://httpbin.org/cookies'
cookies = {'color': 'green'}
r = httpx.get(url, cookies=cookies)
print(r.json())  # {'cookies': {'color': 'green'}}

設置超時時間

import httpx

r = httpx.get('http://httpbin.org', timeout=0.001)
print(r)

超過設置時間則報httpx.ConnectTimeout: timed out

高級用法

我們使用上面的請求方式時,httpx每次發送請求都需要建立一個新的連接,然而隨着請求的數量增加,整個程序的請求效率就會變得很低。

httpx提供了Client來解決以上問題,Client是基於HTTP連接池實現的,這意味着當你對一個網站發送多次請求的時候,Client會保持原有的TCP連接,從而提升程序的執行效率。

使用Client發送請求

創建一個client對象,使用該對象去做相應的請求

import httpx

with httpx.Client() as client:
    headers = {'X-Custom': 'value'}
    r = client.get('https://example.com', headers=headers)
    print(r.text)

跨請求共享配置

我們可以將headerscookiesparams等參數放在http.Client()中,在Client下的請求共享這些配置參數

import httpx

headers1 = {'x-auth': 'from-client'}
params1 = {'client_id': '1234'}
url = 'https://example.com'
with httpx.Client(headers=headers1, params=params1) as client:
    headers2 = {'x-custom': 'from-request'}
    params2 = {'request_id': '4321'}
    r1 = client.get(url)
    print(r1.request.headers)
    r2 = client.get(url, headers=headers2, params=params2)
    print(r2.request.headers)

結果如下

Headers({'host': 'example.com', 'accept': '*/*', 'accept-encoding': 'gzip, deflate', 'connection': 'keep-alive', 'user-agent': 'python-httpx/0.19.0', 'x-auth': 'from-client'})
Headers({'host': 'example.com', 'accept': '*/*', 'accept-encoding': 'gzip, deflate', 'connection': 'keep-alive', 'user-agent': 'python-httpx/0.19.0', 'x-auth': 'from-client', 'x-custom': 'from-request'})

可以看出,r1的請求頭包含{'x-auth': 'from-client'}, r2雖然配置了headers2,但由於里面的headers1和headers2的參數不同,Client會合並這兩個headers的參數作為一個新的headers(如果參數相同,則headers2的參數會覆蓋headers1的參數)。

HTTP代理

httpx可以通過設置proxies參數來使用http代理,我們也可以使用不同的代理來分別處理http和https協議的請求,假設有如下兩個代理

import httpx

proxies = {
    'http://': 'http://localhost:8080',  # 代理1
    'https://': 'http://localhost:8081',  # 代理2
}
url = 'https://example.com'
with httpx.Client(proxies=proxies) as client:
    r1 = client.get(url)
    print(r1)

上面的代理只是示范,實際場景下請替換成有效的ip代理

還有一點需要注意的是,httpx的代理參數proxies只能在httpx.Client()中添加,client.get()是沒有這個參數的。

超時處理

默認情況下,httpx到處都做了嚴格的超時處理,默認時間為5秒,超過5秒無響應則報TimeoutException

# 普通請求:
httpx.get('http://example.com/api/v1/example', timeout=10.0)

# client實例:
with httpx.Client() as client:
    client.get("http://example.com/api/v1/example", timeout=10.0)

或者關閉超時處理

# 普通請求:
httpx.get('http://example.com/api/v1/example', timeout=None)

# client實例:
with httpx.Client() as client:
    client.get("http://example.com/api/v1/example", timeout=None)

SSL驗證

當請求https協議的鏈接時,發出的請求需要驗證所請求主機的身份,因此需要SSL證書來取得服務器的信任后。

如果要使用自定義的CA證書,則可以使用verify參數

import httpx

r = httpx.get("https://example.org", verify="path/to/client.pem")

或者你可以完全禁用SSL驗證(不推薦)。

import httpx

r = httpx.get("https://example.org", verify=False)

異步支持

默認情況下,httpx使用標准的同步請求方式,如果需要的話,我們也可以使用它提供的異步client來發送相關請求。

使用異步client比使用多線程發送請求更加高效,更能體現明顯的性能優勢,並且它還支持WebSocket等長網絡連接。

異步請求

使用async/await語句來進行異步操作,創建一個httpx.AsyncClient()對象

import asyncio
import httpx


async def main():
    async with httpx.AsyncClient() as client:  # 創建一個異步client
        r = await client.get('https://www.example.com/')
        print(r)


if __name__ == '__main__':
    asyncio.run(main())

同步請求與異步請求的比較

我們來嘗試使用同步和異步的方法進行請求,對比兩種不同的方法的效率情況。

同步請求

import time
import httpx


def main():
    with httpx.Client() as client:
        for i in range(300):
            res = client.get('https://www.example.com')
            print(f'第{i + 1}次請求,status_code = {res.status_code}')


if __name__ == '__main__':
    start = time.time()
    main()
    end = time.time()
    print(f'同步發送300次請求,耗時:{end - start}')

同步發送300次請求,耗時:49.65340781211853

異步請求

import asyncio
import time
import httpx


async def req(client, i):
    res = await client.get('https://www.example.com')
    print(f'第{i + 1}次請求,status_code = {res.status_code}')
    return res


async def main():
    async with httpx.AsyncClient() as client:
        task_list = []  # 任務列表
        for i in range(300):
            res = req(client, i)
            task = asyncio.create_task(res)  # 創建任務
            task_list.append(task)
        await asyncio.gather(*task_list)  # 收集任務


if __name__ == '__main__':
    start = time.time()
    asyncio.run(main())
    end = time.time()
    print(f'異步發送300次請求,耗時:{end - start}')

異步發送300次請求,耗時:2.5227813720703125 (由於是異步執行的,所以打印的i值是無序的)

從兩個例子可以看出,異步請求明顯比同步請求的效率高很多。

以上就是httpx庫的基本使用方法,想了解更多可以去httpx官方文檔中查看。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM