パーサーは、サイトが自ら返す8KBのJSONレスポンスのために400KBのHTMLを引き出します。 50倍の違いは「美しいコード」についてではなく、ギガバイトごとに支払う必要があるレジデンシャルプロキシの請求書についてです。内部APIを見つける方法、2026年にそれを再現するのを妨げるもの、そしてこのアイデアを放棄すべき時期について考察します。
HTMLがすでにパースされているのに、なぜ隠れたAPIを探すのか
ほとんどの現代的なインターフェース(React、Vue、Angular、Next.js)は、まずページのフレームを読み込み、その後データを独自のエンドポイントへの別々のリクエストで引き出します。これらのエンドポイントは文書化されていませんが、存在し、クリーンなJSONで応答し、ヘッドレスブラウザなしでアクセス可能です。
それらにアクセスすることで得られるもの:
- トラフィックが大幅に減少します。 一般的な商品検索のHTMLページは、マークアップ、スタイル、トラッカーを含めて約400KBのサイズがありますが、対応するJSONエンドポイントは約8KBで、内部ID、在庫、商品オプションなど、フィールドがより多く含まれています。
- ブラウザは不要です。 JavaScriptのレンダリングが不要になり、それに伴いメモリ、プロセッサ、フォントや分析のための数十の追加リクエストが不要になります。
- データはすでに構造化されています。 CSSクラスの変更によって壊れるセレクタは必要ありません。
- リクエストが少ないほど、禁止される理由も少なくなります。 ブラウザでのカタログページの描画は、サイトへの数十のリクエストを必要としますが、同じデータ量をAPI経由で取得するのは1回です。
レジデンシャルプロキシのプロジェクトにとって、これは直接的なコスト削減です。料金はギガバイト単位で計算され、レンダリングからJSONに切り替えることで、通常は画像のブロックに関するあらゆる工夫よりも請求書が大幅に圧縮されます。関連するテーマは、他の方法でパーサーのトラフィックを5倍に減らす方法です。
ステップバイステップ:エンドポイントの見つけ方
- まず、公式APIがないか確認してください。 目的のサイトの
/developers、/api、/docsを覗いてみてください。公開されている文書化されたAPIはバージョン管理され、非推奨について警告しますが、プライベートAPIは静かに変更されます。 - DevToolsを開き (F12) 、Networkタブに移動し、記録が有効になっていることを確認します。
- Fetch/XHRフィルターを有効にします。 これにより、画像、フォント、分析が除外され、データリクエストのみが残ります。
- リストをクリアします、初期読み込みのノイズを取り除きます。
- 必要なデータを引き出します: 検索結果をスクロールし、「次のページ」をクリックし、フィルターを適用し、カードを開きます。興味のあるリクエストはアクションの瞬間に現れます。
- あなたのデータを含むレスポンスを見つけます。 最も早い方法は、NetworkパネルでCtrl+Fを使用して、画面に表示されているユニークな値(品番、正確な価格、名前の一部)を検索し、それを生成したリクエストを確認します。
- リクエスト全体をコピーします: 行を右クリック → コピー → Copy as cURL。次に、curlconverterを使用してコードに変換します。これにより、ヘッダーを失うことはありません。
最初に見るべき特有のパス:/api/、/v1/、/v2/、/search、/products、/listings、/graphql。
特別なケース:Next.jsのサイト
ここでは、データが別のリクエストを必要としないことがよくあります — それらはHTML内に直接存在します。古いPages Routerでは、これは__NEXT_DATA__ブロックです。App Router(Next.js 13以降)では、ハイドレーションのためのデータが複数のscriptノード内のself.__next_f.push()呼び出しに分散されており、これはReact Server Componentsのシリアライズされたペイロードです。手作業で解析するのは不快です:チャンクは$プレフィックスを介して互いに参照し、文字列の途中で切断されることがあります。Pythonには、HTMLからFlightペイロードと生のRSCレスポンス(RSC: 1ヘッダーを持つリクエスト)を解析するnextflightライブラリがあり、キー名で検索することを提案しています。これにより、パーサーはサイトの再デプロイを乗り越えます。
パラメータのリバース:ページネーションとフィルター
見つけたエンドポイントはほぼ常にパラメータ化されています。3つのスキームが見られます:
- ページによる:
?page=3&per_page=20 - オフセットとリミット:
?offset=40&limit=20 - カーソル:
?after=<token>&limit=20— 次のページのトークンは前のレスポンスの本文に含まれます
時間を節約するための3つのルール:
- 事前に計算されたページ数ではなく、空のバッチで停止します: プライベートAPIの
totalカウンターは、思ったよりも頻繁に嘘をつきます。 - 実際のバッチサイズを確認します。 100をリクエストして20が返ってきた場合、エンドポイントには独自の上限があり、ページ数の計算がすでに誤っています。
- 500ページにはアクセスしないでください。 深いページネーションはほとんどのサーバーでカットオフされます。その代わりに、フィルターでサンプリングをカットします — カテゴリ別、価格範囲別、日付別。
なぜブラウザからのcURLは機能するのに、あなたのコードは機能しないのか
これは最も一般的な失敗ポイントで、原因はほとんど常に1つです:失われたヘッダー。コピーされたcURLはリクエストのすべてのコンテキストを持っていますが、手作りのクライアントは持っていません。
通常、必須となるもの:
X-プレフィックス付きのカスタムヘッダー —X-CSRF-Token、X-Requested-With: XMLHttpRequest、およびフロントエンドが自動的に挿入するさまざまなX-*-Token。これがないと、400〜500の範囲のレスポンスを受け取ります。Referer— ユーザーのアクションによって生成されるコンテキストヘッダー。多くのエンドポイントは、「リクエストが自分のページから来た」ことを確認します。Authorization: Bearer <JWT>— 短命のトークンで、通常は15〜60分の有効期限があります。ハードコーディングする意味はありません:新しいものを取得できる必要があります。- セッションクッキー — それらをセッションオブジェクトに保持し、手動でコピーしないでください。
- POST用の正しい
Content-Type:application/jsonとapplication/x-www-form-urlencodedはボディを異なる方法でエンコードし、宣言されたタイプと不一致になるとリクエストが静かに壊れます。
トークンがクッキーにない場合、どこで探すか:<script>内のHTMLソース(既知の値でCtrl+F検索)、JavaScriptバンドル、localStorageまたはIndexedDB — DevToolsのApplicationタブで。
遅れて知る落とし穴
プライベートAPIは警告なしに変更されます。 バージョン管理、互換性の約束、サポートはありません:フロントエンドチームは木曜日の夜にフィールドの名前を変更し、あなたのパーサーは空のデータを収集します。保護は「信頼できるセレクタ」ではなく、構造の管理です:必須フィールドが適切なタイプで存在することを確認し、空の値の割合と実行中のレコード数を監視し、壊れたレコードをスキップしますが、欠陥が10%を超えた場合は警告を上げます。生のレスポンスを保存して、後で比較できるようにします。
APIは時にはページよりも厳しく保護されています。 これは定期的に発生します:HTMLは静かに返されますが、/api/には、TLSフィンガープリンティングとヘッダーの組み合わせを確認するアンチボットが存在します。この場合、トラフィックの節約は失敗リクエストの割合の増加に変わり、利益が消えてしまいます。
署名されたリクエスト。 パラメータにsign、hash、または_sのようなものが見える場合、フロントエンドはJavaScriptで署名を計算します。それを再現するのは別のプロジェクトであり、しばしばHTMLに留まる方が安上がりです。
レート制限。 プライベートエンドポイントはストリームに対応していません:1〜2リクエスト/秒を維持し、接続と読み取りに別々のタイムアウトを設定します(例:5秒と30秒)、トランジエントエラー(429、500、502、503、504)のみを再試行し、401と404には触れません。指数的な遅延とジッターが必須であり、そうでなければすべてのワーカーが同時に2回目のラウンドに進んでしまいます。詳細は、プロキシ用のタイムアウトとリトライロジックの分析で。
法的枠組み。 公開されている非認証エンドポイントは1つの状況ですが、アカウントへのログインは根本的に異なります:登録はユーザー契約の受け入れを意味します。個人データは、どれだけ簡単に取得できるかに関係なくGDPRの対象となります。事実(価格、特性、在庫)は著作権で保護されていませんが、テキストや画像は保護されています。
HTMLに留まるべき時
隠れたAPIは常に利益をもたらすわけではありません。ページ解析に留まるべき場合:
- サイトがサーバーサイドで、内部APIが存在しない場合;
- エンドポイントが署名やトークンのローテーションを要求する場合 — それを維持するコストがページよりも高くなる;
- APIが公開ページよりも厳しい保護を持っている場合;
- フロントエンドが複数のソースから集めた最終結果が必要な場合;
- 数十のサイトを運営している場合:単一のHTMLパイプラインは、個別の奇妙さを持つプライベートAPIの動物園よりもスケールしやすいです。
APIパーシング用にどのタイプのプロキシを選ぶべきか
JSONへの移行は計算を変えます。なぜなら、ボトルネックが移動するからです:トラフィックは少なくなり、IPの品質とセッションの安定性に対する要求が増えます。
- 認証なしでアンチボットのないオープンエンドポイント。 ここでは、データセンタープロキシが十分です:データ量は少なく、レジデンシャルに支払う必要はありません。
- アンチボットの背後にあるエンドポイントまたはセッションにバインドされたエンドポイント。 レジデンシャルプロキシが必要で、セッショントークン、クッキー、IPがチェーン全体で一致する必要があります。そうでないと、サーバーは2回目のリクエストでセッションをリセットします。この場合、請求は控えめに保たれます — JSONモードではギガバイトがゆっくり消費されます。
- モバイルアプリからのデータ。 ウェブバージョンが閉じられていて、アプリが同じデータを簡単に返す場合、エンドポイントはトラフィックの傍受を通じて探します — これは、mitmproxyを使用してモバイルアプリの隠れたAPIを探すに関する記事で説明された別の手続きです。
まとめ
DevToolsでの20分は、ヘッドレスブラウザとの戦いの日々をしばしば置き換えます:Fetch/XHRフィルター、目に見える値での検索、Copy as cURL — そして、あなたの手には動作するリクエストがあります。次に、詳細を解決します:すべてのヘッダーを移動し、ページネーションのスキームを解析し、レスポンスのバリデーションを設定し、エンドポイントがページ自体よりも厳しく保護されていないか冷静に評価します。プライベートAPIが機能する場所では、トラフィックの量とリクエストの数が減少し、つまりプロキシのコストと禁止される可能性が同時に減少します。
