Selenium+ヘッドレスブラウザ(Chrome)によるスクリーンショットの自動取得
テスト自動化
最近流行のテスト自動化について調べていたら、昔少し名前を聞いた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
$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
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
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
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
> 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のカレントディレクトリからの相対パスで
COPY ../src/test.py /test.py
のように定義したのですが、相対パス先のファイルが参照できず、仕方なくdockerfileと同じディレクトリにtest.pyを配置し、以下のように定義したところきれいに動いてくれました。
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の私の質問
Author And Source
この問題について(Selenium+ヘッドレスブラウザ(Chrome)によるスクリーンショットの自動取得), 我々は、より多くの情報をここで見つけました https://qiita.com/daichannel/items/d7667b83b96d726cb650著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .