web-dev-qa-db-fra.com

Le marionnettiste attend que toutes les images soient chargées, puis prend une capture d'écran

J'utilise Puppeteer pour essayer de prendre une capture d'écran d'un site Web après que toutes les images ont été chargées mais ne peuvent pas le faire fonctionner.

Voici le code que j'ai jusqu'à présent, j'utilise https://www.digg.com comme exemple de site:

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();
})();
15
Petar Vasilev

Il y a une option intégrée pour cela: 

await page.goto('https://www.digg.com/', {"waitUntil" : "networkidle0"});

networkidle0 - considère que la navigation est terminée lorsqu'il n'y a pas plus de 0 connexions réseau pendant au moins 500 ms

networkidle2 - considère que la navigation est terminée lorsqu'il n'y a pas plus de 2 connexions réseau pendant au moins 500 ms.

P.S. Bien sûr, cela ne fonctionnera pas si vous travaillez avec des applications sans fin avec une page, telles que Twitter.

42
Vaviloff

Une autre option, évaluer pour obtenir un rappel lorsque toutes les images ont été chargées

Cette option fonctionnera également avec setContent qui ne prend pas en charge l'option wait networkidle0

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);
    });
  }));
})
8
Daniel Krom

Je suis confronté exactement au même problème… J'ai l'impression que la solution impliquera l'utilisation de:

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#pagesetreququinterinterceptionenabledvalue

0
Wissa