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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:21:15  来源:igfitidea点击:

Puppeteer wait for all images to load then take screenshot

javascriptnode.jsgoogle-chromeautomationpuppeteer

提问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!
});

https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagesetrequestinterceptionenabledvalue

https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagesetrequestinterceptionenabledvalue