Python URL 解析練習:拼接、查詢與清理
很多重複連結並不是真的重複,而是同一個目的地的四種寫法。這些練習把 URL 字串拆成組成部分,基於頁面補全,再重建成規範值。
讀取每個組成部分
先給每個部分命名。scheme 表示協議,netloc 是主機和埠,path 是資源路徑,query 是參數,fragment 是頁內錨點。每個部分在抓取中承擔不同職責。
from urllib.parse import urlparse
url = urlparse("https://example.com:8080/docs?q=python#intro")
print(url.scheme)
print(url.netloc)
print(url.path)
print(url.query)
print(url.fragment)給每個部分命名
基於頁面補全
連結相對於包含它的頁面。urljoin 能處理 ../、根相對路徑和只有查詢參數的引用。儲存前先補全,佇列才不會把一個目的地當成多個頁面。
from urllib.parse import urljoin
base = "https://example.com/docs/guide/page.html"
for href in ["../index.html", "/about", "?page=2"]:
print(urljoin(base, href))三種相對寫法
讀取重複的查詢鍵
parse_qs 回傳列表,即使鍵只出現一次。這是有意的:查詢字串可以重複鍵。只有 API 明確說明單值時,才取第一個值;數字在計算前要顯式轉換。
from urllib.parse import parse_qs
params = parse_qs("tag=python&tag=web&page=2")
print(params["tag"])
print(int(params["page"][0]) + 1)先拿列表,再顯式轉換
編碼新的查詢字串
urlencode 會跳脫空格和保留字元。搜尋表單和分頁連結都應使用它。傳入鍵值對列表可以保留重複鍵和順序,普通字典無法保證這一點。
from urllib.parse import urlencode
query = urlencode([("q", "a b"), ("tag", "python"), ("tag", "web")])
print(query)編碼鍵值對,保留重複
去重前去掉片段
# 後面的片段是給瀏覽器用的,不屬於伺服器請求。把頁面加入 visited 集合前先去掉它。如果需要記錄連結來源,可以另外保留原始 URL。
from urllib.parse import urlsplit, urlunsplit
parts = urlsplit("https://example.com/docs?q=1#section-2")
clean = urlunsplit((parts.scheme, parts.netloc, parts.path, parts.query, ""))
print(clean)一個規範頁面位址
你的練習清單
- 用 urlparse 拆分 URL,而不是手工切字串。
- 去重前用 urljoin 補全相對連結。
- 把 parse_qs 的回傳值當作列表處理。
- 使用者輸入和重複查詢鍵用 urlencode 編碼。
- 比較頁面 URL 前去掉片段。
常見問題
urljoin 會驗證目的地嗎?
不會。它只做語法上的補全。仍然需要檢查協議、主機和抓取規則。
為什麼 parse_qs 回傳列表?
查詢字串可能包含重複鍵,只保留一個值會丟失資訊。
應該把整個 URL 轉成小寫嗎?
不應該。主機名不區分大小寫,但路徑和查詢值可能區分。只規範化你了解規則的部分。
練習 URL 解析
12 道題,覆蓋 urlparse、urljoin、查詢字串、編碼和片段。
繼續閱讀: