web-dev-qa-db-ja.com

操り人形師はすべての画像が読み込まれるのを待ってからスクリーンショットを撮ります

私は Puppeteer を使用して、すべての画像が読み込まれたが機能しなかった後にWebサイトのスクリーンショットを撮ろうとしました。

ここに私がこれまでに手に入れたコードがあります。私は https://www.digg.com をサンプルWebサイトとして使用しています。

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

そのための 組み込みオプション があります。

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

networkidle0-少なくとも500ミリ秒間ネットワーク接続が0を超えていない場合、ナビゲーションが終了したと見なします

networkidle2-少なくとも500 msの間、ネットワーク接続が2つ以下の場合にナビゲーションが終了したと見なします。

追伸もちろん、Twitterのような無限スクロール、単一ページのアプリケーションで作業している場合は機能しません。

52
Vaviloff

別のオプション、すべての画像がロードされたときに実際にコールバックを取得するために評価する

このオプションは、wait networkidle0オプションをサポートしない setContent でも機能します。

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

私はまったく同じ問題に直面しています。私は解決策が使用することを伴うと感じています:

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
Wissa