本篇介紹如何在 Python 中使用 HTTPX 這個 HTTP client 模組,建立各種的 HTTP 請求,下載網頁資料。
HTTPX 是一個 Python 3 的多功能 HTTP client 模組,提供了同步(sync)與非同步(async)的 API 介面,支援 HTTP/1.1 與 HTTP/2,可以用來開發各種 HTTP 通訊相關的應用程式。
安裝 HTTPX
若要安裝 HTTPX 基本的 Python 3 模組,可以執行:
# 安裝基本 HTTPX 模組
pip install httpx
若需要使用到 HTTP/2 協定,可議加裝 http2 這個額外功能(extra):
# 安裝 HTTPX 模組(包含 HTTP/2 協定支援)
pip install httpx[http2]
若需要解開 brotli 壓縮格式的資料,則可加裝 brotli 額外功能:
# 安裝 HTTPX 模組(包含 brotli 解碼器)
pip install httpx[brotli]
發送 HTTP 請求
若要發送 GET 請求,可以使用 httpx.get 函數:
import httpx
# 送出 GET 請求
r = httpx.get('https://httpbin.org/json')
# 判斷是否成功取得網頁內容
if r.is_success:
# 取得原始文字內容
text = r.text
# 將 JSON 資料轉為 Python 物件
jsonObj = r.json()
else:
# 取得 HTTP Status Code
statusCode = r.status_code
print(f"Error: {statusCode}")
取得回應之後,可以使用 is_success 判斷是否成功取得網頁內容,正常狀況下我們可以從回應的物件 r 中以 text 屬性取得原始文字的內容,若確定資料內容為 JSON 格式的話,也可以直接用 json() 函數將資料轉為 Python 的物件。若出現問題時可檢查 HTTP 回應的 status code,依照 status code 來判斷問題並尋找解決方式。
除了 GET 請求之外,其他各種 HTTP 請求也都有對應的函數:
# POST 請求
r = httpx.post('https://httpbin.org/post', data={'key': 'value'})
# PUT 請求
r = httpx.put('https://httpbin.org/put', data={'key': 'value'})
# DELETE 請求
r = httpx.delete('https://httpbin.org/delete')
# HEAD 請求
r = httpx.head('https://httpbin.org/get')
# OPTIONS 請求
r = httpx.options('https://httpbin.org/get')
參數傳遞
若要以 GET 方式傳送參數資料,可以使用 params 來指定參數資料:
# 參數資料
params = {'key1': 'value1', 'key2': 'value2'}
# 以 GET 方式傳遞參數資料
r = httpx.get('https://httpbin.org/get', params=params)
# 檢視 HTTP 請求的 URL
print(r.url)
https://httpbin.org/get?key1=value1&key2=value2
我們也可以採用列表(list)的寫法來指定參數資料:
# 參數資料
params = {'key1': 'value1', 'key2': ['value2', 'value3']}
# 以 GET 方式傳遞參數資料
r = httpx.get('https://httpbin.org/get', params=params)
# 檢視 HTTP 請求的 URL
print(r.url)
https://httpbin.org/get?key1=value1&key2=value2&key2=value3
HTTP 回應資料編碼
HTTPX 會自動採用適合的編碼來處理接收到的資料:
import httpx
r = httpx.get('https://tw.yahoo.com/')
# 取得 HTML 內容
htmlContent = r.text
# 取得編碼
print(r.encoding)
UTF-8
我們也可以自行指定編碼,讓 HTTPX 以自訂的編碼來解析接收到的文字資料:
# 自行指定編碼
r.encoding = 'Big5'
# 取得 HTML 內容
htmlContent = r.text
二進位資料處理
回應資料的二進位內容可以透過 content 屬性來取得:
import httpx
r = httpx.get('https://httpbin.org/get')
# 取得二進位內容
binContent = r.content
HTTPX 會自動解壓縮任何以 gzip 或 deflate 壓縮的資料,另外如果系統有安裝 brotlipy 模組,也會自動解壓縮 brotli 壓縮的資料。
若要下載圖片,可以搭配其他圖片相關的模組來處理:
import httpx
from PIL import Image
from io import BytesIO
# 下載圖片
r = httpx.get('https://www.example.com/image.jpg')
# 讀取圖片資料
img = Image.open(BytesIO(r.content))
傳送檔案
若要上傳檔案,可以使用 files 指定要上傳的檔案清單:
import httpx
# 要上傳的檔案
files = {'upload-file': open('report.xls', 'rb')}
# 上傳檔案
r = httpx.post("https://httpbin.org/post", files=files)
傳送 JSON 格式資料
對於結構比較複雜的資料,可以使用 JSON 格式的方式來傳送:
import httpx
# 要上傳的結構化資料
data = {'integer': 123, 'boolean': True, 'list': ['a', 'b', 'c']}
# 以 JSON 格式上傳結構化資料
r = httpx.post("https://httpbin.org/post", json=data)
串流下載
當下載大量資料時,可以考慮使用串流的方式來處理資料,避免所有資料一次放進記憶體中,佔用太多記憶體資源:
import httpx
# 二進位串流處理
with httpx.stream("GET", "https://www.example.com") as r:
for data in r.iter_bytes():
print(data)
# 文字串流處理
with httpx.stream("GET", "https://www.example.com") as r:
for text in r.iter_text():
print(text)
# 逐行文字串流處理
with httpx.stream("GET", "https://www.example.com") as r:
for line in r.iter_lines():
print(line)
若要對原始資料(未解壓縮)進行串流處理,可以參考以下方式:
# 原始資料(未解壓縮)串流處理
with httpx.stream("GET", "https://www.example.com") as r:
for chunk in r.iter_raw():
print(chunk)
命令列 httpx 指令工具
除了標準的 Python 3 模組之外,HTTPX 同時也提供了命令列的指令工具,讓使用者直接使用簡單的指令即可建立 HTTP 請求。若需要 HTTPX 的指令工具,可以使用以下指令安裝:
# 安裝 HTTPX 模組(包含命令列指令)
pip install httpx[cli]
以下是一些常用的 httpx 指令範例。
傳送基本的 GET 請求:
# 傳送基本 GET 請求
httpx https://httpbin.org/get
若要在 GET 請求中附帶參數,可以使用 -p 或 --params 只定參數的名稱與值:
# 在 GET 請求中附帶參數
httpx -p var1 value1 -p var2 value2 https://httpbin.org/get
若要以 POST 送出表單資料,可以使用 -m 或 --method 指定採用 POST 方式,並以 -d 或 --data 指定資料參數的名稱與值:
# 以 POST 送出表單資料
httpx -m POST -d var1 value1 -d var2 value2 https://httpbin.org/post
若要傳送檔案,可以用 -f 或 --files 參數指定檔案名稱與檔案路徑:
# 以 POST 送出檔案
httpx -m POST -f my_name.jpg /path/my_file.jpg https://httpbin.org/post
若要設定 cookies,可以使用 --cookies 參數指定 cookies 的名稱與值:
# 設定 cookies
httpx --cookies var1 value1 --cookies var2 value2 https://httpbin.org/get
若要發送 JSON 格式的資料,可以使用 -j 或 --json 餐數指定 JSON 格式的字串資料:
# 以 POST 傳送 JSON 資料
httpx -m POST -j '{"A":1}' https://httpbin.org/post
其餘更多 httpx 的參數用法可以使用 --help 參數查詢:
# 查詢 httpx 指令與參數用法
httpx --help
