8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Puppeteerでヘッドレス Chromeのフルページスクリーンショットを撮る

Posted at

Webページのスクリーンショットを大量に取りたいという時に、便利なのがヘッドレス Chrome。
ヘッドレスとは、GUIからではなくCUIからChromeを使用するモードのことで、Chrome 59以降から搭載されました。
ヘッドレス Chromeを使うと、ブラウザで行う様々な操作をコマンドラインから行い、自動化することもできるようになります。

今回はこのヘッドレス ChromeをNode.jsのプログラムで制御するためのライブラリであるPuppeteerを使って、Webページ全体のスクロールショットを撮る方法を模索してみました。

まずはPuppeteerをインストール

npm i puppeteer

Puppeteerをインストールする際、自動でChromiumもインストールされますが、ローカルにあるChromeを使いたい場合には、puppeteer-coreのみでインストールすることもできます。

npm i puppeteer-core

puppeteer-coreを使用する場合、puppeteer.launchでブラウザを起動するときに、channel: 'chrome'というオプションを渡します。

const browser = await puppeteer.launch({
    //ローカルのChromeを使う
    channel: 'chrome',
    //ヘッドレスモードで起動
    headless: true,
    //言語は日本語に
    args: ['--lang=ja']
});

ブラウザでスクリーンショットを撮りたいページへ移動します。
スクリーンショットを撮りたいサイズでviewportを指定することもでき、deviceScaleFactorに2を指定することで、Retinaのスクリーンショットを撮ることも可能です。

const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800, deviceScaleFactor: 2 });
await page.goto('https://qiita.com/');

スクリーンショットを撮る時には、fullPageをtrueにしておくと、Webサイト全体のスクリーンショットが撮れます。

await page.screenshot({ path: './screenshot.png', fullPage: true });

が、これだけだと少し問題があって・・・・
スクロールに応じてコンテンツを読み込むlazyloadの部分があったりだとか、アニメーションなどが付いているときに、その部分がうまくスクリーンショットに反映されないという問題があります。

これに対処するためには、Webページに移動した後に、一旦ページの下までスクロールさせることが必要です。
少しややこしいので、今回はpuppeteer-autoscroll-downというライブラリの力を借ります。

npm i puppeteer-autoscroll-down

まずは念の為、スクロール位置を一番上に。
page.evaluateは、引数に実行したいスクリプトを渡すと、そのスクリプトをページ上で実行してくれます。

await page.evaluate(_ => {
  window.scrollTo(0, 0);
});

そして、puppeteer-autoscroll-downを使って、ページの下までスクロールします。
渡せるオプションは、
size: 一回のスクロール量
delay: スクロールを実行する間隔
stepsLimit: スクロールする回数の最大値
です。
無限スクロールが実装されているページなどはかなり長くなってしまうので、stepsLimitを設定して、よい塩梅にしておくと良いと思います。

const lastPosition = await scrollPageToBottom(page, {
  size: 400,
  delay: 250,
  stepsLimit: 50
})

最後にブラウザを閉じます。

await browser.close();

コードの全体はこちら

const puppeteer = require('puppeteer-core');
const { scrollPageToBottom } = require('puppeteer-autoscroll-down');
 
(async () => {
  const browser = await puppeteer.launch({
    channel: 'chrome',
    headless: true,
    args: ['--lang=ja']
  });
  const page = await browser.newPage();
  await page.setViewport({ width: 1280, height: 800, deviceScaleFactor: 2 });
  await page.goto('https://qiita.com/');

  await page.evaluate(_ => {
        window.scrollTo(0, 0);
  });
  const lastPosition = await scrollPageToBottom(page, {
    size: 400,
    delay: 250,
    stepsLimit: 50
  })

  await page.screenshot({ path: './screenshot.png', fullPage: true });
  await browser.close();

})();

参考にさせていただいた記事
puppeteerで始めるブラウザ操作の自動化
puppeteer-coreとMacにインストール済みのChromeを使って自動操作
Puppeteer with lazy loading images
puppeteerで言語を日本語に設定する方法

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?