Ubuntu Weekly Recipe

第662回Docker+Selenium ServerでWebブラウザ自動操作環境を作る

今回は、Selenium ServerによるWebブラウザ自動操作環境を、Ubuntu上にDockerを使って簡単に構築する方法を紹介します。

Webブラウザの自動操作を可能にするSelenium

Seleniumは、Webアプリケーションのテストを、人が操作することなく自動で行うために開発されているソフトウェアです。本来は「テストの自動化」のために開発されたソフトなのですが、Webブラウザを用いて行っている業務の自動化や、Webサイトの情報を自動収集するスクレイピングなどにも使われています。

今回、主に紹介するのは「Selenium Server」を使う方法ですが、他に「Selenium IDE」というFirefoxおよびGoogle Chrome用の拡張機能も開発・配布されています。Selenium IDEを使えば、デスクトップ環境でWebブラウザの操作を記録し、簡単に再実行させることができます。記録内容をカスタマイズしたり、一から操作コマンドを書くこともできます。

一方、⁠Selenium WebDriver」というAPIを使えば、Python・Ruby・C#・Javaなどで書いたプログラムからWebブラウザを操作したり、内容を取得したり、スクリーンショットを撮ったりできます。プログラムから操作するのでSelenium IDEよりもはるかに高機能な自動化が可能です。

さらに、本記事で紹介するSelenium Serverを動かせば、リモートで動作するブラウザを操作することも可能です。決まった時間にスクリプトを実行し、Webブラウザを自動操作するなら、サーバー環境にSelenium Serverを導入しておくと便利です。たとえば、社員が社内システムにアクセスして時間をかけて行っている処理を自動化できるようになります。

Selenium Serverのセットアップ手順は複雑ですが、公式のDockerイメージを使えば簡単に導入できます。DockerイメージはUbuntuベースとなっているため、日本語フォントを入れるなどのカスタマイズも簡単です。

なお、VNCによるリモートデスクトップ接続により、Dockerコンテナ内で動作するWebブラウザが自動で動く様子を見ながら、操作するスクリプトのデバッグができます。Ubuntuデスクトップなら、前回の記事で紹介したリモートデスクトップクライアント「Remmina」がVNCに対応しています。もちろん、Windowsなど別のOSにVNCクライアントを入れ、Selenium Serverが動作しているDockerコンテナに接続することも可能です。

Dockerのインストール

UbuntuのレポジトリでもDockerのパッケージが提供されていますが、最新版がDockerのレポジトリからインストールできます。

インストールは、公式のドキュメントに記述されているとおり、以下のコマンドで行うことができます。

$ sudo apt-get update
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

また、本記事ではdocker-composeコマンドを使った構築方法を紹介します。以下のコマンドを実行すれば、最新のdocker-composeコマンドが/usr/local/binにインストールされます。

$ COMPOSE_VERSION=$(git ls-remote https://github.com/docker/compose | grep refs/tags | grep -oE "[0-9]+\.[0-9][0-9]+\.[0-9]+$" | sort --version-sort | tail -n 1)
$ curl -L https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` | sudo tee /usr/local/bin/docker-compose > /dev/null
$ sudo chmod +x /usr/local/bin/docker-compose

なお、現在ログインしているユーザーで、sudoを使わずdockerコマンドを実行したい場合は、以下のコマンドを実行してdockerグループに追加し、再起動してログインしなおします。

$ sudo gpasswd -a $USER docker

Selenium公式のDockerイメージを選ぶ

Seleniumの公式Dockerイメージは、Docker Hubで配布されています。2021年4月時点の最新安定版であるdocker-selenium 3のGitHubレポジトリを見ると、以下のイメージが開発・配布されているのが分かります。

Baseイメージ
  • selenium/base:JavaランタイムとSeleniumサーバーのJARファイルが含まれるベースイメージ
Standaloneイメージ
  • selenium/standalone-chrome:ChromeがインストールされたStandaloneイメージ
  • selenium/standalone-firefox:FirefoxがインストールされたStandaloneイメージ
  • selenium/standalone-opera:OperaがインストールされたStandaloneイメージ
  • selenium/standalone-chrome-debug:ChromeとVNCサーバーがインストールされたStandaloneイメージ
  • selenium/standalone-firefox-debug:FirefoxとVNCサーバーがインストールされたStandaloneイメージ
  • selenium/standalone-opera-debug:OperaとVNCサーバーがインストールされたStandaloneイメージ
Grid Hubイメージ
  • selenium/hub: Grid Hubが動くイメージ
Grid Nodeイメージ
  • selenium/node-base:Nodeのベースイメージ
  • selenium/node-chrome:ChromeがインストールされたNodeイメージ
  • selenium/node-firefox:FirefoxがインストールされたNodeイメージ
  • selenium/node-opera:OperaがインストールされたNodeイメージ
  • selenium/node-chrome-debug:ChromeとVNCサーバーがインストールされたNodeイメージ
  • selenium/node-firefox-debug:FirefoxとVNCサーバーがインストールされたNodeイメージ
  • selenium/node-opera-debug:OperaとVNCサーバーがインストールされたNodeイメージ

多くのイメージがありますが、WebブラウザとSelenium Serverが一緒に入っているStandaloneイメージひとつで、ブラウザの自動操作は可能です。本記事では、ChromeとVNCサーバーがインストールされた「standalone-chrome-debug」イメージを利用します。

なお、⁠Grid Hub」「Grid Node」のイメージは、さまざまなブラウザで並行して自動テストを行う「Selenium Grid」を構築する場合に用います。

図1 Selenium Gridの構成図(Seleniumのドキュメントより)
図1

Dockerコンテナで動くのはUbuntu版の各種Webブラウザですが、Windows PCやMacを用意してGrid Nodeをインストールし、複数のOSで動く各種ブラウザ上で並行して動作テストを行うことも可能です。

docker-composeでStandaloneイメージのコンテナを実行する

Seleniumの公式Dockerイメージのままでも自動操作はできるのですが、デバッグ時に日本語を正しく表示するため、日本語フォントなどを追加したイメージにカスタマイズしましょう。そのために、docker-compose.ymlを配置するディレクトリにサブディレクトリ(本記事の例では「custom⁠⁠)を作成し、以下の内容でDockerfileを作成します。

FROM selenium/standalone-chrome-debug:3

USER root
RUN apt-get update \
 && apt-get install -y -q --no-install-recommends \
    fonts-noto-cjk fonts-noto-cjk-extra language-selector-common language-pack-ja \
 && update-locale LANG=ja_JP.UTF-8 \
 && apt-get clean \
 && rm -r /var/lib/apt/lists/*

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8

USER 1200

RUN x11vnc -storepasswd password ${HOME}/.vnc/passwd

最後の行の「password」はVNC接続時のパスワードなので、任意のものに変更してください。

そして、以下の内容でdocker-compose.ymlを作成します。

version: "3"

services:
  chrome:
    build: custom
    restart: unless-stopped
    ports:
      - 4444:4444
      - 15900:5900
    volumes:
      - /dev/shm:/dev/shm
      - /etc/localtime:/etc/localtime:ro
    environment:
      - SCREEN_WIDTH=1600
      - SCREEN_HEIGHT=900

プログラムからSelenium Serverに接続するポート番号は、デフォルトの4444のままとしています。VNCで接続するポートは、ホストでVNCサーバーが5900番ポートで動作している場合にバッティングしないよう、15900にマッピングしています。

SCREEN_WIDTHとSCREEN_HEIGHTは、接続元となるPCの解像度に合わせて調整してください。

これで、以下のコマンドを実行すると、イメージのダウンロード、ビルドが実行された後、Chromeを自動操作できるコンテナが起動します。

$ docker-compose up -d

PythonからWebブラウザを操作する

起動したDockerコンテナでは、仮想ディスプレイとVNCサーバーが動いています。RemminaなどのVNCクライアントから接続してみましょう。LAN上の別のPCから接続することもできます。ただし、ポート番号はdocker-compose.ymlで設定したものを指定する必要があります。今回の例では15900に設定したので、ローカルPCから接続するなら接続先は「127.0.0.1:15900⁠⁠、LAN上の別PCから接続するなら「DockerホストのIPアドレス:15900」となります。

プログラムからDocker Serverを介してブラウザを操作するには、言語ごとにSelenium WebDriverバインディングをインストールする必要があります。たとえば、UbuntuでPython 3を用いる場合、以下のようにpip3コマンドをインストールし、pip3コマンドで最新安定版のSelenium WebDriverバインディングをインストールします。

$ sudo apt install python3-pip
$ pip3 install selenium

これで、PythonスクリプトからSelenium Serverを介してWebブラウザを操作する準備が整いました。以下は「https://gihyo.jp」を開き、検索窓に「Ubuntu」を入力して検索を行い、ヒットした記事のタイトルを出力するスクリプトです。

#!/usr/bin/python3

from selenium import webdriver
import time

# Chromeのオプション
options = webdriver.ChromeOptions()
options.add_argument("--start-maximized")

# Selenium Serverに接続
driver = webdriver.Remote(command_executor='http://localhost:4444/wd/hub',
options=options)

try:
  # 要素の待機時間を最大10秒に設定
  driver.implicitly_wait(10)

  # https://gihyo.jp を開く
  driver.get('https://gihyo.jp')

  # 検索ボックスに「Ubuntu」を入力
  element_search_form = driver.find_element_by_id('searchFormKeyword')
  element_search_form.send_keys('Ubuntu')

  # 検索ボタンをクリック
  element_search_button = driver.find_element_by_id('searchFormSubmit')
  element_search_button.click()
  time.sleep(5)

  # 検索結果のタイトルを取得して出力
  element_titles = driver.find_elements_by_xpath("//a[@class='gs-title']")
  for element_title in element_titles:
    if not element_title.text.strip():
      continue
    print(element_title.text.strip())

except:
  import traceback
  traceback.print_exc()

finally:
  # Chromeを終了
  input("何かキーを押すと終了します...")
  driver.quit()

実行すると、VNCクライアントでChromeが開き、自動操作される様子を見ることができます。VNCで接続していなくても、処理は同じように行われます。

図2 VNCクライアントでSeleniumで自動操作されるChromeを確認できる
図2

このように、自作プログラムを使ってDockerコンテナ内で動くWebブラウザを操作し、内容を取得できました。プログラムをうまく書けば、複雑な処理も自在に行わせることができます。ただし、外部のWebサイトに過剰な負荷をかけたり、プログラムによるアクセスを禁止しているサイトを開いて自動操作したりしないよう、注意が必要です。

Seleniumの詳しい使い方、プログラムの書き方については、Seleniumのドキュメントや各言語のAPIリファレンスを参照してください。

おすすめ記事

記事・ニュース一覧