本篇介紹如何在 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