Python

Pythonを使ったURLの操作やクエリパラメータの使い方を解説

2021年10月7日

Python URLの操作

PythonでURLを操作するために、Request関数やURLのパース関連について解説しています。

標準モジュールを使って操作しているので、他のライブラリを使った方法については説明していません。

この記事で説明しているのは、URLのRequest関数の使い方やURL解析を行うurlparseやurlencodeといった作成についてです。

興味があればぜひご確認ください。

URLを扱う標準のモジュール

PythonでURLを扱うには、urllibのモジュールを使います。

urllibの中には、URLを開いたり読み込んだりするものや、URLをパースするための機能もあります。

モジュール群

  • urllib.request
  • urllib.error
  • urllib.parse
  • urllib.robotparser

URLを開くライブラリ

URLを開く拡張可能なライブラリ

urllib.requestを使えば、基本的な認証やリダイレクション、Cookieなどを使ったURLを開くことができます。

このライブラリを使えば、大体のHTTPに関するURLを開く処理ができるということです。

ほかにも、HTMLのパーサとかと同時に利用することで、自作のカンタンなスクレイピングなども行うことが可能になります。

URLを開いてみる

URLを開くためのもっともカンタンな方法が、urlopenだけを使うことです。

urlopenの引数にURLの文字列を入れることで取得することができます。

今回は、URL先をGoogleの検索ページにしています。

import urllib.request

url = 'https://google.com'
with urllib.request.urlopen(url) as res:
    html = res.read()
    print(html.decode()

urlopenで開いてreadを使うことで、Bodyレスポンスを取得することができます。

res.infoにすることでヘッダーレスポンスを取得することができます。

Request関数の使い方

URLの部分をリクエスト関数を使うことでパラメータの付与やヘッダーなど追加してリクエストを送ることができます。

from urllib.request import Request, urlopen

url = 'https://google.com'
req = Request(url)
with urlopen(req) as res:
    html = res.read()
    print(html.decode()

Requestの第2引数にデータを入れるとGETメソッドから自動的にPOSTメソッドに変わります。

そのため、POSTデータを付与して送るには、下記のようにして送ります。

data = {
    'q': 'python'
}

qs = urlencode(data)
req = Request(url, qs.encode())

ステータスコードの取得

レスポンスデータからHTTPステータスコードを取得するには、getcodeを利用します。

import urllib.request

url = 'https://google.com'
with urllib.request.urlopen(url) as res:
    print(res.getcode()  # 結果 200が返ってきた

Contentタイプの取得

ステータスコードの取得と同じように、レスポンスからinfo関数を使ってヘッダー情報を取得します。

header情報の中から、Content-Typeを指定すると取得することができます。

import urllib.request

url = 'https://google.com'
with urllib.request.urlopen(url) as res:
    print(res.info()['Content-Type'])  # 結果 text/html; charset=ISO-8859-1

Googleの検索ページってUTF8じゃないのにビックリしました!

PUTとDELETEでリクエスト

Request関数でGETとPOSTについて、少しですが説明しました。

PUTやDELETEで投げるにはどうしたら良いの?って思ったので調べると、Request関数でmethod引数をつけるだけっぽいです。

url = 'http://localhost:3000'
data = {
    'q': 'python'
}

headers = {
    'Content-Type': 'application/json',
}

qs = urlencode(data)
req = Request(url, qs.encode(), headers, method='PUT')

DELETEメソッドでリクエストしたい場合は、PUTの部分をDELETEにするだけです。

URLを解析

URLを解析

PythonでURLを解析(パース)することで、クエリパラメータの値の変換やエンコード・デコードをカンタンに行うことができます。

クエリパラメータとは

クエリパラメータとは、URLの中にある?以降のパラメータのことを指します。

例えば下記のようなURLのq=python+querystringの部分です。

https://www.google.com/search?q=python+querystring

このURLのsearch?のqの部分からがクエリパラメータになります。

書き方はkeyと値をイコールで連結し、複数の値をするには、&(アンパサンド)でさらに連結していきます。

https://[ホスト]/test?キー=値&キー2=値2&キー3=値3

URLからクエリパラメータを取得してみる

urllib.parse.urlparse()を使ってURLからクエリ部分を抽出することができます。

from urllib.parse import urlparse

url = 'https://www.google.com/search?q=python+querystring'
obj = urlparse(url)

print(obj.query) # 結果は q=python+querystring

URLをパースして、パースしたデータにqueryを使うことでクエリ文字列の部分だけを取得することができます。

URLのクエリパラメータを辞書として変換

queryだけだと、複数のパラメータが付与された場合、値を分割するのに苦労します。

しかし、parse_qsを使うことで辞書として変換することができます。

from urllib.parse import urlparse, parse_qs

url = 'https://www.google.com/search?q=python+querystring&test=hoge'
qs = parse_qs(urlparse(url).query)

print(qs) # 結果は {'q': ['python querystring'], 'test': ['hoge']}

parse_qsには文字列のクエリパラメータを入れます。

そうすることで、キーが複数あっても辞書として変換することができます。

クエリパラメータの作成

urlencodeを使うことで、辞書型のデータをクエリパラメータとしてエンコードすることができます。

from urllib.parse import urlencode

q_data = {
    'q': 'Pythonでクエリパラメータを作成',
    'option': [1, 3, 5],
    'lang': 'jp',
}

qs = urlencode(q_data)

print(qs)

urlencodeにそのまま入れるだけでクエリパラエータが作成できるのでカンタンですね。

結果は下記になります。

q=Python%E3%81%A7%E3%82%AF%E3%82%A8%E3%83%AA%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%82%92%E4%BD%9C%E6%88%90&option=%5B1%2C+3%2C+5%5D&lang=jp

日本語に関して%Eや%Aといった文字が含まれていますが、これはURLエンコードされたことによって起きる現象です。

クエリパラメータのエンコードに配列があったら注意が必要

クエリパラメータの作成でエンコードされたクエリを元に戻してみると分かります。

もとに戻すコードは、下記になります。

from urllib.parse import urlencode, parse_qs, unquote

q_data = {
    'q': 'Pythonでクエリパラメータを作成',
    'option': [1, 3, 5],
    'lang': 'jp',
}

qs = urlencode(q_data)

print(qs)
print(unquote(qs))
print(parse_qs(qs)

urlencodeを使って、辞書型のデータをクエリパラメータに変換します。

unquoteでは、%などに変換された値をデコードしています。

parse_qsでは辞書として戻しています。

これらの結果が下記になります。

q=Python%E3%81%A7%E3%82%AF%E3%82%A8%E3%83%AA%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%82%92%E4%BD%9C%E6%88%90&option=%5B1%2C+3%2C+5%5D&lang=jp
q=Pythonでクエリパラメータを作成&option=[1,+3,+5]&lang=jp
{'q': ['Pythonでクエリパラメータを作成'], 'option': ['[1, 3, 5]'], 'lang': ['jp']}

unquoteやparse_qsの結果を見てわかる通り、辞書の値の部分が配列になっていたり、リストの部分が文字列になっていたりとおかしな変換になっています。

まずは、parse_qsで変換すると下記になります。

{'q': '値'} -> {'q': ['値']}

値を取得するには、変数名['q'][0]としないと取得できません。

なぜ値が配列として戻ってくるのかはドキュメントを読んでみたらリストを返すようです。

なのでparse_qsの仕様ですね。

option部分の配列はだったのが文字列に変わっているのも仕様で、文字列から配列に変換する必要があります。

"[1, 2, 3]"このような文字列を配列に変換するには、splitを使うしか無いのか?

evalを使えばカンタンに配列になります。

data = parse_qs(qs)
option = data['option'][0]
l = eval(option)
print(l, l[0]) # 結果は [1, 3, 5] 1

まとめ

PythonでURLを扱う標準モジュールを紹介しました。

URLを開くことでHTMLやFTPといったデータを取得することができるurlopenがあります。

ほかにもURLを解析するurlparseを使えば、カンタンにURLについているパラメータを取得することも可能。

サーバ側の処理は足りないのですが、クライアントとして処理する分には、Requestとurlopenだけで十分です。

カンタンなアプリ作成だったら、検討してみるのもアリですね。

Udemyへ

今後の人生を豊かにする為にキャリアアップのステップとして、自分への投資をしてみませんか?

-Python
-