同じ情報を二度取り込まないためには、何を「同じ一件」と呼ぶかを決める必要があります。タイトルが同じ別の商品もあれば、URLの表示用パラメーターだけが違う同じ記事もあります。
使える識別子から決める
取得元が安定したIDを返すなら、その意味と一意になる範囲を確認します。店舗ごとに同じIDが使われる場合は、店舗IDと商品IDを組み合わせるなど、必要な範囲まで含めます。
URLを使う場合は、ページ番号や商品番号など意味のある部分を消さないようにします。タイトルだけの判定は表記の変更と同名の別件を区別しにくいため、補助の確認に向いています。
同じIDの内容が違う場合
重複を見つけても、後の行を無条件に捨てると更新情報を失う場合があります。最初を採用する、最新日時を採用する、不一致として保留する、といった方針を選びます。
次は架空の配列をIDで調べる例です。IDが同じで内容が異なる場合は止めます。実際のWeb取得は行いません。
rows = [
{"id": "A01", "title": "受付用紙"},
{"id": "A01", "title": "受付用紙"},
{"id": "B02", "title": "記入見本"},
]
by_id = {}
for row in rows:
key = row["id"]
if not key:
raise ValueError("IDが空です")
if key in by_id and by_id[key] != row:
raise ValueError(f"同じIDの内容が違います: {key}")
by_id[key] = row
print("入力:", len(rows), "採用:", len(by_id))
この入力の期待値は入力3件、採用2件です。更新日時など比較したくない列があるなら、比較する項目を先に定義します。Pythonの辞書の扱いは公式チュートリアルで確認できます。
URLの整理は項目ごとに判断する
相対URLは取得元の基準URLと組み合わせます。ただし、外部から渡された絶対URLは別のホストへ向くことがあるため、urllib.parseの注意事項に沿って、結果の接続先も確認します。
クエリーを全部削る正規化は避けます。商品や言語を区別する値まで消すと、別の内容を一件にまとめてしまいます。除いてよいパラメーターは取得元の仕様と実データを確かめて一覧にします。
件数と不一致を残す
入力件数、同一内容の重複件数、採用件数、不一致で保留した件数を記録します。重複を減らした後に件数が合わなければ、保存する前に原因を調べられます。
少数の検証データで、同一ID・同一内容、同一ID・異なる内容、ID空欄を試してください。採用した行だけでなく、保留にした理由も残しておくと、判定を変える際に見直せます。
前回との変化は差分収集の基本、入力の不足は取得データの欠損検知で確認できます。
