web-dev-qa-db-fra.com

Comment puis-je capturer toutes les demandes réseau et les données de réponse complète lors du chargement d'une page dans Chrome?

En utilisant Puppeteer, je voudrais charger une URL dans Chrome et capturer les informations suivantes:

  • uRL de demande
  • en-têtes de demande
  • demander des données de publication
  • texte des en-têtes de réponse (y compris les en-têtes en double comme set-cookie)
  • taille de réponse transférée (c'est-à-dire taille compressée)
  • corps de réponse complète

La capture du corps de réponse complet est ce qui cause les problèmes pour moi.

Ce que j'ai essayé:

  • Obtention du contenu des réponses avec response.buffer - cela ne fonctionne pas s'il y a des redirections à tout moment, car les tampons sont effacés lors de la navigation
  • intercepter les demandes et utiliser getResponseBodyForInterception - cela signifie que je peux ne plus accéder à encodedLength , et j'ai également eu des problèmes pour obtenir les en-têtes de demande et de réponse corrects dans certains cas
  • L'utilisation d'un proxy local fonctionne, mais cela a considérablement ralenti les temps de chargement des pages (et a également modifié certains comportements, par exemple les erreurs de certificat)

Idéalement, la solution ne devrait avoir qu'un impact mineur sur les performances et ne présenter aucune différence fonctionnelle par rapport au chargement normal d'une page. Je voudrais également éviter de bifurquer Chrome.

17
Matt Zeunert

Vous pouvez activer une interception de demande avec page.setRequestInterception() pour chaque demande, puis, à l'intérieur page.on('request') , vous pouvez utiliser le - request-promise-native module pour agir en tant qu'intermédiaire pour recueillir les données de réponse avant de poursuivre la demande avec request.continue() dans Puppeteer.

Voici un exemple de travail complet:

'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

Je vous suggère de rechercher un serveur proxy rapide qui permet d'écrire les journaux des demandes avec le contenu réel.

La configuration cible consiste à permettre au serveur proxy d'écrire simplement un fichier journal, puis d'analyser le journal, en recherchant les informations dont vous avez besoin.

Ne pas intercepter les demandes pendant que le proxy fonctionne (cela entraînera un ralentissement)

Les problèmes de performances (avec proxy comme configuration de l'enregistreur) que vous pouvez rencontrer sont principalement liés au support TLS, veuillez faire attention à permettre une prise de contact TLS rapide, protocole HTTP2 dans la configuration du proxy

Par exemple. Squid benchmarks montre qu'il est capable de traiter des centaines de RPS, ce qui devrait être suffisant pour les tests

4
Andrii Muzalevskyi

Je suggérerais d'utiliser un outil à savoir ' fiddler '. Il capturera toutes les informations que vous avez mentionnées lorsque vous chargez une URL URL.

2
ScrapCode

Solution réservée aux marionnettistes

Cela peut être fait avec un marionnettiste seul. Le problème que vous décrivez que le response.buffer Est effacé lors de la navigation, peut être contourné en traitant chaque demande l'une après l'autre.

Comment ça marche

Le code ci-dessous utilise page.setRequestInterception pour intercepter toutes les demandes. S'il y a actuellement une demande en cours de traitement/en attente, de nouvelles demandes sont placées dans une file d'attente. Ensuite, response.buffer() peut être utilisé sans le problème que d'autres requêtes peuvent effacer le tampon de manière asynchrone car il n'y a pas de requêtes parallèles. Dès que la demande/réponse actuellement traitée est traitée, la prochaine demande sera traitée.

Code

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

allez à Chrome appuyez sur F12, puis allez dans l'onglet "réseau", vous pouvez y voir toutes les requêtes http que le site envoie, vous pourrez voir les détails que vous avez mentionnés.

1
Jose Rodriguez