はじめに
Webサイトが静的であれば、requests モジュール等を使ってhtmlの解析ができますが、Javascriptを使った動的サイトであればページが読み込まれてからデータが反映されることもあり、静的サイトのように解析ができません。
そのような動的サイトのスクレイピングは、Selenium というライブラリを使用することで可能になります。ただし、Selenium では走らせるブラウザの WebDriver が必要になります。
今回はSeleniumを使ったWebスクレイピング環境をDockerで構築します。
この記事で使用したソースコードは以下のGitHubで利用できます。
使用するソースコード
今回必要なファイル一式のディレクトリ構造は以下の通りです。
.
├─ dockerfile
├─ main.py
└─ requirements.txt
Dockerfile
使用するdockerfileは次のようになります。
##### building stage #####
FROM python:3.10 as builder
RUN apt-get update && apt-get install -y \
unzip
# chrome driver
ADD https://chromedriver.storage.googleapis.com/101.0.4951.41/chromedriver_linux64.zip /opt/chrome/
RUN cd /opt/chrome/ && \
unzip chromedriver_linux64.zip && \
rm -f chromedriver_linux64.zip
# python package
RUN pip install --upgrade pip
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
##### production stage #####
FROM python:3.10-slim
COPY --from=builder /opt/ /opt/
COPY --from=builder /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages
RUN apt-get update && apt-get install -y \
wget \
curl \
gnupg
# chrome
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add && \
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 && \
apt-get -y clean && \
rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY main.py .
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/chrome
google-chrome-stable でChromeをインストールしています。今回使用しているWebDriverのバージョンは101.0.4951.41ですが、将来、インストールしたChromeとのバージョンの違いで動作しない恐れがあります。
動作しない場合は、インストールされるChromeに適したWebDriverのバージョンを指定してください。
▼ こちらのサイトにChrome Driverのバージョンが管理されています。
pythonファイル
main.pyのソースコードは次の通りです。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome import service as fs
CHROMEDRIVER = '/opt/chrome/chromedriver'
URL = '{スクレイピングするURLを記載}'
options = Options()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
chrome_service = fs.Service(executable_path=CHROMEDRIVER)
driver = webdriver.Chrome(service=chrome_service, options=options)
driver.get(URL)
html = driver.page_source
print(html)
コードの内容は、動的サイトのhtmlを出力する簡単なものです。
Chrome Driverは /opt/chrome/chromedriver
に保存されるので、そのパスを指定しています。また、docker環境でchromeを起動させるのに必要なオプションを記載しています。
requirements.txt
今回使用したrequirements.txtの内容は次の通りです。
requests==2.27.1
selenium==4.1.5
chromedriver-binary==101.0.4951.41.0
chromedriver-binaryのバージョンは、dockerfileでインストールするChrome Driverのものと一致させておきます。
以上が使用したソースコード一式です。
Dockerイメージの作成
次のコマンドを実行して、Dockerイメージを作成します。
$ docker build -t web_scraping .
以下のようにdocker imageが作成されていれば完了です。
# Dockerイメージの確認
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
web_scraping latest xxxxxxxxxxxx x seconds ago 929MB
Dockerコンテナに入って、実際にpythonが実行できるか確かめてみます。
# Dockerコンテナに入る
$ docker run -it --rm web_scraping /bin/bash
# コンテナ内でmain.pyを実行
root@xxxxxxxxxxxx:/app$ python main.py
# 出力
<html>
...
</html>
以上のように、Seleniumを使ったWebスクレイピング環境をDockerで構築することができました。