Python 使用 urllib.parse.unquote() 解碼 URL 編碼字串,會將字串中每一個 %XX 序列替換為其所代表的位元組,並以一般 Python str 形式回傳結果。這一個呼叫就能處理常見的情況——把 Hello%2C%20World%21 還原成 Hello, World!——而且它是標準函式庫內建的功能,無須額外安裝任何東西。同一個模組也提供 unquote_plus(),會再把 + 轉成空白字元,行為與 application/x-www-form-urlencoded 解析器相同;另外還有 quote() 和 quote_plus() 可執行反向編碼。對大多數開發者來說,這就是完整的工具箱。代價在於每次撰寫腳本仍需要花上幾分鐘:開啟 REPL、貼上字串、印出結果、再複製出來。如果你想直接把編碼後的字串貼進一個方框,看它即時變成可讀文字,然後複製結果,那麼基於瀏覽器的 URL 解碼器 就能在不寫任何程式碼的情況下完成這件事。

how to decode url in python
如何在不寫程式碼的情況下用 Python 解碼 URL

Python 的 urllib.parse.unquote 實際上做了什麼

urllib.parse 模組已成為 Python 標準函式庫的一部分多年,其解碼端的功能小到幾分鐘就能學會。基本函式呼叫為 urllib.parse.unquote(string, encoding='utf-8', errors='replace')——你傳入一個百分比編碼字串,就會拿回解碼後的版本。對應的 unquote_plus() 做的事相同,另外會把 + 轉為空白字元,以符合較早期的表單編碼慣例。反向編碼則由 quote() 與 quote_plus() 負責。

這兩個函式看起來幾乎一模一樣,但在一個細節上有所不同。unquote() 會保留 + 不動,因此當你要解碼的是任意 URL 或使用標準百分比編碼的查詢字串值時,它是正確的選擇。unquote_plus() 則會把 + 轉為空白字元,以符合較早期 HTML 表單使用 + 而非 %20 來表示空白的慣例。兩個函式預設都將輸入視為 UTF-8,這表示表情符號、帶變音符號的字母以及 CJK 字元都能正確往返——一個中文問候語在編碼時會變成六組百分比編碼,解碼時又能還原為原本的字元。

在編碼方面,quote() 接受一個 safe 引數,對應到瀏覽器工具中的範圍選擇器,而且和該工具一樣,它遵循 RFC 3986 中所制定的規則,決定哪些字元必須一律跳脫。

逐步解碼 Python 中的 URL

對於偏好留在 Python 環境內、不想打開瀏覽器的開發者來說,整個工作流程只需要四個簡短的呼叫:

  1. 匯入解析器。在你的檔案或 REPL 工作階段頂端,使用 from urllib.parse import unquote, unquote_plus 匯入 urllib.parse。
  2. 選擇正確的函式。若為標準 URL 或查詢值,且其中的 + 代表字面上的加號,請使用 unquote()。若來源是表單編碼的 body 資料,且 + 代表空白字元,則請使用 unquote_plus()。
  3. 傳入編碼後的字串。函式會以一般 Python 字串形式回傳解碼結果。例如,unquote("Hello%2C%20World%21") 會回傳 Hello, World!,而 unquote_plus("name=Jane+Doe") 會回傳 name=Jane Doe。
  4. 處理錯誤情況。單獨的百分比符號或無效的十六進位配對會引發 ValueError 或 UnicodeDecodeError。若要解碼不受信任的輸入,請將呼叫包進 try/except 區塊,並決定要顯示錯誤、替換有問題的序列,還是直接略過該值。

這就是 Python 中用於 URL 解碼的完整工具箱。對於剪貼簿中只有一筆字串的一次性解碼工作,瀏覽器工具能完全略過第 1、2 與 4 步。

什麼時候瀏覽器工具勝過執行腳本

當解碼是某個較大型程式的一部分時——例如你需要讀取某個參數、清理一行日誌,或在請求處理器中對某個位址進行標準化——Python 就是正確的解法。對一次性工作來說,撰寫腳本的成本會累積起來:你要打開終端機、匯入模組、貼上字串、印出結果、再複製出來。基於瀏覽器的解碼器則將所有步驟壓縮成一個動作:貼上、查看結果、複製。

這個權衡很直白,值得明說。Python 執行在資料所在的程式內部,因此能在請求時、迴圈中,或資料清理管線的一部分進行解碼。瀏覽器工具則是在另一個獨立視窗中執行,給你一段要手動複製的字串。兩者並非競爭關係,而是涵蓋同一工作流程上的不同節點。如果編碼後的字串存在於日誌檔、資料庫記錄或 JSON 回應中,Python 勝出。如果編碼後的字串就在你的剪貼簿中——因為同事把連結貼到了聊天視窗——瀏覽器工具勝出。

在瀏覽器中解碼 URL

  1. 在任何現代瀏覽器中開啟 URL 解碼器。該工具只需載入一次,即使之後離線也能繼續運作。
  2. 選擇範圍。若要解碼的是單一查詢值或路徑片段,請選擇 URL component;若要解碼整個網址,並希望冒號、斜線與井字號等結構性字元保持不變,則請選擇 Full URL。
  3. 將方向設定為 Decode。
  4. 將百分比編碼後的文字貼入輸入框。輸入時結果會即時更新;任何格式錯誤的輸入——單獨的百分比符號、無效的十六進位配對,或被截斷的多位元組序列——都會顯示清楚的錯誤訊息,而不是悄悄產生一段壞掉的字串。
  5. 點擊 Copy 將解碼結果放入剪貼簿,即可貼入網址列、聊天訊息或程式碼編輯器中使用。

同一個畫面只要按一下就能切換為編碼模式,當你讀完某個值、想把它送回 URL 中,並且需要整個往返過程落到與最初相同的位元組時,這個功能非常實用。

元件模式 vs 完整 URL 模式

工具中的兩個範圍對應到兩種不同的工作,選錯範圍正是解碼後的網址看起來不對的最常見原因。

元件模式 將輸入視為 URL 中的一個片段:一個查詢值、一個路徑片段,或一個片段識別碼。它會跳脫所有保留字元,包括 &、=、/、? 與 #,因此你的值不會被誤認為分隔符而破壞周圍的網址。它也會跳脫 RFC 3986 的次分隔符 !'()*——某些伺服器與簽章機制會特別處理這些字元——這也是為什麼此模式對應到 Python 的 quote(safe='') 呼叫結果,也是手動組裝查詢字串時你想要的行為。

完整 URL 模式 將輸入視為一個完整的網址。它會保留結構性字元——冒號、斜線、問號、井字號——只跳脫真正不安全的部分,例如空白與非 ASCII 字母。若你將完整的 https://example.com/search?q=hello%20world 貼進元件模式,工具會把冒號與斜線連同編碼過的空白一起跳脫,最後得到的結果將不再是可解析的 URL。

面向URL 元件模式完整 URL 模式
最適用於單一查詢值、單一路徑片段、單一片段識別碼你想整理的完整網址
跳脫 &, =, ?, #, /是否——保留為結構性字元
跳脫 !'()*是(RFC 3986 次分隔符)否
跳脫空白與非 ASCII是是
對應的 Python 寫法quote(safe='')quote(safe='/:?#') 或對整個網址使用 urlencode

格式錯誤的輸入如何被回報

解碼正是錯誤輸入最容易出問題的地方。單獨的 %、% 後接非有效十六進位數字(例如 %zz),或被截斷的多位元組序列,都無法被還原成真實的字元。Python 的 unquote() 在遇到這類輸入時會引發 ValueError 或 UnicodeDecodeError,而一個小腳本可能會把它吞掉,或印出你需要捲動瀏覽的堆疊追蹤。瀏覽器工具則會停下來,清楚告訴你哪裡出了錯,讓你能修正來源字串,而不是把損毀的資料往下游傳遞。

當你在除錯重新導向迴圈、OAuth 回呼,或某個不是你建立的帶參數追蹤連結時,這一點最為關鍵。在這種情況下,你最不希望遇到的,就是一個默默遞給你問號或替代字元的安靜解碼器——明明該是真正的字元才對。

常見的百分比編碼值

下表列出你在真實 URL 中最常會遇到的百分比編碼形式。這些值是由 URL 標準所定義而非計算得出,因此可以放心記住,並一眼認出來。

編碼解碼出現位置
%20空白查詢字串、路徑
%2C,單一值內部的列表
%3A:偶爾出現在路徑或值中
%2F/查詢值中夾帶的斜線
%3F?值中的字面問號
%23#值中的字面井號
%26&值中的字面 & 符號
%3D=值中的字面等號
+空白(僅適用於表單編碼)application/x-www-form-urlencoded 內文

Everyday Tasks You Can Hand Off to the Tool

The browser tool covers the same set of one-off jobs that Python's unquote() covers inside a script, just without the script. The most common are reading a link someone shared so you can see the human text behind the percent signs, checking what a tracking parameter actually contains, building an OAuth callback URL where the entire address has to be carried inside another parameter, escaping values for an API request you are about to copy into curl, and tidying a redirect URL before pasting it into a config file. All of these are paste-and-go on the decoder side, and all of them stay on your device because the entire pipeline runs in plain JavaScript inside the browser tab.

For the cases where the encoded string is inside a larger data flow, Python is still the right tool. For the cases where the encoded string is sitting in your clipboard and you just want to read it, the URL Decoder is the faster path.

Related reading: ASCII Code Converter Example: Text to Decimal and Back.

Related reading: Decode Base32 From the Command Line vs Your Browser.