サイトの各ページのスクリーンショットを自力で作るのが大変だったのでPuppeteerで一括作成してみた

サイトの各ページのスクリーンショットを自力で作るのが大変だったのでPuppeteerで一括作成してみた

ある日、100ページ近くあるサイトの各ページのページ全体スクリーンショットを作成しなければいけない用事が出来まして…

1つ1つのページをブラウザの標準機能や拡張機能を使ってスクリーンショットを撮っていくのはめちゃめちゃ大変…

そこで、Puppeteerというライブラリを使ってNode.jsでヘッドレスブラウザを使うことで、面倒なスクリーンショット保存作業をプログラムに全部やってもらうようにしてみました!

PuppeteerはNode.jsのライブラリなので、Node.jsがインストールされている前提で話を進めます。
Node.jsがインストールされていない場合は別途Google検索等でインストールの方法を調べてインストール作業を先にしておいてください。

Puppeteerのインストール

A Node.js library providing a high-level API to control headless Chrome or Chrom…
developer.chrome.com

Puppeteerのインストール。

npm install -D puppeteer

これだけスッキリ。

スクショを撮るためのプログラム

コード全体

const puppeteer = require('puppeteer');
const fs = require('fs');

// URLの一覧を読み込むファイルパス.
const URL_LIST_PATH = 'url-list.txt';
// スクリーンショット出力先.
const SCREENSHOT_DIR = 'screenshot';
// ビューポート設定.
const VIEWPORT = { width: 1920, height: 1080, deviceScaleFactor: 2 };

(async () => {
    console.log('--- START ---');
    // URLのリストをテキストファイルから取得.
    const text = fs.readFileSync(URL_LIST_PATH, 'utf8');
    const urlList = text.toString().split(/\n/);

    // 出力先の準備.
    if(fs.existsSync(SCREENSHOT_DIR)) {
        fs.rmSync(SCREENSHOT_DIR, { recursive: true, force: true }); 
    }
    fs.mkdirSync(SCREENSHOT_DIR);
    
    // Puppeteer 起動!
    const browser = await puppeteer.launch();
    
    // ページごとにスクショ作成
    let index = 1;
    for (key in urlList) {
        const url = urlList[key];
        // ファイル保存先.
        const fileName = `000${index}`.slice(-3);
        const filePath = `./${SCREENSHOT_DIR}/${fileName}.png`;

        // 設定等
        const page = await browser.newPage();
        await page.setViewport(VIEWPORT);
        if(!url) {
            continue;
        }
        await page.goto(url);

        // ページ内でJS実行.
        await page.evaluate(_ => {
            // クッキー同意ボタン押す.
            const button = document.querySelector('[data-action="enable"]');
            if(button) {
                button.click();
            }
            // 下までスクロールして戻す.
            scroll(0, 99999);
            setTimeout(() => {
                scroll(0, 0);
            }, 200);
        });
    
        await page.screenshot({
            path: filePath,
            fullPage: true,
        });
        console.log(`screenshot: ${url}`);
        index++;
    }

    await browser.close();
    console.log('--- END ---');
})();

このコードを例えば screenshot.js として保存します。

また、スクリーンショットを撮る対象ページのURLをscreenshot.jsと同階層にあるurl-list.txtから読み込むようになっているので、url-list.txtを作成して対象URLを1件1行で書き込んでおきます。

スクリーンショットを大量に取る必要が出てきた時に作ったやつ. Contribute to yosiakatsuki/screenshot-tool develo…
github.com

改行区切りテキストにしておいたほうがエクセルやGoogleスプレッドシートからごそっとコピペできて楽かな?と思ってテキストファイルにしています。

僕が作ったコードの仕様ではスクリーンショットは screenshot ディレクトリに作成するようにしています。ココらへんはご自身の都合に合わせて変更してみてください。

コードの実行はこちら▼

node screenshot.js

注意点として、コードの中で出力先フォルダを中身ごとごっそり削除してまた作り直しているので、わざわざ出力先フォルダを手動で削除する必要はありません。何度も連続で実行出来ます。

その代わり、作成したスクリーンショットを別の場所に移すのを忘れて再度コードを実行すると、前に撮ったスクリーンショットは消えてなくなるのでご注意ください。

ビューポートの設定

ビューポートの設定は下記の部分で行っています。

// ビューポート設定.
const VIEWPORT = { width: 1920, height: 1080, deviceScaleFactor: 2 };

適宜都合のいい画面サイズに変更してみてください。

スクロールアニメーションの発火やcookie同意ボタン対処

下記部分でページ内でいくつかJavaScriptを使った処理をしています。


// ページ内でJS実行.
await page.evaluate(_ => {
    // クッキー同意ボタン押す.
    const button = document.querySelector('[data-action="enable"]');
    if(button) {
        button.click();
    }
    // 下までスクロールして戻す.
    scroll(0, 99999);
    setTimeout(() => {
        scroll(0, 0);
    }, 200);
});

document.querySelector('[data-action="enable"]') に続く部分でクッキー同意ボタンを探してクリックさせました。

ココらへんはサイトによって調整が必要になる部分で使い捨てになりがちなので雑に作りました。目的が果たせればOK。

また、スクロールによって発火するアニメーションのあるサイトなどの対処として、一度99999pxスクロールさせて、その後一番上まで戻す処理をしています。

スクロール量なども適宜調整してみてください。

まとめ

ビューポートの設定を変えればモバイルのレイアウトでもスクショが取れそうだったので良きですね。

ただ、ユーザーエージェントでモバイル・PCのレイアウトを変えているサイトでスクショを撮る必要が出てきたらまた調整しないとですね…

何枚もスクショを撮る必要が出てきたときに使っていきたいと思います。

スクリーンショットを大量に取る必要が出てきた時に作ったやつ. Contribute to yosiakatsuki/screenshot-tool develo…
github.com

ではまた。