【要約】全国6.5万サイトを一晩で調べた。叩かれた側の経験で書いたクローラーと、踏んだ3つの罠 [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
筆者は全国の医療機関サイトの状態を調査するにあたり、大量のリクエストによる相手サーバーへの負荷と、予期せぬエラーによるバッチ処理の中断という課題に直面した。
- ・大量のリクエストによる相手サーバーへの攻撃とみなされるリスク。
- ・ThreadPoolExecutor.map使用時、単一の例外で全プロセスが停止する問題。
- ・Content-Typeの不備による、文字コードデコード時のLookupError。
- ・ホスト単位での集計を行わないことによる、集計データの精度低下。
// Approach
筆者は「自分がされて嫌なことはしない」という指針をコードに落とし込み、負荷軽減と堅牢性を両立する設計を採用した。
- ・1ホストへのリクエストをrobots.txtとトップページの計2回に制限。
- ・threading.Lockとtime.monotonic()を用いた、正確な全体レート制御の実装。
- ・stream=Trueを活用し、判定に必要な400KBのみをダウンロードする帯域節約。
- ・ワーカー関数内で例外を捕捉し、1件の失敗が全体に波及しない設計。
- ・r.encodingを過信せず、try-exceptによるフォールバック処理を実装。
// Result
筆者は一晩で6.5万ホストの調査を完遂し、医療機関における構造化データの普及率が極めて低いという実態を明らかにした。
- ・65,699ホストの調査を、エラーによる中断なく一晩で完了。
- ・HTTPS対応やスマホ対応が8割を超える一方、診療時間の構造化データは8%に留まることを発見。
- ・例外処理と文字コード対策により、大規模バッチにおける停止リスクを排除。
Senior Engineer Insight
> 大規模バッチ処理において、単一の例外がシステム全体を停止させるリスクは極めて高い。ThreadPoolExecutor.mapの挙動を理解し、ワーカー側で例外を適切にハンドリングする設計は必須である。また、外部リソースを扱う際は、r.encodingのようなメタデータの不備を前提とした「防御的プログラミング」が、運用コストと信頼性を左右する。設計段階で「相手への負荷」を構造的に排除するアプローチは、極めて洗練されている。