12
11

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

Selenium + Headless Chrome + Jupyter Notebook + Docker

Last updated at Posted at 2021-05-01

GWに調べたことのメモです。
Jupyter Notebook上でSeleniumを動かすことのできるDockerイメージを作成します。
Seleniumがどんなものか手っ取り早く試してみるための環境です。

参考記事

本記事の作成には、以下の記事を参考に作成させていただきました。

Dockerイメージ作成

まずは、Dockerfileの全体です。

Dockerfile
FROM jupyter/scipy-notebook:latest

USER root
WORKDIR /tmp

# 必要なツールとIPAフォントをインストールします
RUN apt-get update && apt-get install -y gnupg curl fonts-ipafont fonts-ipaexfont
# Google Chromeをインストールします
RUN wget https://dl.google.com/linux/linux_signing_key.pub \
 && apt-key add linux_signing_key.pub \
 && echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list \
 && apt-get update \
 && apt-get install -y google-chrome-stable \
 && google-chrome --version

# Chrome Driverをインストールします
RUN CHROMEDRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` \
 && curl -sS -o /tmp/chromedriver_linux64.zip http://chromedriver.storage.googleapis.com/$CHROMEDRIVER_VERSION/chromedriver_linux64.zip \
 && unzip /tmp/chromedriver_linux64.zip \
 && mv chromedriver /usr/local/bin/

# PermissionError: [Errno 13] Permission denied: '/home/jovyan/.local/share/jupyter'
# となぜか怒られるのでとりあえず所有者を変更
RUN chown -R jovyan /home/jovyan/.local

USER jovyan
# selenium導入
RUN pip install selenium
WORKDIR /home/jovyan

上記を使って、jupyter-seleniumというイメージを作成します。

$ docker build -t jupyter-selenium .

Dockerfileポイント説明

上のDockerfileのポイントをいくつか説明していきます。
Dockerのベースイメージには、jupyter/scipy-notebookを使っています。

Google Chromeインストール

【2019年版】Ubuntu18.04 にChromeとSeleniumをインストールの記事を基にGoogle Chromeをインストールします。

RUN wget https://dl.google.com/linux/linux_signing_key.pub \
 && apt-key add linux_signing_key.pub \
 && echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' | tee /etc/apt/sources.list.d/google-chrome.list \
 && apt-get update \
 && apt-get install -y google-chrome-stable \
 && google-chrome --version

Chrome Driver導入

https://chromedriver.storage.googleapis.com/LATEST_RELEASE というところで、最新のChrome Driverのバージョンが取れるようなので、それを利用します。
解凍したChrome Driverをパスの通った場所に配置します。

RUN CHROMEDRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` \
 && curl -sS -o /tmp/chromedriver_linux64.zip http://chromedriver.storage.googleapis.com/$CHROMEDRIVER_VERSION/chromedriver_linux64.zip \
 && unzip /tmp/chromedriver_linux64.zip \
 && mv chromedriver /usr/local/bin/

Jupyter Notebook起動

作成したイメージを使って、Jupyter Notebookを起動します。
カレントディレクトリにworkというディレクトリを作業用に作成し、マウントしておきます。

$ docker run -d -v $(pwd)/work:/home/jovyan/work -p 8888:8888 --name jupyter-selenium jupyter-selenium

コンテナに入って、rootユーザで色々作業するときは、以下のように起動します。
参考: https://jupyter-docker-stacks.readthedocs.io/en/latest/using/common.html#docker-options

$ docker run -u root -e GRANT_SUDO=yes -d -v $(pwd)/work:/home/jovyan/work -p 8888:8888 --name jupyter-selenium jupyter-selenium

ブラウザでアクセスするためのURLは以下で取得します。
0.0.0.0の部分をlocalhost等に変えて、http://localhost:8888/?token=(トークン)で、Jupyter Notebookにアクセスします。
(手元のMac環境では、0.0.0.0そのままでも動きました。)

$ docker exec -it jupyter-selenium jupyter notebook list
Currently running servers:
http://0.0.0.0:8888/?token=(トークン) :: /home/jovyan

Jupyter Notebookを開いたら、Python 3のノートブックを作成します。

Seleniumコード

ChromeをHeadlessモードで起動して、Google検索するためのコードを書きます。
Pythonは初心者なので、おかしなところはご容赦ください。

初期化

ChromeをHeadlessモードで起動するためのオプションを指定して、Web Driverを初期化します。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from IPython.display import Image

# WebDriverが既に起動したら閉じておく(Pythonでこんな書き方で良いかは自信はない)
try:
    driver.quit()
    print("driver is closed.")
except NameError:
    print("driver is not initialized.")

options = Options()
options.binary_location = '/usr/bin/google-chrome'
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-gpu')
options.add_argument('--window-size=1280,1024')

driver = webdriver.Chrome('chromedriver', options=options)

Google検索

Googleのページを開きます。
スクリーンショットを取得して、保存します。
また、IPython.displayを使って、ノートブック上に画像を表示します。
参考: JupyterNotebook上に画像を表示する2つの方法

driver.get('https://www.google.com/')
print(driver.title)
assert driver.title == "Google"
driver.save_screenshot('screenshot_google.png')
Image("screenshot_google.png")

次に検索ボックスに「Selenide」と入力し、検索します。
ちなみにSelenideは、SeleniumのJavaラッパーのテストフレームワークです。

search_box = driver.find_element_by_name("q")
search_box.send_keys('Selenide')
search_box.submit()
print(driver.title)
driver.save_screenshot('screenshot_search.png')
Image("screenshot_search.png")

最後に、Web Driverを閉じます。

driver.close()
driver.quit()

備考: 要素クリック直前・直後の処理を定義

要素をクリックする直前・直後に行う処理を定義する場合は、初期化時のコードをおそらく以下のようにすれば良さそうです。
待機処理やスクリーンショットの取得をクリック毎に行うような場合に使います。
使っているフレームワークや対象サイトの特性に応じて、上手に活用するとSeleniumの苦手なAjax処理の待機をうまくできたりします。

参考: 【Python】before_click/after_click・・・要素がクリックされる直前/直後の処理を実施する

from selenium.webdriver.support.events import EventFiringWebDriver, AbstractEventListener
# ・・・
class MyListener(AbstractEventListener):
    def before_click(self, element, driver):
        #要素をクリックする直前の処理
        print("before_click:" + driver.current_url)
    def after_click(self, element, driver):
        #要素をクリックした直後の処理
        print("after_click:" + driver.current_url)
        
base_driver = webdriver.Chrome('chromedriver', options=options)
driver = EventFiringWebDriver(base_driver, MyListener())
12
11
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
12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?