PythonでURLを安全に扱う:urllib.parse.quoteとunquoteの徹底解説
Web開発やデータ収集において、URLエンコードとデコードは避けて通れない重要なプロセスです。URLには、特定の文字(例: スペース、日本語、特殊記号)を含めることができません。これらの文字をURLに安全に含めるために、URLエンコード(パーセントエンコーディングとも呼ばれる)が必要になります。
Pythonの標準ライブラリであるurllib.parseモジュールには、URLエンコードを行う**quote関数と、デコードを行うunquote関数**が用意されています。この記事では、これらの関数の使い方を具体的なサンプルコードを交えながら、分かりやすく解説します。短いコード例で、URL操作の基礎をマスターしましょう。
目次
URLエンコード・デコードの必要性
なぜURLのエンコード・デコードが必要なのでしょうか?それは、URLが扱うことのできる文字に制限があるからです。
URLの制約
URLは、RFC 3986などの仕様によって使用できる文字が厳密に定められています。英数字と一部の記号(-, _, ., ~など)は直接使用できますが、それ以外の文字(日本語、スペース、?, &, #などの特殊記号)は、そのままではURLとして解釈されません。
文字化けやエラーの防止
例えば、URLにスペースが含まれると、ブラウザやサーバーはそれを別の意味で解釈したり、エラーを発生させたりする可能性があります。日本語のような非ASCII文字も同様に扱えません。これらを防ぐために、これらの文字を%XX(XXは16進数の文字コード)形式に変換するのがURLエンコードです。
エンコード(encode): 安全でない文字を
%XX形式に変換するプロセスデコード(decode):
%XX形式の文字を元の文字に戻すプロセス
PythonでURLエンコードする:urllib.parse.quote
urllib.parse.quote関数は、指定された文字列をURLエンコードします。これは、URLのパス部分やクエリパラメータの値をエンコードする際に特に役立ちます。
基本的な使い方
from urllib.parse import quote
# 日本語とスペースを含む文字列
text_to_encode = "PythonでURL エンコード"
# 文字列をURLエンコード
encoded_text = quote(text_to_encode)
print(f"元の文字列: {text_to_encode}")
print(f"エンコード後: {encoded_text}")
# 出力例:
# 元の文字列: PythonでURL エンコード
# エンコード後: Python%E3%81%A7URL%20%Eエンコード
上記の例では、日本語の「で」が%E3%81%A7に、スペースが%20に変換されています。
エンコードする文字を制御する:safe引数
quote関数にはsafe引数があり、エンコードせずにそのままにしておく文字を指定できます。デフォルトでは/がsafeに含まれていないため、/もエンコードされます。URLのパス部分をエンコードする際には、/をエンコードしないようにsafe引数で指定することがよくあります。
from urllib.parse import quote
# スラッシュを含むパスのような文字列
path_to_encode = "data/ファイル名 with スペース.txt"
# スラッシュをエンコードしない場合 (safe='/')
encoded_path_safe_slash = quote(path_to_encode, safe='/')
# スラッシュもエンコードする場合 (デフォルト)
encoded_path_default = quote(path_to_encode)
print(f"元のパス: {path_to_encode}")
print(f"スラッシュをsafeにした場合: {encoded_path_safe_slash}")
print(f"デフォルトの場合: {encoded_path_default}")
# 出力例:
# 元のパス: data/ファイル名 with スペース.txt
# スラッシュをsafeにした場合: data/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%90%8D%20with%20%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9.txt
# デフォルトの場合: data%2F%E3%83%95%E3%83%A3%E3%82%A4%E3%83%AB%E5%90%8D%20with%20%E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9.txt
この例からわかるように、safe引数を適切に設定することで、URLの各部分(パス、クエリパラメータ、フラグメントなど)の特性に合わせて柔軟にエンコードできます。
PythonでURLデコードする:urllib.parse.unquote
urllib.parse.unquote関数は、quote関数でエンコードされた文字列を元の形に戻します。Webから取得したURLや、エンコードされたクエリパラメータの値を処理する際に利用します。
from urllib.parse import unquote
# エンコードされたURL文字列
encoded_url_string = "https://example.com/search?q=%E3%83%91%E3%82%A4%E3%82%BD%E3%83%B3+%E3%83%87%E3%83%BC%E3%82%BF%E5%8F%96%E5%BE%97"
# クエリパラメータ部分だけをデコードしたい場合
# まずはクエリ文字列を抽出
from urllib.parse import urlparse
parsed_url = urlparse(encoded_url_string)
query_string = parsed_url.query
# クエリ文字列をデコード
decoded_query_string = unquote(query_string)
print(f"元のURL文字列: {encoded_url_string}")
print(f"デコードされたクエリ文字列: {decoded_query_string}")
# 出力例:
# 元のURL文字列: https://example.com/search?q=%E3%83%91%E3%82%A4%E3%82%BD%E3%83%B3+%E3%83%87%E3%83%BC%E3%82%BF%E5%8F%96%E5%BE%97
# デコードされたクエリ文字列: q=Python データ取得
unquoteは+もスペースにデコードします。これは、application/x-www-form-urlencoded形式で使われる+記号(スペースの代わり)も正しく処理するためです。
quoteとquote_plus、unquoteとunquote_plusの違い
urllib.parseにはquote_plusとunquote_plusという似た名前の関数もあります。これらは、主にWebフォームのデータ(application/x-www-form-urlencoded)を扱う際に役立ちます。
quotevsquote_plus:quote: スペースを%20にエンコードします。quote_plus: スペースを+にエンコードします。Webフォームのデータ送信でよく使われます。
unquotevsunquote_plus:unquote:%XX形式のみをデコードし、+はそのまま残します。unquote_plus:%XX形式に加え、+もスペースにデコードします。
from urllib.parse import quote, quote_plus, unquote, unquote_plus
text = "スペース と + 記号"
# quote と quote_plus の比較
encoded_quote = quote(text)
encoded_quote_plus = quote_plus(text)
print(f"元の文字列: {text}")
print(f"quoteでエンコード: {encoded_quote}")
print(f"quote_plusでエンコード: {encoded_quote_plus}")
# unquote と unquote_plus の比較
# quote_plusでエンコードしたものをデコード
decoded_unquote = unquote(encoded_quote_plus)
decoded_unquote_plus = unquote_plus(encoded_quote_plus)
print(f"quote_plusでエンコードしたもの:")
print(f" unquoteでデコード: {decoded_unquote}")
print(f" unquote_plusでデコード: {decoded_unquote_plus}")
# 出力例:
# 元の文字列: スペース と + 記号
# quoteでエンコード: %E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9%20%E3%81%A8%20%2B%20%E8%A8%98%E5%8F%B7
# quote_plusでエンコード: %E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9+%E3%81%A8+%2B+%E8%A8%98%E5%8F%B7
# quote_plusでエンコードしたもの:
# unquoteでデコード: %E3%82%B9%E3%83%9A%E3%83%BC%E3%82%B9 + %E3%81%A8 + %2B + %E8%A8%98%E5%8F%B7 # ここがポイント!
# unquote_plusでデコード: スペース と + 記号
unquoteが+をデコードしないのに対し、unquote_plusは正しくスペースにデコードしている点が重要です。用途に応じて使い分けましょう。
まとめと活用例
Pythonのurllib.parse.quoteとunquote(およびquote_plus/unquote_plus)は、URLを安全かつ正確に扱うための必須ツールです。
APIリクエストの構築: クエリパラメータに日本語や特殊文字を含む場合、
quoteまたはquote_plusでエンコードしてからURLに結合します。Webスクレイピング: 取得したURLに含まれるエンコードされた文字を
unquoteまたはunquote_plusでデコードし、正しい情報を取り出します。ファイルパスの処理: Webサーバー上でファイル名に特殊文字が含まれる場合、エンコード/デコードを適切に行うことで、パスの問題を防ぎます。
これらの関数を理解し使いこなすことで、PythonでのWeb関連開発の安定性と信頼性が向上します。ぜひ、あなたのプロジェクトで活用してみてください。
■らくらくPython塾 – 読むだけでマスター
■プロンプトだけでオリジナルアプリを開発・公開してみた!!
■AI時代の第一歩!「AI駆動開発コース」はじめました!
テックジム東京本校で先行開始。
■テックジム東京本校
「武田塾」のプログラミング版といえば「テックジム」。
講義動画なし、教科書なし。「進捗管理とコーチング」で効率学習。
より早く、より安く、しかも対面型のプログラミングスクールです。
<短期講習>5日で5万円の「Pythonミニキャンプ」開催中。
<月1開催>放送作家による映像ディレクター養成講座
<オンライン無料>ゼロから始めるPython爆速講座

