Puppeteer wait for all images to load then take screenshot

前端 未结 5 1001
抹茶落季
抹茶落季 2020-12-23 16:38

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

相关标签:
5条回答
  • 2020-12-23 17:09

    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.

    0 讨论(0)
  • 2020-12-23 17:10

    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

    0 讨论(0)
  • 2020-12-23 17:11

    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:

    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);
        });
      }));
    });
    
    0 讨论(0)
  • 2020-12-23 17:15

    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);
        });
      }));
    })
    
    0 讨论(0)
  • 2020-12-23 17:32

    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' });
    })();
    
    0 讨论(0)
提交回复
热议问题