WindowsとWSLでHeadless Chromeを使ってみよう！

#はじめに
今回、はじめてアドベントカレンダーなるものに参加することになりました松原です。
よろしくお願いします！

まずは簡単に自己紹介
沖縄のIT企業でリゾートウェディングやマリンスポーツ＆アクティビティのポータルサイトの運用をしています。
色々とあって今年、約５年ぶりにエンジニアとして復帰したのですが周りについていくのに必死で、浦島太郎状態ですが、これをキッカケに学んだことをアウトプットしていきたいと思います！

#ここからが本題
さて、今回はちょっと前から気になっていたコマンドラインからブラウザの動作確認ができる「Headless Chrome」に関して書いていこうと思います。

##「Headless Chrome」とは
まず「Headless Chrome」とは通常はGUIを通してChromeを実行しますが、Headless Chromeはコマンドラインを通して実行します。つまりGUIを持たないブラウザということです。

##まずは実行環境です。
では、まずは`Headless Chrome`を実行した環境です。
今回はWindows10とUbuntuでの実行環境です。

- Windows
    - Windows10
    - Google Chrome 79.0.3945.79


- WSL
    - Ubuntu 18.04.3
    - Google Chrome 71.0.3578.80


###スクリーンショットを取ってみよう
では早速Windows10でHeadless Chromeを使ってブラウザのスクリーンショットを取りましょう。
まずChromeの実行ファイルは`C:\Program Files (x86)\Google\Chrome\Application`に保存されているので、そのフォルダにパスを通しててください。
パスの設定に関してはこちらを参考にしてください。
https://qiita.com/shuhey/items/7ee0d25f14a997c9e285

パスを通したらコマンドプロンプトを**管理者権限**で実行し、コマンドを実行してスクリーンショットを取ります。
今回は宣伝も兼ねて弊社で運営しているみーぐるのスクショを取ります。
**沖縄マリンスポーツ＆アクティビティ「みーぐる」**
https://www.umi-pon.jp/

```
$ chrome.exe --headless --disable-gpu --window-size=1024,768 --screenshot=C:\headless\pc.png https://www.umi-pon.jp/
```

Chromeをヘッドレスモードで実行するにはオプションに`--headless`をつけます。
`--window-size`オプションで画面サイズを指定して、`--screenshot`オプションでスクリーンショットを実行します。`--screenshot`のあとに`=`で保存先の指定をすることもできます。保存先をしていない場合はChromeがインストールされたフォルダに保存されます。
`--disable-gpu`はいくつかのバグを回避するためのオプションらしいです。そのうち不要になるそうで、今回も無くても問題なく実行されましたが、念の為に付けています。

こちらが保存されたスクリーンショットです。

![pc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533642/eda4a1f9-cba9-7b68-d1c6-3bd946f24833.png)

---

先程はPCサイズでのスクリーンショットだったので、次にスマホサイズで取ってみます。
`--window-size`オプションで画面サイズを変更するだけで出来ます。

```
$ chrome.exe --headless --disable-gpu --window-size=375,812 --screenshot=C:\headless\sp.png https://www.umi-pon.jp/
```

こちらが出力されたスマホサイズでのスクリーンショットです。

![sp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533642/f79cc4b7-f28b-975c-ec75-e8fdb884e829.png)

---

###PDFに出力してみよう
PDFで出力するには`--print-to-pdf`オプションを使います。
スクリーンショットと同じく`--print-to-pdf`に`=`をつけて保存先を指定することが出来ます。


```
$ chrome.exe --headless --disable-gpu --window-size=1024,768 --print-to-pdf=C:\headless\pc.pdf https://www.umi-pon.jp/
```
PDFが出力されました。

![pdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533642/99bee0bc-9f12-560c-f39d-edefb63ab731.png)

---

###DOM出力をしてみよう
DOM出力するには`--dump-dom`オプションを使います。
ダンプの出力先はコマンドの最後に`>`で指定します。


```
$ chrome.exe --headless --disable-gpu --dump-dom https://www.umi-pon.jp/ > C:\headless\output.html
```

HTMLファイルが出力されました。
![html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533642/0c6a39cf-f2c6-0ef6-dd7f-60338abdc451.png)



##WSLでもHeadless Chromeを使ってみよう！
実は今回の記事で本当に書きたかったことはここからです。
Windows10から利用可能になったWSL（Windows Subsystem for Linux）を使ってUbuntu上でHeadless Chromeを実行したいと思います。

###まずはWSLにChromeをインストール
では、まずはChromeのインストールから始めます。

その前に必要なライブラリをインストールします。
パッケージのインデックスを更新し、必要なライブラリをインストールします。

```
$ sudo apt-get update
$ sudo apt-get install libappindicator1 libappindicator3-1 fonts-liberation
```
次にChromeをインストールします。

```
$ curl -O https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
$ sudo dpkg -i google-chrome-stable_current_amd64.deb
```

これでChromeのインストール完了！
次にバージョンを確認します。

```
$ google-chrome --version
Google Chrome 79.0.3945.79
```

これでインストールは完了です！

---

###WSLでスクリーンショットを取ってみよう
では、次にスクリーンショットを取ってみます。

```
$ google-chrome --headless --no-sandbox --disable-gpu --screenshot --window-size=1024,768 https://www.umi-pon.jp/
[1213/203220.322276:WARNING:gpu_process_host.cc(1213)] The GPU process has crashed 1 time(s)
[1213/203220.889742:WARNING:gpu_process_host.cc(1213)] The GPU process has crashed 2 time(s)
[1213/203221.428961:WARNING:gpu_process_host.cc(1213)] The GPU process has crashed 3 time(s)
[1213/203221.898998:WARNING:gpu_process_host.cc(1213)] The GPU process has crashed 4 time(s)
[1213/203222.442822:WARNING:gpu_process_host.cc(1213)] The GPU process has crashed 5 time(s)
[1213/203222.909966:WARNING:gpu_process_host.cc(1213)] The GPU process has crashed 6 time(s)
[1213/203222.910073:FATAL:gpu_data_manager_impl_private.cc(990)] The display compositor is frequently crashing. Goodbye.
Failed to generate minidump.Illegal instruction (コアダンプ)
```
なにやらGPUがクラッシュしたようです。
原因が分からずググっていたのですが、どうやら最新版だとバグなどで利用できないことがあるとのこと。
そこでChromeをダウングレードします。

まずはChromeのアンインストール

```
$ sudo dpkg -r google-chrome-stable
```

下記サイトより古いバージョンのChromeをダウンロードします。
色々とバージョンを試しましたが`71.0.3578.80`が正常に動作しました。
https://www.slimjet.com/chrome/google-chrome-old-version.php

curlやwgetなどでダウンロードしインストールしてください。
そして改めてスクショを取るためにコマンドを実行します。

```
$ google-chrome --headless --no-sandbox --disable-gpu --screenshot --window-size=1024,768 https://www.umi-pon.jp/
[1218/132153.010010:ERROR:gpu_process_transport_factory.cc(967)] Lost UI shared context.
shared memfd open() failed: 関数は実装されていません
[1218/132159.029805:INFO:headless_shell.cc(546)] Written to file screenshot.png.
```

再びなにやらエラーがでますが、問題なく`screenshot.png`が出力されます。

![screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533642/3aa8a755-4e2a-7933-c386-89bdfdcd452f.png)

Windows10のときと同様にPDFやDOMも出力可能です。後ほどお試しください。


##最後に
今回はスクショやPDFを出力しましたが、node.jsなどと組み合わせることでスクレイピングや自動でテストを行うこともできます。
そちらも改めて記事として投稿しようと思います。


明日のプラコレアドベントカレンダーの担当はデザイン・コーディングができて、最近はPHPまでマスターした沖縄が誇るハイブリッドなクリエイター**横田さん**です。
ちょっと天然なみゆきワールドをぜひご堪能ください！

プラコレではエンジニア、デザイナーも幅広く募集しています！！
[プラコレ](https://pla-cole.co/)は[プラコレWedding](https://pla-cole.wedding/)以外にもウェディングのメディア[Dressy](https://dressy.pla-cole.wedding/)や[farny](https://www.farny.jp/)なども運営しています。ぜひ見ていってもらえると嬉しいです！