0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PythonのAPIクエリ変換、検索条件の欠落2件を防ぐ

0
Posted at

同じURLを読み戻しただけで、検索条件が2件減った。

検索APIのクエリでは、キーと値の組を最後まで残したい。辞書にすると複数指定がつぶれる。空文字も読み取り時に消えるんだよね。

今日、5組の条件をURLへ変換し、読み戻して比べた。例外は出ないのに、タグが一つと空の条件が欠けた。LLMの検索ツールでこれが起きると、回答だけ見て原因を追うのは難しい。

検索APIのクエリで、どの2件が消えるか

今回扱うのは、tag=Python&tag=LLMのように同じキーを繰り返す形式。入力は次の5組にした。

キー 値 残したい内容
q A+B C プラス記号と空白を含む検索語
tag Python 一つ目のタグ
tag LLM 二つ目のタグ
owner 空文字 空値を明示した指定
limit 0 文字列のゼロ

空値や複数タグの意味はAPIごとの仕様だ。ここでは5組を変えずに送信できるかを調べる。検索結果は測っていない。

CPython 3.14.6、macOSで実行済み。標準ライブラリのみ、外部通信なし。query_roundtrip.pyに保存し、python3 query_roundtrip.pyで動く。

from collections import Counter
from urllib.parse import parse_qsl, urlencode

expected = [
    ('q', 'A+B C'),
    ('tag', 'Python'),
    ('tag', 'LLM'),
    ('owner', ''),
    ('limit', '0'),
]
query = urlencode(expected)
before = list(dict(parse_qsl(query)).items())
after = parse_qsl(query, keep_blank_values=True)

def missing(actual):
    return sum((Counter(expected) - Counter(actual)).values())

print(query)
print('before:', before)
print('after:', after)
print(f'欠落: {missing(before)} -> {missing(after)}')
assert missing(before) == 2
assert after == expected

出力はこうなった。

q=A%2BB+C&tag=Python&tag=LLM&owner=&limit=0
before: [('q', 'A+B C'), ('tag', 'LLM'), ('limit', '0')]
after: [('q', 'A+B C'), ('tag', 'Python'), ('tag', 'LLM'), ('owner', ''), ('limit', '0')]
欠落: 2 -> 0

生成したクエリには、まだ5組とも入っている。

owner=が落ち、続くdict()でtag=Pythonが上書きされる。LLMは残っているので、タグ名だけ眺めると気づきにくい。

Counterの差で欠けた組を数える。追加や順序の違いは数字に出ない。assert after == expectedで、余分な組がなく、順序も一致することまで確かめた。

urllib.parseの中で起きていること

手元のurllib.parseのソースとdocstringも確認した。parse_qsl()は、既定のkeep_blank_values=Falseでは空値を含めない。空値を残す処理では、ここを明示する。

返り値はタプルのリストなので、同じキーを何度でも持てる。辞書へ詰め直すと、キー一つにつき後の値だけが残る。

parse_qs()なら、同じキーの値をリストにまとめてくれる。今回のように並びごと照合するなら、parse_qsl()のままが扱いやすい。

出力のA%2BB+Cでは、プラス記号が%2B、空白が+になった。この組み合わせなら元へ戻る。手書きでq=A+Bを作ると、読み戻した検索語はA Bだった。プラス記号を探す検索で、この差は痛い。

このくらいのURLでも、ログを目で追うのは面倒だな。

API連携へ持ち込む前に

この手順は、同じキーを繰り返して受け取るAPIで使える。配列をカンマ区切りやJSONで送るAPIには、その仕様に合わせた変換が要る。URLへ載せられても、複数タグの検索が成立したかは別に確かめたい。

自分は検索ツールを足すとき、複数値と空文字を含む条件を一度読み戻して照合する。今回の5組では、欠落2件を0件にできた。実際の連携では、API側の絞り込み結果も確認する。検索ツールが増えるほど、条件を辞書へ詰め直す小さな処理が、調査の手間を増やすと見ている。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?