ブラウザのDevToolsを使用して隠れたAPIを見つけてスクレイピングする方法
Advanced Data Extraction Specialist
TL;DR:
- 隠れたAPIとは、ページが使用するリクエストであり、公開の開発者APIとして広告されていないものです。 JSON、GraphQLデータ、HTMLフラグメント、またはフロントエンドによって消費されるストリームを返す場合があります。
- ブラウザのDevToolsはリクエスト契約を明らかにします。 ページアクションを記録し、Fetch/XHRをフィルタリングし、URL、メソッド、クエリ、ペイロード、レスポンス、イニシエーター、ページネーションの動作を検査します。
- 公開または認可されたリクエストのみを再現します。 リクエストがログイン、プライベートデータ、アクセス制御トークン、またはサイトの利用規約で禁止されている使用に依存している場合は停止します。
- ブラウザを発見とフォールバックレイヤーとして保持します。 内部エンドポイントは通知なしに変更される可能性があり、一部のリクエストには同じブラウザセッション内で確立されたクッキーや状態が必要です。
- フィールドとページのアイデンティティを検証します。 成功したステータスは十分ではなく、期待されるスキーマ、ロケール、ページネーションカーソル、および必要な公開レコードを確認してください。
多くのJavaScriptページは、ドキュメントが読み込まれた後に本当のコンテンツを取得します。レンダリングされたカードは、ブラウザのネットワークパネルにすでに表示されている構造化されたレスポンスの一つの表現に過ぎません。
隠れたAPIをスクレイピングするということは、それらのブラウザから開始されたリクエストを観察し、データが公開または明示的に認可されている場合、最小限の安定したリクエスト契約を再現することを意味します。これは、プライベートエンドポイントを発見したり、認証を突破したり、ページの特権を拡張したりすることを意味するものではありません。
隠れたAPIとは?
隠れたAPIとは、サイトのフロントエンドが使用する内部のHTTPまたはWebSocketインターフェースであり、サポートされている公開APIとして提示されていないものです。エンドポイントは文書化されていない場合があり、フロントエンドの変更時に変更される可能性があります。
一般的なレスポンスの形状には以下が含まれます:
- JSONオブジェクトまたは配列;
- GraphQLレスポンスエンベロープ;
- ページに挿入されたHTMLフラグメント;
- 改行区切りのイベントストリーム;
- サイト自身のデコーダーを必要とするバイナリ形式。
このフレーズは発見可能性を示しており、許可を示しているわけではありません。ブラウザで可視化されるリクエストは、アカウント状態、個人データ、ライセンスされたコンテンツ、または契約上の制限を持っている可能性があります。ワークフローは公開または認可された表面内に留めてください。
DOMスクレイピング vs 内部JSONリクエスト
正しいソースは、最小限の安定した契約で承認されたフィールドを返すものです。
| 質問 | DOM抽出 | 内部リクエスト抽出 |
|---|---|---|
| データ形式 | HTML要素と属性 | 構造化されたJSONまたはGraphQLが一般的 |
| 発見 | レンダリングされたページを検査 | ネットワークアクティビティを検査 |
| 再設計への感受性 | CSSとDOMの変更 | エンドポイントおよびスキーマの変更 |
| ブラウザの要件 | クライアントレンダリングに必要 | 発見またはセッション状態に必要なことが多い |
| ページネーション | クリック、スクロール、次のリンク | ページ、オフセット、カーソル、またはリクエストペイロード |
| 最適な使用方法 | データがプレゼンテーションにのみ存在する場合 | 安定した公開フィールドが構造化されたレスポンスに表示される場合 |
ページ自身のプレゼンテーションが権威あるソースであるか、リクエスト契約があまりにも壊れやすい場合はDOMを使用します。必要な公開フィールドをクリーンに露出し、ワークフローが同じアクセス境界を尊重できる場合は内部レスポンスを使用します。
ステップ1 — ページアクションの前にDevToolsを開く
ネットワークパネルは、開いている間に行われたリクエストのみを記録します。DevToolsを開き、「ネットワーク」を選択し、ナビゲーションが関与する場合は「ログを保持」を有効にし、既存のリストをクリアします。
Chrome DevToolsネットワークリファレンスでは、ログを保持、リクエストタイプフィルタ、ペイロード検査、レスポンスプレビュー、イニシエーター、HARエクスポート、およびFetchまたはcURLとしてコピーすることが文書化されています。
次に、データを読み込むアクションを1つ実行します:
- 1つの公開検索を送信する;
- 1つのカテゴリを切り替える;
- 次の結果ページを読み込む;
- 1つの公開詳細パネルを展開する;
- 次のバッチが表示されるまでスクロールする。
1つのアクションは、最初に全ページと対話するよりも小さく、監査可能なリクエストの差を作ります。
ステップ2 — Fetch/XHRをフィルタリングし、データが含まれるレスポンスを見つける
Fetch/XHRを選択し、ページアクションとタイミングが一致するリクエストを検査します。レスポンスボディを検索して、ページに表示されている1つの安定した公開値(アイテムID、正確なタイトル、またはカテゴリコードなど)を見つけます。
以下のフィールドを確認します:
| DevToolsフィールド | キャプチャするもの | なぜ重要か |
|---|---|---|
| リクエストURL | 起源、パス、クエリ | ルートとページパラメータを定義します |
| メソッド | GETまたはPOST | パラメータの所在を決定します |
| ペイロード | クエリ文字列、フォームデータ、またはJSON | フィルタとカーソルを運びます |
| レスポンス | トップレベルスキーマと必要なフィールド | リクエストにターゲットデータが含まれていることを確認します |
| イニシエーター | スクリプトまたはコールスタック | どのページアクションがそれを作成したかを示します |
| ヘッダー | コンテンツタイプと必要な公開コンテキスト | 表現とロケールを区別します |
| タイミング | 開始と持続時間 | リクエストとアクションの相関を助けます |
すべてのブラウザヘッダーをコピーしないでください。メソッド、URL、ペイロード、および文書化された公開コンテキストから始めます。制御されたテストにより、リクエスト契約がそれを必要とすることが証明された場合にのみ、ヘッダーを追加します。
ステップ 3 — リクエストを再現するのが安全かどうかを決定する
再現可能なリクエストは、同じ認証境界内に留まる必要があります。
次の場合に進みます:
- レスポンスには、ユーザーがアカウントなしでアクセスできる公開データが含まれている場合;
- リクエストが明示的に許可された統合またはテストの一部である場合;
- 意図されたボリュームが適切である場合;
- フィールドが指定されたデータセットに必要な場合。
次の場合は停止します:
- レスポンスがプライベートまたはアカウントスコープのデータを公開する場合;
- 再現がログイン、ペイウォール、またはアクセス制御の境界を越えることになる場合;
- リクエストがあなたのものではない秘密に依存している場合;
- サイトの利用規約またはプロジェクトの承認がその活動を許可していない場合。
Chrome HAR エクスポートガイダンスは、サニタイズされたエクスポートがCookie、Set-Cookie、およびAuthorizationなどのセンシティブヘッダーを省略することに言及しています。承認されたデバッグタスクが特に保護された値を必要としない限り、ドキュメント化にはサニタイズされたキャプチャを使用してください。
ステップ 4 — リクエストをコピーし、次に削減する
DevToolsは、リクエストをcURLまたはNode.jsのfetch呼び出しとしてコピーできます。その出力を診断スナップショットとして扱い、本番コードとして扱ってはいけません。
次の順に削除します:
- トラッキングおよびブラウザ生成ヘッダー;
- 公開表現に無関係なクッキー;
- ワンオフの相関値;
- 必要な結果を変えないパラメータ;
- 冗長なコンテンツネゴシエーションヘッダー。
各変更の後、レスポンススキーマと必要なレコードを検証します。目標は、フィールドごとに説明できる最小限のリクエスト契約です。
ブラウザのFetch APIは、クッキーと認証ヘッダーを資格情報として扱います。MDN Fetch APIガイドは、資格情報の処理がクロスオリジンリクエストとどのように相互作用するかを説明しています。 明示的に承認された仕事であり、ストレージとアクセスモデルがレビューされている場合を除いて、スタンドアロンスクリプトに資格情報を持ち込まないでください。
ステップ 5 — レスポンスを安定したスキーマにマッピングする
内部レスポンスは、データセットに必要なものよりも多くのフィールドを公開することがよくあります。狭い出力契約を定義します。
json
{
"source_url": "https://example.com/public-search?q=notebook",
"query": "notebook",
"page": {
"cursor": "next-public-cursor",
"has_more": true
},
"items": [
{
"id": "item-123",
"title": "Illustrative public result",
"url": "https://example.com/public/items/item-123",
"price": null
}
]
}
上記のスキーマは説明的なサンプルです。ヌル可能なフィールドはヌル可能のままにし、ソースURLを保持し、レスポンスが一つを提供する場合は安定した識別子を保持します。
発見にJavaScriptとブラウザの状態が必要な場合は、無料の Scrapeless Scraping Browser セッションを開始してください。
ステップ 6 — スケーリング前にページネーションを理解する
ページネーションは通常、次の4つの場所のいずれかに表示されます:
- クエリ内の
page数値; offsetに固定の制限が加わる;- レスポンス内の不透明なカーソル;
- リクエストボディ内のGraphQL変数。
正確に1つの次ページアクションをトリガーし、2つのリクエストを比較します。どの値が変更されたか、次の値を提供するレスポンスフィールドを記録します。不透明なカーソルを考案したりデコードしたりしないでください。
契約に結びついた停止ルールを使用します:has_more が false になる、次のカーソルが存在しない、結果の配列が空である、または承認された最大ページ数に達する。タイトルテキストではなく、安定した公開IDに基づいて重複を除去します。
ステップ 7 — リクエストがそれを必要とする場合にセッション状態を保持する
一部の内部リクエストは、ページがクッキー、同意、ロケール、または他の許可された状態を確立した後のみ機能します。その場合、発見と抽出を1つの制限されたブラウザセッション内に保持します。
Scrapeless Scraping Browser はクラウドブラウザでJavaScriptを実行し、承認されたナビゲーションの間にセッション状態を保持します。同じコンテキストからリクエストを観察し、レスポンスを抽出するために使用し、不透明な状態を無関係なクライアントにエクスポートしないでください。
Scrapeless Scraping Browser ドキュメント は、制限されたセッションの寿命と地理的ルーティングパラメータを文書化しています。リクエストを検証する際に地理、言語、クッキー、およびページシーケンスを固定のままにしてください。
ブラウザフォールバック: 内部APIが間違ったソースである場合
内部エンドポイントが不安定、アカウントスコープにある、瞬時の状態に強く結合されている、または表示依存のフィールドが欠けている場合、ブラウザは安全なフォールバックのままです。
以下の場合はレンダリングされたDOM抽出を選択します:
- レスポンススキーマがセマンティックページ要素よりも頻繁に変化する;
- 公開フィールドがクライアントレンダリングの後にのみ計算される;
- エンドポイントの認可モデルが不明確である;
- リクエストを再現するにはセンシティブな資格情報をコピーする必要がある;
- ページの可視表現が記録のデータセットである。
JavaScriptレンダリングガイドでは、初期HTML、クライアントレンダリングされたコンテンツ、および非同期リクエストの違いが説明されています。
隠されたAPIスクレイピングのトラブルシューティング
| 観察 | 考えられる説明 | チェック |
|---|---|---|
| レスポンスがHTMLで、JSONではない | リダイレクト、チャレンジ、同意、またはエラーの表現 | 最終URL、コンテンツタイプ、タイトル、ボディマーカー |
| JSONに空のアイテムがある | 不正なロケール、公開パラメーターの欠如、またはページネーションの終了 | 動作するブラウザリクエストとページの状態を比較 |
| フィールドが消える | スキーマドリフトまたは条件付き結果タイプ | nullableフィールドを保持し、各アイテムタイプを検証 |
| カーソルが繰り返される | 不正なカーソルソースまたはキャッシュされたリクエスト | 現在受け入れられたレスポンスから次のカーソルを読み取る |
| スタンドアロンリクエストが拒否される | ブラウザセッションの状態が必要 | 認可されたブラウザコンテキスト内での抽出を保持 |
| DOMとJSONのカウントが異なる | UIフィルタリング、パーソナライズ、または追加のレスポンスレコード | どの表現が権威あるものであるかを定義 |
1回の変数を変更し、受け入れられたレスポンスの形状のサニタイズされた例を保存します。リクエストがアクセス境界を越える場合は、クライアントを調整するのではなく停止します。
結論:リクエスト契約を依存関係として扱う
隠されたAPIのスクレイピングは、壊れやすいDOM解析を構造化された公開データに置き換えることができますが、エンドポイントはサポートされた公開契約ではなく、内部依存関係です。1ページアクションを通じてそれを発見し、コピーされたリクエストを減少させ、必要なフィールドのみをマッピングし、ページネーションと状態を文書化します。
スキーマの変更やセッションに結びついたフローに対してブラウザのフォールバックを保持してください。ページ、エンドポイント、またはデータセットのスコープが変更されるたびに認可を再確認します。
ブラウザ対応の抽出ワークフローを構築する準備はできましたか?
公開データの発見とスキーマ設計について話し合うためにScrapelessコミュニティに参加してください:Discord · Telegram。
Scrapelessの料金を確認し、app.scrapeless.comで無料のスクレイピングブラウザランタイムにサインアップしてください。
FAQ
Q: 隠されたAPIをスクレイピングすることは合法ですか?
内部リクエストをスクレイピングすることは、公開または許可されたデータにアクセスする場合に合法であり得ますが、法律、契約、事実は異なるため、サイトの利用規約を確認し、プロジェクトについて法律的なアドバイスを取得してください。
Q: 隠されたAPIは公開APIと同じですか?
隠されたAPIはフロントエンドによって内部で使用され、文書、安定性、または第三者アクセスの約束はありませんが、公開APIは意図的にサポートされた契約の下で公開されています。
Q: 隠されたAPIを検査するためにプロキシは必要ですか?
ローカルDevTools検査にはプロキシは不要ですが、承認された場所特有のデータセットや比例配分のワークフローには必要となる場合があります。
Q: 内部リクエストがアクセス拒否のページを返した場合はどうすればよいですか?
停止して返された表現、認可境界、プロジェクトのスコープを検査し、異なるヘッダーやトークンを許可として扱わないでください。
Q: DOMやスキーマの変更に対処するにはどうすればよいですか?
1つの既知のページアクションを再実行し、リクエストとレスポンス契約を比較し、nullableマッピングを更新し、内部レスポンスがもはや提供しないフィールドのレンダードDOMフォールバックを保持してください。
Q: 隠されたAPIスクレイパーはどれくらいの同時性を使用するべきですか?
サイトの公開ルール、認可、および観察された安定性がより高いレベルを支持するまで、ホストあたりのワーカーは3以下に同時性を維持してください。
Q: このワークフローはAIエージェントなしで実行できますか?
はい、DevToolsの発見、サニタイズされたリクエストの再現、スキーマバリデーション、ブラウザフォールバックは、AIエージェントを必要としない決定論的なエンジニアリングステップです。
Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。



