Python | Web / API:クエリパラメータ

Python Python
スポンサーリンク

概要(クエリパラメータは「URLに条件を添える」最短手段)

クエリパラメータは、URLの末尾に ?key=value の形で付ける追加情報です。検索条件やページ番号、並び順などをサーバへ伝えるために使います。Pythonでは requests の params 引数で安全に付与でき、urllib.parse を使えば既存URLから取得・更新・合成もできます。重要なのは「手書き連結を避けてエンコードを自動化」「配列や複数値の表現」「Noneは送らない」「日本語や記号の文字化けを防ぐ」この4点です。


クエリパラメータの基礎(URL構造と意味)

URLのどこに付くかと基本形

クエリは URL の末尾に ? があり、その後に key=value を & で連結します。例: https://example.com/search?q=python&page=2。この q や page がクエリパラメータです。サーバ側はこれを読み取り、検索やページ分割の条件に使います。

値の型の考え方(文字列化される)

クエリは「文字列」です。数値や真偽値、日付などを渡すと最終的には文字列にエンコードされます。サーバ実装が期待する形式(例: 2025-12-16、true/false、1/0)に合わせて文字列を用意するとトラブルが減ります。


requestsで安全に付ける(params引数が最短で確実)

辞書で渡すだけ(自動エンコード)

import requests

params = {"q": "東京 天気", "page": 2, "lang": "ja"}
r = requests.get("https://httpbin.org/get", params=params, timeout=5)
r.raise_for_status()
print(r.url)  # ?q=%E6%9D%B1%E4%BA%AC%20%E5%A4%A9%E6%B0%97&page=2&lang=ja
Python

params に辞書を渡すと、スペースや日本語、記号が安全にパーセントエンコードされます。手書きで連結しないのが基本です。

None は送らない、空文字は送る

import requests

p = {"q": "python", "page": None, "filter": ""}  # page は除外、filter は空文字として送信
r = requests.get("https://httpbin.org/get", params=p)
print(r.url)
Python

値が None のキーはクエリから除外されます。空文字は送られるため、API仕様に合わせて使い分けます。

配列や複数値はリストで(同名キーの繰り返し)

import requests

p = {"tag": ["python", "api"], "sort": "new"}
r = requests.get("https://httpbin.org/get", params=p)
print(r.url)  # ...?tag=python&tag=api&sort=new
Python

同名キーの繰り返しが必要なAPIでは、値をリストにすると自動で展開されます。

ブール値や日付の表現を合わせる

import requests
from datetime import date

p = {"active": "true", "from": date(2025, 12, 1).isoformat()}  # "2025-12-01"
r = requests.get("https://httpbin.org/get", params=p)
print(r.url)
Python

APIが期待する表現(”true”/”false”、ISO8601の日付文字列など)に明示的に合わせます。


既存URLの操作(urllib.parseで取得・作成・変更)

既存URLからクエリを読む(parse_qs)

from urllib.parse import urlparse, parse_qs

url = "https://example.com/search?q=python&page=2&tag=api&tag=web"
q = parse_qs(urlparse(url).query)
print(q)  # {'q': ['python'], 'page': ['2'], 'tag': ['api', 'web']}
Python

parse_qs は同名キーの繰り返しをリストで返してくれます。型はすべて文字列なので、必要に応じて int 変換します。

URLへ安全にクエリを付加・更新(urlencode)

from urllib.parse import urlencode, urlparse, urlunparse, parse_qsl

base = "https://example.com/search?q=python&page=2"
parsed = urlparse(base)
current = dict(parse_qsl(parsed.query))
current.update({"page": "3", "lang": "ja"})       # 既存値を更新・追加
new_query = urlencode(current, doseq=True)
new_url = urlunparse(parsed._replace(query=new_query))
print(new_url)  # https://example.com/search?q=python&page=3&lang=ja
Python

parse_qsl で既存のクエリを辞書化し、更新してから urlencode で安全に組み立てます。doseq=True でリストを繰り返しキーに展開できます。

ベースURLとパスを合成(urljoin)

from urllib.parse import urljoin

base = "https://api.example.com/v1/"
endpoint = urljoin(base, "items")
print(endpoint)  # https://api.example.com/v1/items
Python

手書きのスラッシュ調整はバグの元。urljoin で確実に合成します。


実務で効く型(ページネーション・フィルタ・署名)

ページネーション(page・limitを標準化)

page と limit(または per_page)で小さく区切り、ページを順に取得します。limit は大きすぎるとレート制限やタイムアウトに触れるため、APIの推奨値に合わせます。

import requests

p = {"page": 1, "limit": 100}
r = requests.get("https://httpbin.org/get", params=p, timeout=5)
print(r.url)
Python

複数フィルタ(範囲・集合・並び順)

範囲は from/to、集合は tag=… を繰り返しキーで、並び順は sort= と order=asc/desc が定番です。

import requests

p = {"from": "2025-11-01", "to": "2025-12-01", "tag": ["python", "api"], "sort": "created_at", "order": "desc"}
print(requests.get("https://httpbin.org/get", params=p).url)
Python

署名やトークン(クエリ渡しは慎重に)

APIキーやトークンをクエリに載せるとログに残りやすいので、できればヘッダー(Authorization)で渡します。やむを得ずクエリに載せる場合は、URL共有・ログ出力に注意します。


よくある落とし穴の回避(連結・エンコード・仕様違い)

文字列連結で壊れる

“?q=” + keyword + “&page=” + page のような手書きは、スペースや日本語・記号のエンコード漏れが起きます。必ず params や urlencode を使う。

日本語や記号が文字化け・未エンコード

スペースは %20(または +)、日本語はUTF-8のパーセントエンコードが必要です。requests/urllib は自動対応するので任せましょう。

ブール・配列の仕様がAPIと違う

APIが “true”/”false” を期待しているのに 1/0 を送る、配列をカンマ区切りで要求するのに繰り返しキーを送るなどのズレに注意。ドキュメントを確認し、必要なら自前で文字列化します。

# カンマ区切りを要求するAPI例
tags = ["python", "api"]
p = {"tags": ",".join(tags)}

None と空文字の取り扱い

None は除外、空文字は送信されます。APIが「空文字は無効」「キー未指定はデフォルト適用」などと区別していることがあるため、意図に合わせて値を決めます。


例題で身につける(定番から一歩先まで)

例題1:requestsで日本語込みのクエリ

import requests

params = {"q": "東京 天気", "unit": "metric", "page": 1}
resp = requests.get("https://httpbin.org/get", params=params, timeout=5)
resp.raise_for_status()
print(resp.url)   # 安全なエンコード済みURL
print(resp.json()["args"])
Python

例題2:既存URLへ安全に条件を追加

from urllib.parse import urlparse, parse_qsl, urlencode, urlunparse

url = "https://example.com/search?q=python&page=2"
parsed = urlparse(url)
q = dict(parse_qsl(parsed.query))
q.update({"lang": "ja", "page": "3"})
new = urlunparse(parsed._replace(query=urlencode(q)))
print(new)  # https://example.com/search?q=python&page=3&lang=ja
Python

例題3:配列パラメータ(繰り返しキー)

import requests

params = {"tag": ["python", "api", "web"], "sort": "new"}
r = requests.get("https://httpbin.org/get", params=params)
print(r.url)
print(r.json()["args"]["tag"])  # ['python', 'api', 'web']
Python

例題4:ページネーションのループ(上限と待機)

import time, requests

for page in range(1, 4):
    r = requests.get("https://httpbin.org/get", params={"page": page, "limit": 50}, timeout=5)
    r.raise_for_status()
    print("page:", page, "url:", r.url)
    time.sleep(0.2)  # レート制限対策の小休止
Python

まとめ

クエリパラメータは URL に条件を添える仕組みで、Pythonでは params と urllib.parse を使えば安全に扱えます。手書き連結を避け、エンコードをライブラリに任せる。配列は繰り返しキー、None は除外、空文字は送信。API仕様(ブール・配列形式・日付フォーマット)に合わせて文字列化すると、誤解なくサーバと意思疎通できます。これらの型を身につければ、初心者でも短く、壊れないWeb/APIアクセスが書けます。

タイトルとURLをコピーしました