【问题标题】:How to get the download stream (buffer) using puppeteer?如何使用 puppeteer 获取下载流(缓冲区)?
【发布时间】:2019-03-28 23:20:28
【问题描述】:

我想获取下载内容(缓冲区),然后很快将数据存储在我的 S3 帐户中。到目前为止,我无法找到一些解决方案......在网上寻找一些例子,我注意到有很多人有这个问题。我尝试(不成功)使用 page.on("response") 事件来检索原始响应内容,根据以下 sn-p:

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)来拦截下载流,而无需将文件保存到磁盘?

非常感谢。

【问题讨论】:

    标签: node.js puppeteer


    【解决方案1】:

    问题是,一旦发生任何类型的导航请求,缓冲区就会被清除。在您的情况下,这可能是重定向或页面重新加载。

    要解决这个问题,你需要确保在你的资源没有下载完成的情况下,页面不会发出任何导航请求。为此,我们可以使用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('...');
    

    【讨论】:

    • Thomas,毕竟我要感谢您的帮助。虽然,发现 Puppeteer 中有一个严重的错误会阻碍我的旅程。当我们设置 page.setRequestInterception(true) 时,Chromium 将无法解析页面。浏览器永远处于 about:blank 状态。该问题在此处显示:github.com/GoogleChrome/puppeteer/issues/3118 虽然此错误未解决,但此处描述的原始问题将存在。
    • 暂时,我正在克服它并在下载完成后从内存(虚拟磁盘)中读取文件。不幸的是,我使用的是传统的 Node FS 方法。您是否尝试过使用 Chromium 将 setRequestInterception 设置为 true?对不起,我的英语有点弱。如果您在我的文字中发现一些错误,请不要担心。 ://
    • 不知道这些request interception problems。您还可以尝试使用请求中的 cookie 和标头再次使用 https.get 下载请求。但这会触发第二次下载。
    • 我会听从你的建议 Thomas 并评估什么对我来说是最好的。谢谢。
    • 这个解决方案对我没有帮助,我仍然收到关于“等待”的错误 const buffer = await res.buffer();你是怎么解决的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-07
    • 1970-01-01
    • 2023-04-06
    • 2023-03-22
    • 1970-01-01
    • 2013-06-24
    相关资源
    最近更新 更多