Javascript Puppeteer 等待所有图像加载然后截屏
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46160929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Puppeteer wait for all images to load then take screenshot
提问by Petar Vasilev
I am using Puppeteerto try to take a screenshot of a website after all images have loaded but can't get it to work.
我正在使用Puppeteer尝试在所有图像加载后截取网站的屏幕截图,但无法使其正常工作。
Here is the code I've got so far, I am using https://www.digg.comas the example website:
这是我到目前为止的代码,我使用https://www.digg.com作为示例网站:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.digg.com/');
await page.setViewport({width: 1640, height: 800});
await page.evaluate(() => {
return Promise.resolve(window.scrollTo(0,document.body.scrollHeight));
});
await page.waitFor(1000);
await page.evaluate(() => {
var images = document.querySelectorAll('img');
function preLoad() {
var promises = [];
function loadImage(img) {
return new Promise(function(resolve,reject) {
if (img.complete) {
resolve(img)
}
img.onload = function() {
resolve(img);
};
img.onerror = function(e) {
resolve(img);
};
})
}
for (var i = 0; i < images.length; i++)
{
promises.push(loadImage(images[i]));
}
return Promise.all(promises);
}
return preLoad();
});
await page.screenshot({path: 'digg.png', fullPage: true});
browser.close();
})();
回答by Vaviloff
There is a built-in optionfor that:
有一个内置选项:
await page.goto('https://www.digg.com/', {"waitUntil" : "networkidle0"});
networkidle0- consider navigation to be finished when there are no more than 0 network connections for at least 500 ms
networkidle2- consider navigation to be finished when there are no more than 2 network connections for at least 500 ms.
networkidle0- 当至少 500 毫秒没有超过 0 个网络连接时,认为导航已完成
networkidle2- 当至少 500 毫秒没有超过 2 个网络连接时,认为导航已完成。
P.S. Of course it won't work if you're working with endless-scrolling-single-page-applications like Twitter.
PS 当然,如果您使用的是像 Twitter 这样的无限滚动单页应用程序,它当然不会起作用。
回答by Daniel Krom
Another option, actually evaluate to get callback when all images were loaded
另一种选择,实际评估以在所有图像加载时获取回调
This option will also work with setContentthat doesn't support the wait networkidle0option
此选项也适用于不支持等待选项的setContentnetworkidle0
await page.evaluate(async () => {
const selectors = Array.from(document.querySelectorAll("img"));
await Promise.all(selectors.map(img => {
if (img.complete) return;
return new Promise((resolve, reject) => {
img.addEventListener('load', resolve);
img.addEventListener('error', reject);
});
}));
})
回答by Grant Miller
Wait for Lazy Loading Images
等待延迟加载图像
You may want to consider scrolling down first using a method such as Element.scrollIntoView()to account for lazy loading images:
您可能需要考虑先使用诸如Element.scrollIntoView()延迟加载图像的方法向下滚动:
await page.goto('https://www.digg.com/', {
waitUntil: 'networkidle0', // Wait for all non-lazy loaded images to load
});
await page.evaluate(async () => {
// Scroll down to bottom of page to activate lazy loading images
document.body.scrollIntoView(false);
// Wait for all remaining lazy loading images to load
await Promise.all(Array.from(document.getElementsByTagName('img'), image => {
if (image.complete) {
return;
}
return new Promise((resolve, reject) => {
image.addEventListener('load', resolve);
image.addEventListener('error', reject);
});
}));
});
回答by Wissa
I'm facing the exact same issue. I have a feeling the solution will involve using:
我面临着完全相同的问题。我有一种感觉,解决方案将涉及使用:
await page.setRequestInterceptionEnabled(true);
page.on('request', interceptedRequest => {
//some code here that adds this request to ...
//a list and checks whether all list items have ...
//been successfully completed!
});

