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のパス部分やクエリパラメータの値をエンコードする際に特に役立ちます。

基本的な使い方

Python
 
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引数で指定することがよくあります。

Python
 
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や、エンコードされたクエリパラメータの値を処理する際に利用します。

Python
 
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形式で使われる+記号(スペースの代わり)も正しく処理するためです。


quotequote_plusunquoteunquote_plusの違い

urllib.parseにはquote_plusunquote_plusという似た名前の関数もあります。これらは、主にWebフォームのデータ(application/x-www-form-urlencoded)を扱う際に役立ちます。

  • quote vs quote_plus:

    • quote: スペースを%20にエンコードします。

    • quote_plus: スペースを+にエンコードします。Webフォームのデータ送信でよく使われます。

  • unquote vs unquote_plus:

    • unquote: %XX形式のみをデコードし、+はそのまま残します。

    • unquote_plus: %XX形式に加え、+もスペースにデコードします。

Python
 
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.quoteunquote(および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爆速講座