Seleniumによる自動ブラウジングを活用することでウェブ上から情報を自動取得するスクレイピングやウェブアプリの自動テストなどが可能になります。特にスクレイピングは解析したい情報を大量に取得する方法として有用です。
今回の記事ではDockerを使って簡単にSelenium環境を構築する方法を紹介します!以下の人におすすめです。
- これからスクレイピングを初めてみたい人
- BeautifulSoupで情報収集できないページに困っている人
- Seleniumの初期設定に困っている人
- 複数の人とSelenium実行環境を共有したい人
そもそもSeleniumを使うメリット
Pythonのスクレイピングといえばライブラリをインストールするだけで使えるBeautifulSoupも有名ですが、BeautifulSoup自体の更新が止まっている点やJavaが組み込まれたサイトから情報を取得できないという点が弱点です。
一方、Thoughtworks社に開発されたSeleniumは今でも更新が続いており、ChromeやEdgeなどのブラウザを自動で操作(自動ブラウジング)できるフレームワークです。自動ブラウジングできるのでJavaのページによくあるスクロールダウンすると記事が増える仕組みや、フォームの入力、スクリーンショットの取得など様々な動きを実現できます。ただし自動操作するブラウザとSelenium WebDriverのバージョンが一致している必要があったり、Dockerなしで環境を用意するのが難しい場合もあります。
Python+Selenium環境の概要
今回用意する環境を図で表すと以下になります。
ローカルPC内にPythonコンテナとSeleniumコンテナを用意し、Docker-composeで同時にコンテナを起動します。
Pythonコンテナ
PythonコンテナはSeleniumがインストールされたPython環境です。pythonファイルをこちらのコンテナから実行して、同時に起動するSeleniumコンテナ内のChromeを操作します。Python公式イメージにSeleniumなどの必要ライブラリーをインストールして使います。
Seleniumコンテナ
Selenium公式『Selenium:standalone-chrome』イメージから構築できるコンテナをそのまま使います。UbuntuベースにChromeがインストールされているだけでなく、コンテナ内にWebDriverがインストールされたSeleniumサーバーも構築されています(細かい理解が間違っていたらすみません)。Pythonコンテナから来る指令をWebDriverが仲介してChromeを操作します。
ローカルで普段使いしているChromeを使わないので、WebDriverとChromeのバージョン管理をしなくてよい点が最大のメリットです!
構築手順
まずDockerが必要なので公式ドキュメントなどを参考にDockerをインストールしましょう。
以下のディレクトリ構造のファイルを用意します。この構造で後述のファイルを完全コピペすればエラーなく動作する環境を構築できるはずです。
PythonSelenium
├── docker-compose.yml
├── py_context
│ ├── Dockerfile
│ └── requirements.txt
└── work
└── test.py
構築に必要なファイルの用意
各ファイルの中身を見ていきます。まずはdocker-compose.ymlファイル
version: '3'
services:
selenium: # selenium container
image: selenium/standalone-chrome:latest # docker hubのselenium公式イメージ
shm_size: 2gb # ホストとメモリを共有するために設定
ports:
- 4444:4444 # selenium sever port
- 7900:7900 # 実行中のChromeを確認するVNC用port
python: # python container
build: ./py_context # python3のbuild contextを指定
volumes:
- ./work:/work # ローカルの"./work"とコンテナの"/work"をバインド
tty: true # ターミナル入力を受け付ける
depends_on: # seleniumコンテナの後で起動させるように指定
- selenium
ymlファイルではseleniumとpythonそれぞれのコンテナの起動に関する設定を記載します。WebDriverのアドレスが『http://[seleniumコンテナの名前]:4444/wd/hub』となるので、コンテナ名を変更する場合は注意してください。pythonコンテナは後ほどアレンジできるようにpy_contextから作成します。
続いてpythonコンテナを構築するDockerfile
FROM python:latest # ベースイメージとしてpython公式
RUN apt-get update && \ # Linux環境を整えるパッケージインストール
apt-get install -y \ # お好みで必要なパッケージを追加してください
build-essential \
cmake \
git \
sudo \
wget \
vim
RUN pip install --upgrade pip # pipの更新
COPY ./requirements.txt /requirements.txt # python libraryのリストをホストから取得
RUN pip install -r /requirements.txt # requirements.txt内のライブラリーを一括インストール
WORKDIR /work
CMD ["/bin/bash"]
Linuxのパッケージとpythonライブラリーは目的に応じて追記してください。スクレイピングには概ね以下のライブラリーが入っていれば事足りる印象です。
requests
selenium
BeautifulSoup4
pandas
docker-composeによるコンテナ起動
PythonSeleniumディレクトリに移動して以下のコマンドを実行します。
$ cd PythonSelenium
$ docker-compose build
$ docker-compose up -d # detouched mode option
$ docker-compose exec python bash # 起動したpythonコンテナに入る
これでターミナルの先頭が”#”になっていればpythonコンテナに入っていることを意味しています。あとは好きなpythonファイルを実行するだけです。
PythonファイルからSeleniumでChromeを操作する
pythonファイルは超シンプルにしました。実際にスクレイピングする際はoptionsを真面目に設定したりする必要があります。
from selenium import webdriver
import time
options = webdriver.ChromeOptions()
driver = webdriver.Remote(
command_executor = 'http://selenium:4444/wd/hub',
options = options
)
driver.implicitly_wait(10)
url = 'https://datascience-beginer.com/' # テストでアクセスするURLを指定
driver.get(url)
time.sleep(3)
driver.save_screenshot('test.png') # アクセスした先でスクリーンショットを取得
driver.quit()
上記のtest.pyファイルをコマンドラインから実行します。
# python /work/test.py
実行後にスクリーンショットが”test.png”として取得できていれば成功です!
pythonファイル実行中のChromeブラウザの挙動は、ホストの適当なブラウザから『http://localhost:7900/?autoconnect=1&resize=scale&password=secret』にアクセスすることでリアルタイムで確認できます!
まとめ
今回の記事はDockerがインストールされていることが前提ですが、逆にいうとDockerさえ入っていれば簡単かつ再現性よくSelenium環境を用意できます。やはりDockerは便利ですね!ぜひお試しください!
コメント
compoesのtypoがありますね。
shinriyo様
諸事情ありまして返信が大変遅くなりました。
“compoes”のタイポご指摘ありがとうございます。修正しました。
管理人
docker+selenium+スクレイピングでこのサイトに辿り着きました。
記事の内容で無事スクレイピングが実施できました。
ありがとうございます!
一点、タイポを見つけたので報告です。
「docker-composeによるコンテナ起動」にあるコマンドが違うようです。
誤: $ docker-compoes up -d
正: $ docker-compose up -d
(composeがcompoesになっている)
ご確認いただければ幸いです。
mkeisuke様
諸事情ありまして返信が大変遅くなりました。
“compoes”のタイポご指摘ありがとうございます。修正しました。
管理人