PuppeteerでWebページの差分をscreenshot画像で確認する方法

PuppeteerでWebページの差分確認

PuppeteerでWebページの差分確認はページ内のテキストを取得すれば簡単にできるが、それだと画像や余白などの変化に気付くことができない。

そのため、Webページの画像や余白などの差分を確認するには修正前と修正後のスクリーンショット画像を比較する必要がある。

これらを手作業でやるのは手間がかかるが、Puppeteerとimage-diffを使用すればコマンドを入力するだけで簡単にできる。

image-diffとは

その名の通り画像の差分(diff)を確認するためのもの。

Puppeteerはスクリーンショット画像は保存できるが、画像の差分までは検出できないためimage-diffも使用する。

インストール手順

まずmkdir my-diffのような適当なフォルダを作成してcd my-diffで移動する。

次にnpm init -yを実行した後に以下のコマンドでpuppeteerとimage-diffをインストールする。

npm i -D puppeteer image-diff

インストールが完了したらdiff.jsのようなファイルを作成して画像差分を確認するためのコードをこのように作成する。

const fs = require('fs');
const puppeteer = require('puppeteer');
const imageDiff = require('image-diff');

fs.access('screenshot.png', err => {
  if (!err) {
    fs.rename('screenshot.png', 'screenshot.old.png', () => {});
  }
});

puppeteer.launch({
  headless: false,
  slowMo: 100
}).then(async browser => {
  const page = await browser.newPage();
  const url = process.argv[2];
  await page.goto(url);
  await page.$eval('.widget-area .adsense', e => e.remove());
  await page.screenshot({path: 'screenshot.png'});
  fs.access('screenshot.old.png', err => {
    if (!err) {
      imageDiff({
        actualImage: 'screenshot.png',       // 元となる画像
        expectedImage: 'screenshot.old.png', // 比較する画像
        diffImage: 'screenshot.diff.png',    // 同じであれば真っ白
      }, (err, imagesAreSame) => {
        if (imagesAreSame) {
          console.log('前回と同じ画像です。');
        } else {
          console.log('前回と異なる画像です。');
        }
      });
    } else {
      console.log('最初の画像を保存しました。')
    }
  });
  await browser.close();
});

実行する際はnode diff.js [URL]となる。iwb.jpの場合は以下の通り。

node diff.js https://iwb.jp/

iwb.jpのようにランダムで表示される広告があると修正がなくても差分が発生してしまうためremove()などであらかじめ非表示にすると良いだろう。

await page.$eval('.widget-area .adsense', e => e.remove());

スクリーンショット画像はフルページの場合はfullPage: trueを付ける。

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

前回のスクリーンショットと差分がある場合は「前回と異なる画像です。」と表示され、screenshot.diff.pngに差分のある箇所が赤く表示される。
PuppeteerでWebページの差分をscreenshot画像で確認する方法