web-dev-qa-db-ja.com

Chromeでページを読み込むときに、すべてのネットワーク要求と完全な応答データをキャプチャするにはどうすればよいですか?

Puppeteerを使用して、URLをChromeに読み込み、次の情報をキャプチャします。

  • リクエストURL
  • リクエストヘッダー
  • 投稿データをリクエストする
  • 応答ヘッダーテキスト(set-cookieなどの重複ヘッダーを含む)
  • 転送された応答サイズ(つまり、圧縮サイズ)
  • 完全な応答本文

完全な応答本文を取得することが、私にとって問題の原因です。

私が試したこと:

  • response.buffer で応答コンテンツを取得します- ナビゲーションでバッファが消去されます
  • リクエストのインターセプトとgetResponseBodyForInterceptionの使用-これは、 encodedLengthにアクセスできなくなった が可能なことを意味し、場合によっては正しいリクエストおよびレスポンスヘッダーの取得に問題がありました
  • ローカルプロキシを使用しても機能しますが、これによりページの読み込み時間が大幅に遅くなりました(また、証明書エラーなどの動作も変更されました)

理想的には、ソリューションのパフォーマンスへの影響はわずかで、通常のページのロードと機能上の違いはありません。また、Chromeの分岐を避けたいです。

17
Matt Zeunert

要求ごとに page.setRequestInterception() を使用して要求インターセプトを有効にできます。次に、 page.on('request') 内で-を使用できます _request-promise-native_ Puppeteerで request.continue() を使用してリクエストを続行する前に応答データを収集する仲介者として機能するモジュール。

ここに完全な例があります:

_'use strict';

const puppeteer = require('puppeteer');
const request_client = require('request-promise-native');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  const result = [];

  await page.setRequestInterception(true);

  page.on('request', request => {
    request_client({
      uri: request.url(),
      resolveWithFullResponse: true,
    }).then(response => {
      const request_url = request.url();
      const request_headers = request.headers();
      const request_post_data = request.postData();
      const response_headers = response.headers;
      const response_size = response_headers['content-length'];
      const response_body = response.body;

      result.Push({
        request_url,
        request_headers,
        request_post_data,
        response_headers,
        response_size,
        response_body,
      });

      console.log(result);
      request.continue();
    }).catch(error => {
      console.error(error);
      request.abort();
    });
  });

  await page.goto('https://example.com/', {
    waitUntil: 'networkidle0',
  });

  await browser.close();
})();
_
10
Grant Miller

要求ログを実際のコンテンツと一緒に書き込めるクイックプロキシサーバーを検索することをお勧めします。

ターゲットのセットアップは、プロキシサーバーがログファイルを書き込むだけで、ログを分析し、必要な情報を検索できるようにすることです。

プロキシが動作している間はリクエストを傍受しないでください(これにより速度が低下します)

発生する可能性のあるパフォーマンスの問題(ロガーセットアップとしてのプロキシを使用)は、主にTLSサポートに関連しています。プロキシセットアップでの高速TLSハンドシェイク、HTTP2プロトコルの許可に注意してください

例えば。 Squidベンチマーク 数百のRPSを処理できることを示します。これはテスト目的には十分なはずです

4

フィドラー 」というツールを使用することをお勧めします。 URL urlを読み込むときに言及したすべての情報をキャプチャします。

2
ScrapCode

操り人形のみのソリューション

これは、操り人形師だけで行うことができます。ナビゲーションで_response.buffer_がクリアされることを説明している問題は、各リクエストを次々に処理することで回避できます。

使い方

以下のコードは _page.setRequestInterception_ を使用してすべてのリクエストをインターセプトします。現在処理中/待機中のリクエストがある場合、新しいリクエストはキューに入れられます。次に、 response.buffer() を使用できます。並列要求がないため、他の要求が非同期的にバッファーを消去するという問題はありません。現在処理されている要求/応答が処理されるとすぐに、次の要求が処理されます。

コード

_const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch();
    const [page] = await browser.pages();

    const results = []; // collects all results

    let paused = false;
    let pausedRequests = [];

    const nextRequest = () => { // continue the next request or "unpause"
        if (pausedRequests.length === 0) {
            paused = false;
        } else {
            // continue first request in "queue"
            (pausedRequests.shift())(); // calls the request.continue function
        }
    };

    await page.setRequestInterception(true);
    page.on('request', request => {
        if (paused) {
            pausedRequests.Push(() => request.continue());
        } else {
            paused = true; // pause, as we are processing a request now
            request.continue();
        }
    });

    page.on('requestfinished', async (request) => {
        const response = await request.response();

        const responseHeaders = response.headers();
        let responseBody;
        if (request.redirectChain().length === 0) {
            // body can only be access for non-redirect responses
            responseBody = await response.buffer();
        }

        const information = {
            url: request.url(),
            requestHeaders: request.headers(),
            requestPostData: request.postData(),
            responseHeaders: responseHeaders,
            responseSize: responseHeaders['content-length'],
            responseBody,
        };
        results.Push(information);

        nextRequest(); // continue with next request
    });
    page.on('requestfailed', (request) => {
        // handle failed request
        nextRequest();
    });

    await page.goto('...', { waitUntil: 'networkidle0' });
    console.log(results);

    await browser.close();
})();
_
2
Thomas Dondorf

Chromeを押してから[ネットワーク]タブに移動すると、ウェブサイトが送信するすべてのhttpリクエストが表示されます。言及した詳細を表示できます。

1
Jose Rodriguez