我有以下代码可从特定网站提取所有请求(获取所有图像,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中所示?
答案 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看看发生了什么。如果您在网络标签中查看瀑布图,则它看起来像这样:
看到那条红线吗?这是加载事件。默认情况下,page.goto
等待此事件。但是在我们的例子中,实际上在触发事件后有一些文件正在加载(文件位于红线右边)。为了也等待这些资源加载,我们可以使用page.goto
函数的选项之一。使用waitUntil: 'networkidle0'
脚本将等待直到不再有网络活动为止。
因此,如果您从顶部将page.goto
行切换为该行,则应该看到预期的请求数:
await page.goto('https://stackoverflow.com', { waitUntil: 'networkidle0' });
使用此设置时,上面的代码为我返回了39
,这正是您所期望的。