Goalist Developers Blog

EC2でChromeヘッドレスを動かす

AWSのEC2でChromeをヘッドレスモードで動かしてクローリングしたい!
そこに至るまでにはいくつかの壁があります。

  • Amazon Linuxでは上手くいかない
  • Chromeだけでなく、日本語フォントが必要
  • ChromeとChromeDriverの対応バージョンを合わせる必要がある

この辺を乗り越えたときのメモを残しておこう思います。最後におまけとして「ページのロードが終わらないでタイムアウトする」というSelenium WebDriverあるあるを解決する方法も載せておきます。

環境

  • EC2(OS:Ubuntu)
  • Selenium WebDriver for Java 2.53.0

手順

とりあえずUbuntuでEC2インスタンスを立てる

今回はインスタンス作成ボタンを押したときに出てくる一覧から以下を選択。
Ubuntu Server 16.04 LTS (HVM), SSD Volume Type

Chromeをインストール

/home/ubuntu/chrome-setup を作成し、以降の作業はそこで行います。

mkdir /home/ubuntu/chrome-setup
cd /home/ubuntu/chrome-setup

Chromeはdebパッケージをダウンロードしてインストールします。
ただし、以下のように最新版をインストールするとChromeDriverが対応するバージョンを超える場合があります。

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

ChromeとChromeDriverのバージョンの対応はChromeDriverの ダウンロードページで確認できます。 今回は61が欲しかったのでslimjetのサイトから落としました。
ブラウザから落とす場合は以下のURLで落とせます。
https://www.slimjet.com/chrome/google-chrome-old-version.php
クローラ云々は別として、Google公式ではChromeの最新バージョンしかダウンロードできないので有用なサイトです。
wgetでdebパッケージを落とす場合は以下です。

wget https://www.slimjet.com/chrome/download-chrome.php?file=lnx%2Fchrome64_61.0.3163.79.deb

ダウンロードしたので、インストール 。

sudo dpkg -i download-chrome.php?file=lnx%2Fchrome64_61.0.3163.79.deb

なんかめっちゃエラーでて怒られるので、 依存モジュールをaptでインストール。

sudo apt update
sudo apt -f install -y

インストール確認。

which google-chrome

こんな感じで表示されれば多分OK→ /usr/bin/google-chrome

日本語フォントをインストール

このままだと日本語がお豆腐になってしまうので、今回はIPAフォントをインストールします。
まずはunzipをインストール。

sudo apt install unzip

IPAフォントをダウンロードしてunzipしてfontに置く。

wget --content-disposition IPAfont00303.zip http://ipafont.ipa.go.jp/old/ipafont/IPAfont00303.php

sudo unzip IPAfont00303.zip -d /usr/share/fonts/

フォントキャッシュクリア

sudo fc-cache -fv

おまけ

以上でEC2上でChromeをヘッドレスモードで動かす準備はできたわけですが、Javaのコード上で実際にヘッドレスを指定する方法を載せておきます。
ついでにページロードが終わらなくてタイムアウトする問題にはpageLoadStrategyというパラメータが有効です。Chromeでは指定しない場合はnormalが指定されていますが、noneを指定すればタイムアウトは回避できます。
ただし、noneの場合はきちんと対象の要素を待つようなロジックにしないと思った通りの動作にならない場合があります。
また、pageLoadStrategyに指定できるのはnormal eager noneの3種類ですが、eagerはChromeでは認識されませんでした。

private static WebDriver getChromeDriver() {     
    System.setProperty("webdriver.chrome.driver", "path to your chromedriver");
    
    ChromeOptions chromeOptions = new ChromeOptions();
    chromeOptions.addArguments("--headless", "window-size=1280,1024"); // xvfbとか一切無しでdislayサイズも指定できちゃう
    
    DesiredCapabilities capabilities = DesiredCapabilities.chrome();
    capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
    capabilities.setCapability("pageLoadStrategy", "none"); // normal eager none
    return new ChromeDriver(capabilities);
}