2022年11月27日日曜日

Raspberry Piで動作するSelenium+最新PythonのDockerコンテナを作成する

Raspberry Pi上のDockerでSeleniumを使う場合、Doker Hubにはselenium/standalone-chromeをforkしてRaspberry PiのCPUアーキテクチャであるARMに対応したseleniarm/standalone-chromiumがある。ただ、selenium/standalone-chromeのイメージにインストールされているPythonのバージョンは3.8と少し古い。そこで、今回はSeleniumと最新バージョンのPythonがインストールされたDockerコンテナを作成して、Raspberry Piで起動してみる。


環境

Raspberry Pi OS(64bit)。Raspberry Pi OS(64bit)にDockerとComposeをインストールする方法はRaspberry Pi OS 64bitでDockerを使うを参照。

$ lsb_release -dr
Description:    Raspbian GNU/Linux 11 (bullseye)
Release:        11
$ docker --version
Docker version 20.10.21, build baeda1f
$ docker-compose --version
docker-compose version 1.29.2, build unknown


Dockerfileの作成

Seleniumと最新Pythonが使えるDockerイメージを作成するためのDockerfileを用意する。ベースとなるDockerイメージとしてDocker Hubにある公式のPyrthonイメージの3.11-bullseyeを使う。Seleniumを使うにはブラウザとドライバが必要だが、今回はFirefoxとそのドライバであるgeckodriverをインストールする。Firefoxで日本語を表示できるように、日本語フォントの googlefonts / noto-cjkもインストールする。

FROM python:3.11-bullseye

WORKDIR /app

# Firefoxと日本語フォントインストール
RUN apt update \
    && apt -y install --no-install-recommends \
    # 日本語フォントインストール
    # 日本語フォントをインストールしておかないとFirefoxの表示が文字化けする
    fonts-noto-cjk \
    firefox-esr \
    && apt clean

# SeleniumのPythonバインディングインストール
RUN pip install selenium --no-cache-dir

# geckodriverインストール
RUN curl -LO https://github.com/mozilla/geckodriver/releases/download/v0.32.0/geckodriver-v0.32.0-linux-aarch64.tar.gz \
  && tar xzvf geckodriver-v0.32.0-linux-aarch64.tar.gz \
  && mv geckodriver /usr/bin/ \
  && rm geckodriver-v0.32.0-linux-aarch64.tar.gz


docker-composeファイルとSeleniumを使うサンプルスクリプトの用意

Dockerfileのほかに、docker-compose.ymlとSeleniumを使うPythonサンプルスクリプトを用意する。

version: '3'
services:
  selenium:
    build:
      context: .
      dockerfile: ./Dockerfile
    tty: true
    environment:
      - TZ=Asia/Tokyo
    volumes:
      - ./app:/app


以下のPythonスクリプトでは、Firefoxを起動してGoogleで「Raspberry Pi」を検索し、結果のスクリーンショットを保存する。

import os

from selenium.webdriver import Firefox, FirefoxOptions
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions

url = 'https://www.google.com'

# ブラウザーをヘッドレスで起動
options = FirefoxOptions()
options.add_argument('-headless')
service = Service(
    executable_path='/usr/bin/geckodriver', log_path=os.devnull
)
with Firefox(service=service, options=options) as driver:
    driver.get(url)

    # 画面表示を最大5秒まで待つ
    driver.implicitly_wait(5)
    # 検索ボックスのエレメントを取得(inputタグのname属性はq)
    elem = driver.find_element(By.NAME, 'q')
    # 検索ボックス内のテキストをクリア
    elem.clear()
    # 検索ワードを入力
    elem.send_keys('Raspberry Pi')
    # 検索ボタンがクリックできるようになるまで最大10秒待つ
    wait = WebDriverWait(driver, 10)
    input = wait.until(expected_conditions.element_to_be_clickable((By.XPATH, "//input[@value='Google 検索']")))

    if input.get_attribute('type') == 'submit':
        input.click()
    else:
        print('Failed to find submit button.')

    # 検索結果がなければ「No results found.」と表示する
    assert 'No results found.' not in driver.page_source

    # スクリーンショットを保存
    driver.save_screenshot('firefox_search.png')


ファイル配置は以下のようになる。

|-- Dockerfile
|-- app
| `-- sample.py
`-- docker-compose.yml


コンテナ上でSeleniumを使う

ファイルの準備ができたら、Dockerイメージを作成してSeleniumをPythonで使ってみる。まずはイメージをビルドする。

$ docker-compose build

続いて、コンテナ上で、作成したPythonスクリプトを実行する。

$ docker-compose run selenium python sample.py

スクリプトを実行すると、以下のようなfirefox_search.pngというFirefoxのスクリーンショットファイルが保存される。


0 件のコメント:

コメントを投稿