76
63

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 3 years have passed since last update.

Puppeteer を使って web ページの画像差分を作成する

Last updated at Posted at 2019-03-11

ブラウザのオートメーションを使って 2 つの web ページの差分画像を作成してみます。 JavaScript のライブラリだけを使ってこれを実現します。

ライブラリのインストール

ヘッドレス Chrome (Chromium) を制御するライブラリ Puppeteerを使います。
yarn または npm を使い、Puppeteer と他に必要なライブラリをインストールします。

$ mkdir my-project
$ cd my-project
$ yarn init # or npm init
$ yarn add puppeteer looks-same # or npm install puppeteer looks-same

looks-same は、2 つの画像を比較して同じ画像なのかを判定したり、差分画像を生成することができるライブラリです。

ここでは、プログラムを作成する前に、生成する画像を保存するディレクトリを作成しておきます。

$ mkdir dist

 Puppetter を制御する JavaScript を作成する

Puppetter の API を使い、ブラウザを制御するプログラムを作成します。ここでは URL_AURL_B という変数名で比較する 2 つの web ページを指定します。
作成するプログラムでは以下の操作を行います。

  1. ヘッドレス Chrome を起動する
  2. URL_A に遷移する
  3. URL_A のスクリーンショットを作成する
  4. URL_B に遷移する
  5. URL_B のスクリーンショットを作成する
  6. 作成した 2 個のスクリーンショットから差分画像を生成する
// index.js
const puppeteer = require('puppeteer')
const looksSame = require('looks-same')

const URL_A = 'https://example.com/a'
const URL_B = 'https://example.com/b'

;(async () => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  await page.setViewport({ width: 512, height: 100 })

  const pathA = 'dist/a.png'
  const pathB = 'dist/b.png'
  const pathDiff = 'dist/diff.png'
  await page.goto(URL_A)
  await page.screenshot({ path: pathA })
  await page.goto(URL_B)
  await page.screenshot({ path: pathB })

  await new Promise((resolve, reject) =>
    looksSame.createDiff(
      {
        reference: pathA,
        current: pathB,
        diff: pathDiff,
        highlightColor: '#ff00ff'
      },
      error => (error ? reject() : resolve())
    )
  )

  await browser.close()
})()

プログラムを実行します。

$ node index.js

プログラムを実行すると、 dist ディレクトリの中にスクリーンショットとその差分が生成されているのがわかります。 なお、画像のうちの異なる部分はピンク色(#ff00ff)でハイライトされます。

実際の例

以下の微妙に内容が異なる 2 つの web ページのスクリーンショットの差分画像を実際に作成してみます。

<!-- a.html -->
<!DOCTYPE html>
<html>
  <body>
    <h1 class="title">Helloo!</h1>
    <p class="content">This is page A!</p>
  </body>
</html>
<!-- b.html -->
<!DOCTYPE html>
<html>
  <body>
    <h1 class="title">Hello!</h1>
    <p class="content">This is page B!</p>
  </body>
</html>

テキストの差分はこんな感じ。

$ diff a.html b.html
1c1
< <!-- a.html -->
---
> <!-- b.html -->
5,6c5,6
<     <h1 class="title">Helloo!</h1>
<     <p class="content">This is page A!</p>
---
>     <h1 class="title">Hello!</h1>
>     <p class="content">This is page B!</p>

前述のプログラムにハードコードされている URL を適切に変更します。
別途ウェブサーバーを立ち上げるなどして、上記の HTML に下記の URL でアクセスできるようにしておいてください。

// index.js
// ...
const URL_A = 'http://127.0.0.1:8080/a.html'
const URL_B = 'http://127.0.0.1:8080/b.html'
// ...

プログラムを実行します。

node index.js

以下のように画像が生成されます。

a.png
a.png

b.png
b.png

差分画像
diff.png

まとめ

Node.js を使って2つの web ページのスクリーンショットの差分画像を作成し、コンテンツの違いやスタイルの違いなどを検出できることが分かりました。Production と 開発環境の間でどのような見た目の変化が生じているかを可視化したり、 CI などで回してチャットツールに差分画像をポストするなども簡単にできそうですね。

76
63
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
76
63

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?