CentOS7でPuppeteerを使う

JavaScriptでDOM操作をして要素を出力しているページに対してスクレイピングを行うために[Puppeteer](https://github.com/GoogleChrome/puppeteer#puppeteer)が必要になりそうでしたのでさわりだけ試しました。

# とりあえず動かしてみたい

とりあえずREADME.mdの最初のスクリーンショットをとる[サンプル](https://github.com/GoogleChrome/puppeteer#usage)を`https://qiita.com/`のページ全体を対象として動作させてみることにしました。

```js:example.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://qiita.com/');
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();
```

`node example.js`を実行してみる

```:エラー
node_modules/puppeteer/.local-chromium/linux-588429/chrome-linux/chrome: error while loading shared libraries: libXcomposite.so.1: cannot open shared object file: No such file or directory


TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md
```

[Troubleshooting](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#troubleshooting)を確認してみると
CentOS Dependenciesという項目があったので[Check out discussions](https://github.com/GoogleChrome/puppeteer/issues/391)を確認してみたところ
[From a minimal CentOS 7 setup](https://github.com/GoogleChrome/puppeteer/issues/391#issuecomment-398660894)とあったので以下を実行

```
yum -y install libX11 libXcomposite libXcursor libXdamage libXext libXi libXtst cups-libs libXScrnSaver libXrandr alsa-lib pango atk at-spi2-atk gtk3
```

再度`node example.js`を実行してみる

```:エラー
ERROR:zygote_host_impl_linux.cc(89)] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.


TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md
```

[Troubleshooting](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#troubleshooting)を確認してみると
[Chrome Headless fails due to sandbox issues](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md#chrome-headless-fails-due-to-sandbox-issues)という項目があったので

```diff
- const browser = await puppeteer.launch();
+ const browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']});
```

に修正して再度`node example.js`を実行

とりあえず無事に以下のスクリーンショットが取れました。

![example1.png](https://qiita-image-store.s3.amazonaws.com/0/156195/c30e5e36-62b2-e4ca-2a35-231ca057ca6c.png)


## [念のため読み込みが無くなってからスクリーンショットしたい](https://github.com/GoogleChrome/puppeteer/blob/v1.8.0/docs/api.md#pagegotourl-options)

```diff
- await page.goto('https://qiita.com/');
+ await page.goto('https://qiita.com/', {waitUntil : 'networkidle0'});
```

`waitUntil : 'networkidle0'`
だと戻ってこないページがあったので
`waitUntil: 'domcontentloaded'`
の後に
`page.waitFor(milliseconds)`
で待機する方法が無難そうです。

それでも返ってこない場合は順番に試してく方法がよさそうです。
[こちら](https://qiita.com/horikeso/items/631e2a8d0d17320d9f4f)で使用しているように以下の様なオプションリストを作ったりして。

>
```js
optionList = [
    {waitUntil: 'load'},
    {waitUntil: 'domcontentloaded'},
    {waitUntil: 'networkidle0'},
    {waitUntil: 'networkidle2'}
];
```

## [文字化けを直したい](https://github.com/GoogleChrome/puppeteer/issues/391#issuecomment-324551649)

```
yum -y install ipa-gothic-fonts xorg-x11-fonts-100dpi xorg-x11-fonts-75dpi xorg-x11-utils xorg-x11-fonts-cyrillic xorg-x11-fonts-Type1 xorg-x11-fonts-misc
```

## [スクリーンショットの幅を広げたい](https://github.com/GoogleChrome/puppeteer/blob/v1.8.0/docs/api.md#pagesetviewportviewport)

```diff
+ await page.setViewport({width: 1280, height: 720});
(widthのみの指定ではエラーになりました。)
```

## [全ページにしたい](https://github.com/GoogleChrome/puppeteer/blob/v1.8.0/docs/api.md#pagescreenshotoptions)

```diff
- await page.screenshot({path: 'example.png'});
+ await page.screenshot({path: 'example.png', fullPage: true});
```

修正して再度`node example.js`を実行

![example2.png](https://qiita-image-store.s3.amazonaws.com/0/156195/fe369865-dd15-ea11-8e40-0494c6de77de.png)

## 英語になっているので言語設定やユーザーエージェントを設定したい

### 言語設定

[How to specify browser language in Puppeteer
](https://stackoverflow.com/questions/46908636/how-to-specify-browser-language-in-puppeteer#answer-47292022)

これによると
[browserのオプション](https://peter.sh/experiments/chromium-command-line-switches/#lang)で設定する方法
[pageのメソッド](https://github.com/GoogleChrome/puppeteer/blob/v1.8.0/docs/api.md#pagesetextrahttpheadersheaders)で設定する方法
がある様子。

今回はbrowserのオプションで設定してみます。

```diff
+ '--lang=ja,en-US;q=0.9,en;q=0.8',
```

### ユーザーエージェント設定

[browserのオプション](https://peter.sh/experiments/chromium-command-line-switches/#user-agent)で設定する方法
[browserのメソッド](https://github.com/GoogleChrome/puppeteer/blob/v1.8.0/docs/api.md#browseruseragent)で設定する方法
[pageのメソッド](https://github.com/GoogleChrome/puppeteer/blob/v1.8.0/docs/api.md#pagesetuseragentuseragent)で設定する方法
[pageのemulateのオプション](https://github.com/GoogleChrome/puppeteer/blob/v1.8.0/docs/api.md#pageemulateoptions)で設定する方法
がある様子。

今回はbrowserのオプションで設定してみます。

```diff
+ '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
```

修正して再度`node example.js`を実行

```js:example.js
const puppeteer = require('puppeteer');

(async () => {
  try {
    const browser = await puppeteer.launch({
      args: [
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--lang=ja,en-US;q=0.9,en;q=0.8',
        '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
      ]
    });
    const page = await browser.newPage();
    await page.goto('https://qiita.com/', {waitUntil : 'domcontentloaded'});
    await page.waitFor(2000);
    await page.setViewport({width: 1280, height: 720});
    await page.screenshot({path: 'example.png', fullPage: true});
    
    await page.close();
    await browser.close();
  } catch (error) {
    throw error;
  }
})().catch((error) => {
  console.log(error);
  process.exit(1);
});
```

![example3.png](https://qiita-image-store.s3.amazonaws.com/0/156195/6e1ff6f3-b9d3-e68b-b556-b669259ec866.png)