3
7

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

Selenium+ヘッドレスブラウザ(Chrome)によるスクリーンショットの自動取得

Posted at

テスト自動化

最近流行のテスト自動化について調べていたら、昔少し名前を聞いたSeleniumがかなり使われており、Docker環境での分散試験や、ヘッドレスブラウザでの高速化など、いろいろな技術を使っていることを知りました。

せっかくDocker環境を構築できるようになってきたので、自分でもすごさを体感したいと思い環境を作ってみましたが、Vagrant+Docker-composeで環境構築の自動化までやろうとしたら、いろいろ躓いた(まだ躓いたまま…)のでメモ書きとしてこの記事を書きます。

ヘッドレスブラウザ

「ヘッドレスブラウザ」で検索すれば、いろいろ説明が出てきますが、簡単に言うと画面表示をしないことで、オーバーヘッドをなくした(レス)ブラウザです。

作成するもの

Pythonのコードから、Selenium+ヘッドレスブラウザを呼び出し、画面のスクリーンショットを取って終了するような環境を作成します。

Vagrant上にVirtualBoxでCentOS環境を構築し、そこにDockerを乗っけて、UbuntuコンテナにSelenium+ヘッドレスブラウザをインストールしてスクリーンショットを取得するイメージです。

フォルダ構成

フォルダ構成は以下の通りです。

  +-- docker
  |     +-- selenium
  |     |     +-- chromedriver_linux64.zip(※後述)
  |     |     +-- Dockerfile
  |     |     +-- test.py(スクリーンショット取得プログラムソース)
  |     |
  |     +-- docker-compose.yaml
  |
  +-- image
  |     +-- (取得したスクリーンショットが保存されるディレクトリ)
  |
  +-- Vagrantfile

※docker/selenium/chromedriver_linux64.zip は、ダウンロードするChromeのバージョンに併せてダウンロードするドライバを変更します。
 しかし、Chrome最新版のダウンロードURLしか分からず、2019/09/29 時点の最新バージョンが 77.0.3865.90 である為、それに一番近い以下のURLのバージョンを予めダウンロードしています。(過去のバージョンをダウンロードする方法が分かるかた教えてください!)
https://chromedriver.storage.googleapis.com/77.0.3865.40/chromedriver_linux64.zip

 以下にchromedriverのバージョン一覧があります。
 http://chromedriver.storage.googleapis.com/

 恐らく、77.0.3865 まであわせれば大丈夫です。

Vagrantfile

vagrantfile
$vm_name = "selenium-test"
$vm_memory_mb = 2048
$vm_cpus = 2
$docker_compose_version = "1.21.2"
$chrome_version = "77.0.3865.40"

Vagrant.configure("2") do |config|

  # ----- Vitual machine name -----
  config.vm.define $vm_name

  # ----- Virtual machine spec -----
  config.vm.provider :virtualbox do |v|
    v.name = $vm_name
    v.memory = $vm_memory_mb
    v.cpus = $vm_cpus
  end

  # ----- Synced folder -----
  #  ホスト側のフォルダとゲストOSのフォルダを同期する設定。
  config.vm.synced_folder "./", "/vagrant"

  # ----- OS -----
  config.vm.box = "centos/7"
  
  # ----- Provisioning (初回の一回だけ実行する) -----
  config.vm.provision :shell, inline: <<-SHELL
    # Dockerインストール
    sudo yum install -y yum-utils device-mapper-persistent-data lvm2
    sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    sudo yum makecache fast
    sudo yum -y install docker-ce

    # Dockerデーモン自動起動設定
    sudo systemctl enable docker.service

    # Dockerデーモン開始
    sudo systemctl start docker

    # wget インストール
    sudo yum -y install wget

    # docker-compose をインストール
    sudo wget -L --no-verbose https://github.com/docker/compose/releases/download/#{$docker_compose_version}/docker-compose-`uname -s`-`uname -m`
    sudo chmod +x docker-compose-`uname -s`-`uname -m`
    sudo mv docker-compose-`uname -s`-`uname -m` /usr/local/bin/docker-compose
    sudo chown root:root /usr/local/bin/docker-compose

    # 環境変数(chromeのバージョン)
    export CHROME_VERSION=$chrome_version

    # Dockerイメージのビルド
    sudo /usr/local/bin/docker-compose -f /vagrant/docker/docker-compose.yaml build
  SHELL

  # ----- Provisioning (常に実行) -----
  config.vm.provision :shell, run: "always", inline: <<-SHELL
    # dockerコンテナ群を起動する
    sudo /usr/local/bin/docker-compose -f /vagrant/docker/docker-compose.yaml up -d
  SHELL
end

docker-compose.yaml

docker-compose.yaml
version: '3.5'

services:

  selenium:
    container_name: selenium-test-container
    image: selenium-test-image
    build: ./selenium
    volumes:
      - ../image:/tmp
    command: python3 test.py

Dockerfile

Dockerfile
FROM ubuntu:16.04

# default derectory
WORKDIR /

# wgetやunzipをインストール
RUN apt-get update && \
    apt-get -y upgrade && \
    apt-get -y install iputils-ping net-tools wget unzip

# Googleの公開鍵再取得
RUN wget -q https://dl.google.com/linux/linux_signing_key.pub
RUN apt-key add linux_signing_key.pub

# chromedriver のインストール
COPY chromedriver_linux64.zip /chromedriver_linux64.zip
RUN unzip chromedriver_linux64.zip
RUN mv chromedriver /usr/bin/
RUN chmod +x /usr/bin/chromedriver

# chrome のインストール準備
RUN apt-get -y install fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 libcairo2 libcups2 libdbus-1-3 
RUN apt-get -y install libnspr4 libnss3 libxss1 lsb-release xdg-utils

# chrome のインストール
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN dpkg -i google-chrome-stable_current_amd64.deb

# selenium のインストール
RUN apt-get -y install python3-pip && \
    apt-get -y install python3-selenium

# 日本語フォントのインストール
RUN wget --content-disposition IPAfont00303.zip http://ipafont.ipa.go.jp/old/ipafont/IPAfont00303.php  || RET=$? || true && \
    unzip IPAfont00303.zip -d /usr/share/fonts/ && \
    fc-cache -fv

# 不要ファイルの削除
RUN rm -f chromedriver_linux64.zip google-chrome-stable_current_amd64.deb

# スクリーンショット取得プログラムの配置
COPY test.py /test.py

test.py

test.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time

options = Options()
options.binary_location = '/usr/bin/google-chrome-stable'
options.add_argument('--headless')
options.add_argument('--no-sandbox')

driver = webdriver.Chrome('chromedriver', chrome_options=options)
# URLのデータを取得
driver.get('https://qiita.com/daichannel/items/08e074a01e8ab41d52f7')
# ここでウィンドウサイズ設定
page_width = driver.execute_script('return document.body.scrollWidth')
page_height = driver.execute_script('return document.body.scrollHeight')
driver.set_window_size(page_width, page_height)

print(driver)
driver.save_screenshot('/tmp/screenshot.png')
driver.quit()

実行

> vagrant up

これ一発でimageフォルダ配下に、screenshot.pngファイルが出来ているはずです。

はまったところ

今回、こちらを参考にさせて頂き、環境を作っていきました。
最初からdocker-composeで自動化したわけではなく、最初は一個一個コマンド打って動作を確認しながら実施しました。その際は、特に躓くこともなくすんなり環境構築できたのですが、docker-composeで自動化して記事にしようとしたところ、かなりいろんなところではまりました。

1:ubuntu 18.04 だとダメ

Teratailでもまだ質問中ですが、上記ではubuntu 16.04で環境構築していますが、当初は18.04で環境構築していました。
ですが、そうするとwgetのインストールや、python3-pipのインストールでエラーが発生して、進めなくなってしまいました。
16.04に変更してみて再度試したところエラーなくインストールできました。
原因が未だ不明なままです。。。

2:chromedriverのバージョン

chromedriverは、Chrome向けのWebDriver(Webブラウザを外部から操作する機能)です。その為、Chromeとバージョンを合わせる必要があるのですが、通常最新版しかダウンロードできず、Dockerfileの中で動的にダウンロードライブラリのバージョンを変えることが出来ません。
その為、今回はバージョンを固定し、vagrantfileの中で環境変数を設定してDockerfileまで受け渡していこうと考えましたが、docker-compose.yamlで利用する環境変数は、実行時(docker-compose up)のときに設定されるもので、ビルド(docker-compose build)時には適用されないことが分かり、諦めてバージョン番号をdockerfileに書くようにしました。。。

3:Googleの公開鍵取得

Chromeをインストールを試みたタイミングでエラーとなりました。
調査したところ、GoogleのリポジトリのGPG公開鍵をインポートする必要があることが分かりました。

4:スクリーンショットの最大化ファイルの取得

Pythonで作成したスクリーンショットの自動取得処理ですが、URLによってエラーになることがありました。
調査したところ、あまり大きい画像になる場合、メモリ不足で落ちているようです。
今回は回避方法まで調べ切れませんでした。

5:chromeのインストール

参考にしたサイトでは、簡単にchromeをインストールしていましたが、関連ライブラリが多く、それらを全てインストールしないとエラーが消えませんでした。
その為、上記のdockerfileではchromeインストール前の準備処理があります。

6:Dockerコンテナへのファイル受け渡し

dockerホスト(CentOS)からdockerゲスト(Ubuntu)へのファイル受け渡しを、当初はdocker-compose.yamlのVOLUMESパラメータによるディレクトリのマウントで行おうと考えました。
しかし、これはdocker-compose実行時にしかマウントされない為、dockerfileのCOPYコマンドで対応することにしました。
この際、dockerfileのカレントディレクトリからの相対パスで

dockerfile
COPY ../src/test.py /test.py

のように定義したのですが、相対パス先のファイルが参照できず、仕方なくdockerfileと同じディレクトリにtest.pyを配置し、以下のように定義したところきれいに動いてくれました。

dockerfile
COPY test.py /test.py

マニュアルを読めば分かることかもしれませんが、変なところではまってしまいました。

7:Proxy

proxy、これが面倒な問題です。
私の利用しているネットワーク環境がProxy環境下である為、Vagrantやdocker-composeに軒並みProxyの設定をしてやらないとVMのダウンロードもままなりません。
Vagrantの vagrant-proxyconf という便利なpluginがあるので、これを使ってこの問題を回避しました。

Proxyとは関係ないですが、会社のインターネット接続制限でGitHubに接続できない問題もあって、chromedriverができなかったりと地味に面倒な環境の中で構築作業を進めた為、ちゃんとスクリーンショットが取れたときは、感動しました。

URL

参考にさせて頂いたサイト

https://qiita.com/xio_yae/items/72c398e9db3ffe7b3136
https://blog.geeko.jp/ftake/2138
https://blog.amedama.jp/entry/2018/07/28/003342

Teratailの私の質問

apt-get install python3-pip にてインストールに失敗する

3
7
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
3
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?