GWに調べたことのメモです。
Jupyter Notebook上でSeleniumを動かすことのできるDockerイメージを作成します。
Seleniumがどんなものか手っ取り早く試してみるための環境です。
参考記事
本記事の作成には、以下の記事を参考に作成させていただきました。
Dockerイメージ作成
まずは、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())