保護されたサイトのスクレイピングに関するアドバイスの多くは、あらゆる手法を同時に使う必要があるかのように書かれている。ヘッドレスブラウザ、偽装フィンガープリント、行動ペーシング、全部だ。だが実際にはそうする必要はなく、デフォルトで全部に手を伸ばすこと自体が誤りである。ターゲットによっては素のGETリクエストを何の問題もなく受け付けるものもあれば、ページが読み込まれる前にスクリプトライブラリをブロックするものもある。高い成功率と、ブロックの山や無駄な計算資源の消費とを分けるスキルは、一つの巧妙なテクニックを知っていることではない。キャリブレーションだ。つまり、あるターゲットを確実に突破できる最も単純な手法を使い、サイトがそれを強いる場合にのみ段階を上げていくことである。
これは梯子だと考えるとよい。それぞれの段はより強力な防御層を打ち破るが、その分実行コストも高くなる。これは個々の手法、プレーンなクライアント、TLSインパーソネーション、実際のブラウザ、完全なステルスを一つの判断軸に結びつける地図である。すなわち、そのターゲットは実際にどの段を必要としているのか、という判断だ。
最大限の努力よりキャリブレーションが勝る理由
失敗のパターンは二つに大別できる。一つ目は分かりやすい過小設計だ。厳重に防御されたサイトにrequestsで挑めば即座にブロックされ、リトライをいくら重ねても無駄である。もう一つはより静かで、実はより多く見られる過剰設計という無駄だ。単純なHTTP呼び出しで済むはずのサイトに対して、管理されたフィンガープリントを持つフルブラウザ群を動かしてしまうケースである。これはスループット、帯域、インフラ、信頼性のコストを押し上げる。ブラウザは遅く、重く、壊れる要素もはるかに多いのに、それは対象がそもそも突きつけてもいない問題を解決するためだけの投資になる。
正しい姿勢は、安価に始めてエビデンスに基づいて段階を上げていくことだ。効果のある最も低い段を使い、必要になったときはターゲット自身のレスポンスにそれを教えてもらい、サイトが楽になったら段を下げる。労力は想定しうる最悪のケースではなく、実際に遭遇する防御に応じて配分すべきである。
段0: プレーンなHTTPクライアントとクリーンなレジデンシャルIP
これでウェブの大半をカバーできる。堅実なHTTPクライアント(requests、httpx、あるいはあなたの言語の同等品)を、クリーンなレジデンシャルIP経由で使えば、主な防御がIPレピュテーションと基本的なリクエストの妥当性チェックであるサイトはすべて突破できる。ここに、普通に見せるための衛生管理を加える。現実的なヘッダー、ホストごとの妥当なレート、429に対するバックオフ、そして責任あるスクレイピングの基本だ。
この段で最も大きなレバーはIPレピュテーションである。クリーンなレジデンシャルアドレスがあれば、データセンタートラフィックを冷たく拒む評判チェックを通過できる。これこそ「保護されている」と思われる多くのサイトが実はこれ以上を必要としない理由だ。すべてのターゲットに対してここから始めること。最も速く、最も安く、最も信頼できる選択肢であり、しばしばこれ以上の段は不要である。
段1: TLSインパーソネーションを行うクライアント
段0がページの読み込み前に即座にブロックされ、IPをローテーションしても改善しない場合にこの段に上がる。このシグネチャはクライアント層のブロックを示している。つまりハンドシェイクがフィンガープリンティングされているのだ。TLSおよびHTTP/2フィンガープリンティングで解説されている通り、スクリプトライブラリのTLS ClientHelloとHTTP/2設定はブラウザのものとは似ても似つかず、多くのアンチボットシステムはそれだけで接続を拒否する。
対処法はフルブラウザではなく、実際のブラウザのネットワークフィンガープリントを提示しつつ軽量なHTTP呼び出しであり続けるTLSインパーソネーション対応HTTPクライアント(curl_cffi、tls-client、utlsなど)である。段0を止めたフィンガープリンティングを、わずかなコスト増だけで打ち破れる。ブラウザに飛びつく前にこれを試すべきだ。ブラウザのオーバーヘッドなしに、防御の一階層をまるごと突破できるからだ。
段2: 実際のヘッドレスブラウザ
コンテンツがJavaScriptでレンダリングされている場合、インタラクションの背後にゲートされている場合、あるいはターゲットがネットワーク層を超えたフィンガープリンティングを行っている場合にこの段に上がる。実際のブラウザ、Playwright、Puppeteer、あるいはSeleniumは、ページのJavaScriptを実行し、その定義上、実際のブラウザのTLS、HTTP/2、DOMを備えている。スクリプトを実行しなければページが存在しないため、プレーンな、あるいはインパーソネーションを行うクライアントでは単純に対応できないサイトを扱える。
コストは実在する。ブラウザはHTTP呼び出しに比べてメモリを大量に消費し、遅い。そのため、この段でスループットが下がり、インフラが増大する。不要なリソースをブロックすること、画像、フォント、メディアなど、そしてリクエストごとに起動するのではなく一つの長寿命なブラウザインスタンスを再利用することで、コストを鈍らせられる。サイトが「重要」だからという理由だけでこの段に上がってはならない。レンダリングされたページなしにはデータが本当に存在しないから、この段に上がるのだ。
段3: フィンガープリントと行動ステルスを備えたブラウザ
最上段は、素のヘッドレスブラウザすら見破ってしまう最も手強いターゲット向けである。この段階では、サイトはデバイスフィンガープリント(ヘッドレスの兆候、canvas、navigatorの癖)と行動(マウスの動き、タイミング、インタラクションのパターン)を精査している。突破するには、アンチデテクトブラウザがやっているようにフィンガープリントを管理し、それぞれのアイデンティティに一貫した独自のプロファイルを与え、瞬時ではなく人間らしく見えるようインタラクションのペースを調整する必要がある。検知を引き起こすミスはすべてこの段に集約される。
これは最もコストが高く、最も壊れやすい選択肢であり、まさにそれゆえにデフォルトではなく最後の手段であるべきだ。ほとんどのスクレイピングはこれを必要としない。あるターゲットが本当にこれを必要とするのは、それより安価な段がすべて試され、エビデンスによって失敗が示された場合だけである。
すべての段で変わらないもの: IP
この梯子はクライアントの高度さに関するものだが、段を上がっても変わらないものが一つある。どの段であっても、その下にはクリーンなレジデンシャルIPが必要だということだ。フラグ付きやデータセンターのアドレスから発せられた完璧なブラウザフィンガープリントは、その上に積み上げられたものがどれほど説得力があろうと、ネットワーク層で捕まってしまう。そしてセッションの一貫性もすべてのレベルで重要であり、一つの筋の通った訪問者に見せたいものにはスティッキーセッションを、ログインの背後にいる場合には認証済みセッションの規律を用いる必要がある。IPとセッションは梯子全体が立脚する土台であり、各段はその上にどれだけのクライアントの高度さを載せるかを決めているにすぎない。
どう段を上るか: 失敗に語らせる
この梯子のポイントは、どの段にいるかを推測しないことだ。診断するのである。失敗を正しく読み取ることで、自分がどこで詰まっているのかが正確にわかる。
- 即座にブロックされ、IPをローテーションしても何も変わらないが、TLSインパーソネーションを行うクライアントなら通る場合、クライアントフィンガープリントの層で詰まっている。段1へ。
- リクエストは成功するがコンテンツが欠けている、あるいは空である場合、それはJavaScriptでレンダリングされているためであり、実際のブラウザが必要だ。段2へ。
- ブラウザは最初は動作するが、時間が経つとチャレンジされたりフラグを立てられたりする場合、デバイスフィンガープリントか行動が正体を明かしている。段3へ。
- ほとんどの場合はうまくいくが、一部のIPだけがチャレンジされる場合、それはそもそも段の問題ではなく、IPレピュテーションの問題である。プールを直せ、段を上げるな。
そのエビデンスに基づいて段階を上げ、また段階を下げもすること。ターゲットが緩和されたら、より安価な段に戻ってスループットを取り戻す。だからこそターゲットごとの監視が重要になる。どのターゲットが上昇していて、どれが緩和したかを教えてくれるので、労力が想定ではなく現実に沿うようになる。
ターゲットごとに段を割り当てる、プロジェクトごとではない
最後の原則は、最もコストを節約できるものだ。段はターゲットごとに割り当てるものであり、パイプラインごとではない。あるクロールが百のサイトに触れるとして、そのうち95は段0で問題なく、5はブラウザを必要とするとしよう。その5に合わせてクロール全体を段2で走らせるのは、残り95に対する巨大で不要な税金となる。よく作られたパイプラインは、ターゲットごとに段を記録し、新しいターゲットはデフォルトで段0とし、特定のターゲットが失敗したときにだけ、理想的には自動的に段を上げる。その結果、成功率とコストの比率が最良になる。各ターゲットは確実に突破できる最も安価な段で処理され、過剰な構築は一切なくなる。
結論
厳重に防御されたサイトのスクレイピングは単一の手法ではなく、梯子である。そして勝つチームは、すべてを最大限のステルスで動かすチームではない。労力を各ターゲットに合わせるチームだ。段0からプレーンなクライアントとクリーンなレジデンシャルIPで始め、TLSインパーソネーションを行うクライアントへ、次に実際のブラウザへ、そして完全なステルスへと、ターゲット自身のレスポンスが各ステップを強いる場合にのみ段を上げ、その土台としてクリーンなIPと一貫したセッションを常に維持する。失敗から段を診断し、ターゲットごとに段を割り当て、サイトが楽になったら段を下げる。
これを実践すれば、成功率は上がりコストは下がる。HTTPの問題に対してブラウザの価格を払わなくて済むようになるからだ。あらゆる段の土台となるレジデンシャルプロキシはギガバイト単位で価格設定されているため、この梯子が促す規律あるキャリブレーションされたアプローチこそが、最もコストを抑えられるアプローチでもある。