Python requests 網路請求

在 Python 網頁開發或是 API 串接的過程中,處理 HTTP 請求是核心任務。雖然 Python 內建了 urllib 模組,但其介面設計較為原始且繁瑣。Requests 是一個「專為人類設計」(HTTP for Humans) 的第三方函式庫,它將複雜的 HTTP 通訊封裝成簡潔且語意化的 API,是目前業界處理 API 調用與網頁抓取的標準工具。

安裝 Requests

Requests 是第三方套件,請先確保你的環境中已安裝 pip,然後執行:

pip install requests

基礎語法:GET 與 POST 請求

1. GET 請求 (取得資料)

GET 請求主要用於向伺服器索取資源。你可以直接將變數透過 params 參數傳遞,Requests 會自動處理 URL 編碼。

import requests

# 取得 GitHub API 搜尋專案資料
url = "https://api.github.com/search/repositories"
params = {
    "q": "python",
    "sort": "stars",
    "order": "desc"
}

response = requests.get(url, params=params)

# 快速查看最終產生的 URL
print(f"最終請求 URL: {response.url}")

if response.status_code == 200:
    # Requests 內建 JSON 解析器
    data = response.json()
    items = data.get('items', [])
    print(f"熱門 Python 專案數量: {data.get('total_count')}")
    for item in items[:3]:
        print(f"- {item['name']}: {item['stargazers_count']} stars")

2. POST 請求 (提交資料)

POST 請求常用於提交表單或傳送 JSON 內容給伺服器,例如新增資料或登入。

import requests

url = "https://httpbin.org/post"
payload = {"username": "mike_lee", "role": "admin"}

# 方式 A:提交傳統表單格式 (application/x-www-form-urlencoded)
response_form = requests.post(url, data=payload)

# 方式 B:提交 JSON 格式 (現代 API 與 RESTful 的標準做法)
# 使用 json 參數時,Requests 會自動將 dict 轉為 JSON 並加上正確的 Header
response_json = requests.post(url, json=payload)

print(f"JSON 請求狀態: {response_json.status_code}")

回應物件 (Response Object) 詳解

當你執行請求後,會回傳一個 Response 物件。為了有效處理資料,你必須了解其常用屬性與方法:

屬性/方法用途說明
status_codeHTTP 狀態碼 (如 200: 成功, 404: 找不到, 500: 伺服器錯誤)
ok布林值,若狀態碼小於 400 則為 True
text回應字串內容 (Requests 會根據 Header 自動推測編碼)
content二進位內容 (通常用於下載圖片、PDF 或壓縮檔)
json()將回應內容解析為 Python 字典 (若回應非 JSON 會拋出 ValueError)
headers回應的標頭資訊 (Dictionary 格式)
cookies伺服器回傳的 Cookie
request原始請求物件,可用於檢查發出的 Header

進階實務技巧

1. 自定義 Headers 與 User-Agent

許多網站會檢查 User-Agent 來分辨你的身分。如果沒設定,預設的 User-Agent 會顯示為 python-requests/x.x.x,這在某些網站會被直接封鎖。

custom_headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
    "Accept-Language": "zh-TW,zh;q=0.9",
    "Authorization": "Bearer YOUR_ACCESS_TOKEN"
}

response = requests.get("https://example.com/api", headers=custom_headers)

如果你需要執行一系列相關的請求(例如:先登入,再讀取會員資料),應使用 Session

# 建立 Session 物件
session = requests.Session()

# 設定 Session 層級的共通 Headers (所有透過此 session 發出的請求都會帶上)
session.headers.update({"x-test": "true"})

# 第一次請求:假設這會取得 Login Cookie
session.post("https://httpbin.org/cookies/set/session_token/xyz123")

# 第二次請求:會自動帶上剛才取得的 Cookie,且連線會被重用 (Pooling) 提升效能
response = session.get("https://httpbin.org/cookies")
print(response.json())

3. 超時設定與例外處理

網路請求可能因為伺服器忙碌或連線問題而卡住。在正式環境中,永遠應該設定 timeout

from requests.exceptions import HTTPError, Timeout, ConnectionError

try:
    # timeout=(連線超時, 讀取超時),單位為秒
    response = requests.get("https://api.github.com", timeout=(3.05, 27))

    # 若狀態碼非 2xx,主動引發異常
    response.raise_for_status()

except Timeout:
    print("請求超時,請稍後再試")
except ConnectionError:
    print("網路連線失敗,請檢查網路設定")
except HTTPError as http_err:
    print(f"HTTP 錯誤發生: {http_err}")
except Exception as err:
    print(f"其他不可預知的錯誤: {err}")

4. 檔案下載與串流回應

處理大檔案時,不可使用 response.content 一次讀進記憶體,這會導致 OOM (記憶體溢出)。應使用 stream=True

url = "https://example.com/large-file.zip"

with requests.get(url, stream=True) as r:
    r.raise_for_status()
    with open("local_file.zip", "wb") as f:
        # 每次寫入 8KB
        for chunk in r.iter_content(chunk_size=8192):
            f.write(chunk)

5. 認證機制 (Authentication)

Requests 簡化了常見的認證流程:

# Basic Auth (帳號, 密碼)
from requests.auth import HTTPBasicAuth
requests.get("https://api.example.com", auth=HTTPBasicAuth('user', 'pass'))

# 簡寫格式
requests.get("https://api.example.com", auth=('user', 'pass'))

結語

Requests 的強大在於它隱藏了底層 Socket 通訊與協定握手的複雜性,讓開發者能專注於業務邏輯。

  • 快速原型:直接使用 requests.get/post
  • 效能與狀態:使用 requests.Session()
  • 安全性:設定 timeout、正確處理 raise_for_status()

學會 Requests 之後,你可以進一步結合 BeautifulSoup 開發爬蟲,或者串接各大服務的 RESTful API,這是踏入後端開發與資料工程的必修課。