人偶不会返回来自特定网站的所有请求

时间:2019-04-29 21:21:52

标签: node.js puppeteer

我有以下代码可从特定网站提取所有请求(获取所有图像,css,脚本,字体...)

var totalRequests = 0;

    puppeteer.launch().then(async browser => {
        const page = await browser.newPage();
        await page.setRequestInterception(true);
        page.on('request', interceptedRequest => {
            interceptedRequest.continue();
        });
        page.on('response', response => {
            totalRequests = totalRequests + 1;
            console.log('Url: ' + response.url());
        });
        await page.goto('https://stackoverflow.com');
        await browser.close().then(() => {
            res.send('Requests: ' + totalRequests);
        });

太好了,在控制台中,我可以看到 stackoverflow.com 中的所有网址(Css文件,图像文件,字体文件和Javascript文件)以及所请求的文件总数(在这种情况下,我看到了31个请求),但由于某种原因,我最终注意到该代码无法返回所有页面请求。

如果我们转到Google Chrome浏览器,请按F12键,转到“网络”部分并重新加载页面(考虑到您使用的是 https://stackoverflow.com 网址),我们将总共看到39个-40请求文件。

问题是我的代码仅返回30到31个请求,并且在控制台中我看不到所有显示在Chrome上的链接。可能会发生什么?我该怎么做才能返回所有请求,如Google Chrome中所示?

1 个答案:

答案 0 :(得分:1)

主要问题

对于stackoverflow.com,已加载资源的数量取决于浏览器窗口的大小。如果您的视口允许,则stackoverflow将在右侧栏上显示广告。但是,只有在视口足够大的情况下,才会加载相应的资源(JavaScript,图像等)。您可以尝试减小窗口大小,直到隐藏右侧栏,然后重新加载页面,自己尝试一下。 DevTools将向您显示不同数量的已加载资源。

示例代码

以下示例显示如何通过设置defaultViewport属性来模拟更大的浏览器窗口。请注意,在此示例中,我完全使用了 async / await 语法,并删除了page.setRequestInterception调用,因为如果没有它,response事件也会被触发(您只需要如果您确实要修改请求或响应,请使用它。

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({ // headless: false, devtools: true,
        defaultViewport: { width: 1600, height: 800 }
    });
    const page = await browser.newPage();

    var totalRequests = 0;
    page.on('response', () => {
        totalRequests = totalRequests + 1;
    });

    await page.goto('https://stackoverflow.com');
    console.log(totalRequests);

    await browser.close();
})();

这会为我返回30,这仍然不是我们期望的数字(〜40)。

等待所有资源加载完毕

您的代码还有另一个问题。让我们打开DevTools看看发生了什么。如果您在网络标签中查看瀑布图,则它看起来像这样:

Waterfall Diagram in Chrom DevTools

看到那条红线吗?这是加载事件。默认情况下,page.goto等待此事件。但是在我们的例子中,实际上在触发事件后有一些文件正在加载(文件位于红线右边)。为了也等待这些资源加载,我们可以使用page.goto函数的选项之一。使用waitUntil: 'networkidle0'脚本将等待直到不再有网络活动为止。

因此,如果您从顶部将page.goto行切换为该行,则应该看到预期的请求数:

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

使用此设置时,上面的代码为我返回了39,这正是您所期望的。