Pythonを用いたスクレイピングではBeautiful Soupがよく用いられていますが、それだけではJavascriptを使用した動的webサイトに対応することができません。
Go言語のスクレイピングライブラリのgoqueryでも同様です。
ローカルに色々インストールするのは美しくないので、今回はDockerでPython用のスクレイピング環境を構築しようと思います。

最終的には次のような構造になります。

$ tree
.
├── Dockerfile
├── docker-compose.yaml
└── src
    └── scrape.py

 

コードはGitHubにあげてあります。

https://github.com/samskeyti88/python-scrape

Dockerfile

FROM python:3.7-alpine

RUN apk update
RUN apk add ttf-freefont chromium chromium-chromedriver
RUN pip install beautifulsoup4 selenium

RUN mkdir /noto
ADD https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip /noto
WORKDIR /noto
RUN unzip NotoSansCJKjp-hinted.zip && \
    mkdir -p /usr/share/fonts/noto && \
    cp *.otf /usr/share/fonts/noto && \
    chmod 644 -R /usr/share/fonts/noto/ && \
    fc-cache -fv
RUN rm -rf /noto

 

Headless Chromeを用いるためにchromiumとchromium-chromedriverをインストールします。

フォント部分は日本語を処理できるようにするためのものです。

 

docker-compose.yaml

version: '3'
services:
  python-scrape:
    build: .
    image: python-scrape
    container_name: python-scrape
    working_dir: /root/src
    volumes:
      - ./src/:/root/src/
    tty: true

 

特に問題ないと思います。pythonファイルは./srcディレクトリ以下に保存するようにします。

 

scrape.py

# #coding: utf-8
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
driver = webdriver.Chrome(options=options)


driver.get('https://www.tv-asahi.co.jp/ametalk/backnumber/')
html = driver.page_source.encode('utf-8')
soup = BeautifulSoup(html, "html.parser")
print(soup.select_one("#backnumber > ul.column-3-box.clearfix > li.row1141.rowall > a > p"))

 

オプションで「--no-sandbox」を付けることに気をつけてください。これがないとうまく動作しません。

今回はテレビ朝日のアメトーークのバックナンバーページを対象としてみました。

このページはJavascriptを用いた動的サイトで、普通にBeautiful Soupを使ってスクレイピングをしようと思っても失敗します。

 

実行

docker-composeでdockerコンテナを作成します。

$ docker-compose up -d

 

dockerイメージがまだ作られていない場合は、このコマンドで自動で作成してくれます。

次に、dockerコンテナに入ってみましょう。

$ docker-compose exec python-scrape sh

 

scrape.pyの対象となっているテレ朝のページをchromeの開発者モードで確認します。


Beautiful Soupで取り出したいselectorは、chromeの開発者モードで該当箇所を右クリックしてCopy selectorから得ましょう。

実際にDockerコンテナ上でpythonファイルを実行してみます。

$ python scrape.py
<p class="txt-box summernote">3月7日<br/>実家ビンボー芸人</p>

 

きちんとデータが取ってこれることが分かりました。

 

まとめ

DockerでHeadless Chromeとpythonを用いた動的webサイトのスクレイピングを行う方法を紹介しました。

この環境さえ揃っていれば静的サイトも同様にスクレイピングできます。

コンテナは気軽に消せて最高ですね。

おすすめの記事
macでOpenPoseを動かす
機械学習
CVPR2017で発表されたリアルタイム姿勢検出手法のライブラリOpenPoseをmacで動かしてみました。pyenvを用います。matpl...