Как получить поток загрузки (буфер), используя puppeteer? - PullRequest
1 голос
/ 29 марта 2019

Я хочу получить загружаемый контент (буфер) и вскоре после этого сохранить данные в моей учетной записи S3. До сих пор я не смог найти какое-то решение ... Просматривая примеры в Интернете, я заметил, что есть много людей с этой проблемой. Я попытался (безуспешно) использовать событие page.on ("response") для получения необработанного содержимого ответа в следующем фрагменте:

const bucket = [];
await page.on("response", async response => {
        const url = response.url();
        if (
          url ===
          "https://the.earth.li/~sgtatham/putty/0.71/w32/putty-0.71-installer.msi"
        ) {
          try {
            if (response.status() === 200) {
              bucket.push(await response.buffer());
              console.log(bucket);
              // I got the following: 'Protocol error (Network.getResponseBody): No resource with given identifier found' }
            }
          } catch (err) {
            console.error(err, "ERROR");
          }
        }
      });

С таким кодом, приведенным выше, я хотел бы обнаружить событие диалога загрузки и затем каким-то образом получить двоичный контент.

Я не уверен, что это правильный подход. Я заметил, что некоторые люди используют решение, основанное на чтении файлов, другими словами, после завершения загрузки они читают сохраненный файл с диска. Похожее обсуждение: https://github.com/GoogleChrome/puppeteer/issues/299.

Мой вопрос: существует ли какой-либо способ (с использованием puppeteer) перехватить поток загрузки без необходимости сохранять файл на диск раньше?

Большое спасибо.

1 Ответ

2 голосов
/ 29 марта 2019

Проблема в том, что буфер очищается, как только происходит какой-либо запрос навигации. Это может быть перенаправление или перезагрузка страницы в вашем случае.

Чтобы решить эту проблему, вам нужно убедиться, что страница не выполняет никаких запросов навигации, если вы не закончили загрузку своего ресурса. Для этого мы можем использовать page.setRequestInterception.

Существует простое решение, которое может помочь вам начать, но не всегда может работать, и более сложное решение этой проблемы.

Простое решение

Это решение отменяет любые запросы навигации после первоначального запроса. Это означает, что любая перезагрузка или навигация на странице не будут работать. Поэтому буферы ресурсов не очищаются.

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

let initialRequest = true;
await page.setRequestInterception(true);

page.on('request', request => {
    // cancel any navigation requests after the initial page.goto
    if (request.isNavigationRequest() && !initialRequest) {
        return request.abort();
    }
    initialRequest = false;
    request.continue();
});

page.on('response', async (response) => {
    if (response.url() === 'RESOURCE YOU WANT TO DOWNLOAD') {
        const buffer = await response.buffer();
        // handle buffer
    }
});

await page.goto('...');

Расширенное решение

Следующий код будет обрабатывать каждый запрос один за другим. Если вы загружаете буфер, он будет ждать загрузки буфера, прежде чем обрабатывать следующий запрос.

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

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();
    if (response.url() === 'RESOURCE YOU WANT TO DOWNLOAD') {
        const buffer = await response.buffer();
        // handle buffer
    }
    nextRequest(); // continue with next request
});
page.on('requestfailed', nextRequest);

await page.goto('...');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...