Ubuntu ServerのDocker上でseleniumを動かす

Pythonといえば「WEBスクレイピング」というように、ライブラリをインストールするだけで簡単にできるということで今回は、WEBスクレイピングに挑戦です。

はじめに

WEBスクレイピングには、①WEBページの取得、②データの抽出という段階がありますが、よく耳にする requests と BeautifulSoup の組み合わせは動的に生成されたページからの情報が取得できないとのこと…
①WEBページの取得は requests 、②データの抽出は BeautifulSoup という役割分担になっていますが、Selenium は Chrome や firefox などのブラウザを自動で操作できるフレームワークということで、Selenium だけで動的に生成されたページの取得ができ、情報の取得もできるというツワモノだそうです。
ただし、ブラウザを制御するために Selenium のコアとなる、 Web Driver と ブラウザのバージョンが一致する必要があるため導入の際には注意が必要なようです。

Seleniumの導入

そこで、今回は、selenium の環境を構築するために Docker を使用します。
Docker を使用することでホスト環境に影響を与えることなく構築することができるのが最大のメリットです。
Selenium の イメージは docker hubで幾つか配布されていますが、今回はselenium/standalone-chromeを使用したいと思います。

Selenium の Dcoker image を起動してみます。

$ docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-chrome:latest

ダウンロードが行われたらそのままデーモンとして起動されたはずです。
ダウンロードされた Dcoker image を確認してみます。

$ docker images
REPOSITORY                   TAG       IMAGE ID       CREATED       SIZE
selenium/standalone-chrome   latest    deff784da213   11 days ago   1.21GB

起動したコンテナを確認します。

$ docker ps
CONTAINER ID   IMAGE                               COMMAND                   CREATED        STATUS          PORTS                                                                                            NAMES
aa10cb67136f   selenium/standalone-chrome:latest   "/opt/bin/entry_poin…"   10 hours ago   Up 24 seconds   0.0.0.0:4444->4444/tcp, :::4444->4444/tcp, 0.0.0.0:7900->7900/tcp, :::7900->7900/tcp, 5900/tcp   nifty_mendeleev

動作確認として、ローカルである Ubuntu Server には GUI がないので、ホスト側からVNCポートへアクセスしてみます。

http://localhost:7900/?autoconnect=1&resize=scale&password=secret

当然、この場合は接続できません。
Selenium server は 仮想マシンで稼働しているため、ホスト側のローカルホストではアクセス出来ないためです。
ネットワーク設定をブリッジに変更したのはそのためで、割り当てられたIPアドレスを指定してアクセスします。

http://192.168.0.92:7900/?autoconnect=1&resize=scale&password=secret

無事にVNC接続が確認できました。

Pythonの導入

次にPythonを導入します。
今回は、新たに Dockerfile を作成し Docker上で動作するPython環境を構築したいと思います。

Dockerfile を保存するディレクトリと作業用のディレクトリを作成します。

$ mkdir docker-selenium
$ mkdir docker-selenium/work

Dockerfile の保存先となる docker-selenium へ移動します。

$ cd docker-selenium

Dockerfile を作成します。
※インストールした Ubuntu Server にはエディタ環境がないので、お好きなエディタを導入してください。私は nano 派です。

$ nano Dockerfile

内容は下記のようにpython環境のうえにseleniumのみを導入します。

FROM python:latest
RUN apt-get update
RUN pip install --upgrade pip
RUN python -m pip install selenium
WORKDIR /work

buildコマンドで Dockerfile からイメージファイルを作成します。

$ docker build -t python-selenium:test -f Dockerfile .

ビルドしたイメージを run コマンドで実行します。

$ docker run -d -it --name python-selenium python-selenium:test

現在、Docker image は下記のようになっています。

$ docker images
REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
python-selenium              test      b1750d3d20c2   25 seconds ago   1.1GB
selenium/standalone-chrome   latest    deff784da213   11 days ago      1.21GB

起動したコンテナを確認します。

$ docker ps
CONTAINER ID   IMAGE                               COMMAND                   CREATED              STATUS              PORTS                                                                                            NAMES
c96de4c4d339   python-selenium:test                "python3"                 About a minute ago   Up About a minute                                                                                                    python-selenium
aa10cb67136f   selenium/standalone-chrome:latest   "/opt/bin/entry_poin…"   11 hours ago         Up About an hour    0.0.0.0:4444->4444/tcp, :::4444->4444/tcp, 0.0.0.0:7900->7900/tcp, :::7900->7900/tcp, 5900/tcp   nifty_mendeleev

バックグランドで実行中のPython環境にログインしてみます。

$ docker exec -it python-selenium bash

実は、この環境エディタなどがないのでちょっと不便です。
そこで、先ほど作成した作業ディレクトリの work を bind して python 環境から自由にアクセスできるようにしたいと思います。
まず、現在起動中のコンテナを停止して削除します

$ docker stop python-selenium
$ docker rm c96de4c4d339

今度は bind を指定して先ほど作成した work ディレクトリを bind したいと思います。
今回は work の中に test.py というpythonコードを準備します。

$ nano work/test.py

中身はこれ

print("hello world")

では、bind付きでコンテナを作成します。

$ docker run -d -it --name python-selenium --mount type=bind,source=./work,target=/work python-selenium:test

さきほどと同様にバックグランドで実行中のPython環境にログインしてみます。

$ docker exec -it python-selenium bash

ls コマンドで確認すると

root@47cb3038ec9a:/work# ls
test.py

test.py を実行してみます。

root@47cb3038ec9a:/work# python test.py
hello world

無事に hello world が表示されました。

seleniumの動作確認

今度は selenium の動作確認を行いたいと思います。
下記のように se.py を用意します。

from selenium import webdriver
import time

options = webdriver.ChromeOptions()
driver = webdriver.Remote(
             command_executor = 'http://192.168.0.92:4444/wd/hub',
             options = options
             )

driver.implicitly_wait(10)

url = 'https://www.chobits.com'
driver.get(url)

time.sleep(3)
driver.save_screenshot('chobits-selenium.png')
driver.quit()

それでは、実行してみたいと思います。

root@47cb3038ec9a:/work# python se.py

エラーなく無事に chobits-selenium.png も生成されれば成功です。

これで、selenium によるスクレイピングができるようになりました。
実はここまでが下準備のようなものです。
まだまだ、作業は続きますが、今回はここまで…