PythonでURLエンコードおよびデコードをするには、urllib.parseモジュールを使います。本記事ではこれらの使い方についてまとめます。
確認環境
- OS: Ubuntu16.04LTS
- Python3.7.1
URLエンコードとは
日本語や特殊文字などの非ASCII文字をクエリ文字列に組み込んでGETリクエストを送信する場合など、これらの文字をURL構成要素として使用できるよう適切にエンコードする必要があります。 これを一般的にURLエンコードと呼んでいます。
URLエンコードは、以下2つがあります。
※参考:パーセントエンコーディング- Wikipedia
- パーセントエンコーディング
- URL Standard 4.4 URL parsing, path state、RFC3986のSection 2.1で定義
- 半角スペースは”%20″にエンコード
- application/x-www-form-urlencoded
- URL Standard 5. application/x-www-form-urlencodedで定義
- 半角スペースは”+”にエンコード
- GETリクエストの標準に準拠
Pythonでは、urllib.parseモジュールを使ってURLエンコードを実行します。
URLエンコードを行う
urllib.parse.quote()関数によるURLエンコード
- 特殊文字を%エスケープを使った文字に置き換えます。尚、”_.-~”は置き換えられません。
- オプション引数safeはクオートしたくないASCII文字を指定できます。デフォルトは、”/”です
# アルファベット、数値、" _.-~ "および"/(safeのデフォルト値)"はクオートされない
>>> urllib.parse.quote('abc123_.-~/')
'abc123_.-~/'
# オプション引数safeを"*"に設定すると、"/"がクオートされ、"*"がクオートされなくなる
>>> urllib.parse.quote('abc123/*', safe="*")
'abc123%2F*'
# 日本語も%エンコードされます。
>>> urllib.parse.quote('お正月')
'%E3%81%8A%E6%AD%A3%E6%9C%88'
urllib.parse.quote_plus()関数によるURLエンコード
- quote() と似ていますが、クエリ文字列を URL に挿入する時のために HTML フォームの値の空白をプラス記号「+」に置き換えます。
>>> urllib.parse.quote_plus('abc def')
'abc+def'
- オリジナルの文字列に「+」がある場合は safe に指定されている場合を除きエンコードされます。
>>> urllib.parse.quote_plus('abc+def')
'abc%2Bdef'
# safeに"+"を指定した場合
>>> urllib.parse.quote_plus('abc+def', safe="+")
'abc+def'
- safe にデフォルト値は設定されていません。
>>> urllib.parse.quote_plus('abc/def')
'abc%2Fdef'
URLエンコードされた値を元に戻す
urllib.parse.unquote()関数によるデコード
- エスケープされた %xx をそれに対応した単一文字に置き換えます。
>>> urllib.parse.unquote('%E3%81%8A%E6%AD%A3%E6%9C%88')
'お正月'
>>> urllib.parse.unquote('abc%20def%2Aghi%21')
'abc def*ghi!'
urllib.parse.unquote_plus()関数によるデコード
- unquote() と似ていますが、HTMLフォームの値のアンクオートのために「+」をスペースに置き換えます。
>>> urllib.parse.unquote_plus('abc+def')
'abc def'
クエリ文字列の生成
urllib.parse.urlencode()関数によるクエリ文字列生成
- マッピング型オブジェクトまたは 2 個の要素からなるタプルのシーケンスを、パーセントエンコードされたASCII文字列に変換します。
- 戻り値は、 ‘&’ 文字で区切られた key=value のペアからなる一組の文字列になります。
- デフォルトで値をクオートはquote_plus() が使用されます。
- つまり、スペースは ‘+’ 文字に、 ‘/’ 文字は%2Fにクォートされます。
- ※ GETリクエストの標準に準拠 (application/x-www-form-urlencoded)。
# クエリ文字列の生成
>>> query = (('abc', '00'), ('def', '11'))
>>> urllib.parse.urlencode(query)
'abc=00&def=11'
# quote_plusによるエンコード
>>> query = (('ab c', '00'), ('de/f', '11'))
>>> urllib.parse.urlencode(query)
'ab+c=00&de%2Ff=11'
# 日本語も下記の通りエンコードされます
>>> query = (('天気', '00'), ('飛行機', '11'))
>>> urllib.parse.urlencode(query)
'%E5%A4%A9%E6%B0%97=00&%E9%A3%9B%E8%A1%8C%E6%A9%9F=11'
まとめ
urllib.parseモジュールを用いたURLエンコードの方法についてまとめました。
実際は例えばrequestsモジュール等が自動で処理をしてくれるので、実際にこれを使う場面は多くはないかもしれません。