概要(クエリパラメータは「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
Pythonparams に辞書を渡すと、スペースや日本語、記号が安全にパーセントエンコードされます。手書きで連結しないのが基本です。
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)
PythonAPIが期待する表現(”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']}
Pythonparse_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
Pythonparse_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アクセスが書けます。
