I am using Puppeteer to try to take a screenshot of a website after all images have loaded but can\'t get it to work.
Here is the code I\'ve got so far, I am using h
There is a built-in option for 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.
P.S. Of course it won't work if you're working with endless-scrolling-single-page-applications like Twitter.
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!
});
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagesetrequestinterceptionenabledvalue
You may want to consider scrolling down first using a method such as Element.scrollIntoView() to account for lazy loading images:
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);
});
}));
});
Another option, actually evaluate to get callback when all images were loaded
This option will also work with setContent that doesn't support the wait networkidle0
option
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);
});
}));
})
I found a solution which is applicable to multiple sites using the page.setViewPort(...) method as given below:
const puppeteer = require('puppeteer');
async(() => {
const browser = await puppeteer.launch({
headless: true, // Set to false while development
defaultViewport: null,
args: [
'--no-sandbox',
'--start-maximized', // Start in maximized state
],
});
const page = await = browser.newPage();
await page.goto('https://www.digg.com/', {
waitUntil: 'networkidle0', timeout: 0
});
// Get scroll width and height of the rendered page and set viewport
const bodyWidth = await page.evaluate(() => document.body.scrollWidth);
const bodyHeight = await page.evaluate(() => document.body.scrollHeight);
await page.setViewport({ width: bodyWidth, height: bodyHeight });
await page.waitFor(1000);
await page.screenshot({path: 'digg-example.png' });
})();