You are currently viewing ConoHa上のDockerでSelenium ~とにかく動かしたい人向け~

前の記事でConoHaというVPSにDockerとdocker-composeの環境を構築しました。なぜ構築したかというと…Seleniumを動かしたかったからです。正直なところ別にDocker上で動かす必要は無いのですが、一度、Docker環境で動かせるようになっておけば、他環境にも入れやすくなるのでやってみました。

というわけで今回は、ConoHa上のDockerでサクッとSeleniumを動かすことによって、ちょっとした自動操作をやってみたいと思います。GUIがない環境でも動くようにヘッドレス、ChromeとFirefoxで動かすのを目標にやっていきます。

Selenium?

SeleniumはWebアプリケーションのテスト用に開発されているフレームワークです。テスト用ではありますが、自動でWebページを操作できるというのは色々夢が広がります。動作テスト、情報の収集、タスクの自動化など…。Seleniumを動かせる言語は色々とありますが、今回はPythonでやっていきたいと思います。

Dockerfile! docker-compose.yml!

さて、今回はサクッとが目標なので、本題に入ります。まずはdocker-compose.ymlです。これだけあればほぼほぼ構築が完了するんですからDocker…コンテナの技術ってネ申ですね。

version: '3'

services:
  selenium-hub:
    image: selenium/hub
    container_name: 'selenium-hub'
    ports:
      - 4444:4444
    environment:
      - GRID_TIMEOUT=300
    restart: always

  chrome:
    image: selenium/node-chrome-debug
    container_name: 'chrome'
    links:
      - selenium-hub:hub
    ports:
      - 5900:5900
    environment:
      - NODE_MAX_INSTANCES=5
      - NODE_MAX_SESSION=5
      - no_proxy=localhost
      - HUB_ENV_no_proxy=localhost
      - HUB_PORT_4444_TCP_ADDR=selenium-hub
      - HUB_PORT_4444_TCP_PORT=4444
      - SCREEN_WIDTH=1440
      - SCREEN_HEIGHT=900
    volumes:
      - /dev/shm:/dev/shm
    restart: always

  firefox:
    image: selenium/node-firefox-debug
    container_name: 'firefox'
    links:
      - selenium-hub:hub
    ports:
      - 5901:5901
    environment:
      - NODE_MAX_INSTANCES=5
      - NODE_MAX_SESSION=5
      - no_proxy=localhost
      - HUB_ENV_no_proxy=localhost
      - HUB_PORT_4444_TCP_ADDR=selenium-hub
      - HUB_PORT_4444_TCP_PORT=4444
      - SCREEN_WIDTH=1440
      - SCREEN_HEIGHT=900
    volumes:
      - /dev/shm:/dev/shm
    restart: always

  python:
    build: './python-selenium'
    container_name: 'python'
    links:
      - selenium-hub:hub
    working_dir: '/root/script/'
    volumes:
      - ./script/:/root/script/
    environment:
      - 'TZ=Asia/Tokyo'
    tty: true
    restart: always

これをdocker-compose.ymlに記述します。これだけでSeleniumとChrome,Firefoxの作業環境が構築されます。端末自体にChromeやFirefoxをインストールする必要すらありません。ちなみに各コンテナは上から「SeleniumGrid」「Chrome」「Firefox」「Python実行環境」の機能を提供してくれます。そのため、Python以外の言語で動かしたければ、4つ目のコンテナを変えてもらうだけで動いてくれると思います。

あとはいい感じにPython環境を構築してもらうようにDockerfileを書いていきます。ここでの「いい感じ」とは使用するライブラリ類をインストールしてくれるというだけです。

FROM python:3

# seleniumをインストール
RUN apt-get update

COPY ./requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
selenium

はい。これだけです。ここでやっていることはPython側から呼び出すためにSeleniumのライブラリを入れているだけになります。インストールのためにrequirements.txtを用意します。もし他にもインストールしておきたいライブラリなどがあれば、このテキストファイルに1行に1つずつ書いていくだけでビルド時にインストールしてくれます。

ファイル構成

以上の準備が終わると以下のようになります。(sample.pyはこれから書きます!)

.
├── docker-compose.yml
├── python-selenium
│   ├── Dockerfile
│   └── requirements.txt
└── script
    └── sample.py

Python!

さて環境は整ったので、次はコードを書いていきます。今回はよくあるテストということで、おなじみGoogleさんで自動検索をしてみようと思います。…それだけではつまんないので、スクリーンショットも撮ってみます。

#!/usr/local/bin/python3
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def execSearch(browser: webdriver, img_name: str):
    """
    Googleで検索する
    :param browser: webdriver
    """
    # Googleにアクセス
    browser.get('https://www.google.co.jp/')
    WebDriverWait(browser, 15).until(EC.presence_of_all_elements_located)

    # キーワードの入力
    search_box = browser.find_element_by_name("q")
    search_box.send_keys('hello selenium')

    # 検索実行
    search_box.submit()
    WebDriverWait(browser, 15).until(EC.presence_of_all_elements_located)

    # スクリーンショット
    browser.save_screenshot(img_name + '.png')

if __name__ == '__main__':
    try:
        # UA を設定
        capabilities = webdriver.common.desired_capabilities.DesiredCapabilities.CHROME.copy()
        capabilities['javascriptEnabled'] = True

        options = webdriver.ChromeOptions()
        options.add_argument('--user-agent="Mozilla/5.0 (Linux; Android 4.0.3; SC-02C Build/IML74K) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.58 Mobile Safari/537.31"')

        # HEADLESSブラウザに接続
        browser = webdriver.Remote(
            command_executor='http://selenium-hub:4444/wd/hub',
            desired_capabilities=DesiredCapabilities.CHROME,
            options=options
        )

        browser2 = webdriver.Remote(
            command_executor='http://selenium-hub:4444/wd/hub',
            desired_capabilities=DesiredCapabilities.FIREFOX
        )

        # FBで実行
        execSearch(browser,  img_name='chrome')
        execSearch(browser2, img_name='firefox')

        browser.close()
        browser2.close()

    finally:
        # 終了
        pass

はい。やっていることはコメントのとおりですが。これだけで、ChromeとFirefoxでGoogleにアクセス&「Hello Selenium」と検索、結果のところでスクリーンショットという処理を行います。

実行!

はい。では最後に実行します。

$ cd [docker-compose.ymlがあるディレクトリ]
$ docker-compose up -d --build
$ docker exec -it python python /root/script/sample.py

はい。これで実行もできて、scriptディレクトリの下には検索結果のスクリーンショットも出力されます。またVNCでブラウザコンテナのポートを指定すると動作している画面を表示することもできます。今回ならlocalhost:5900でOK。

終わりに!

はい。これでいろんな環境でSeleniumが動かせますね。今回作業した内容は下記のリポジトリでまとめておきますので参考までにどうぞ!

次はここで構築したSeleniumを使って何かやりたいと思います。それでは!