2017/03/15更新

[Python] JavascriptでレンダリングされるWebページを、スクレイピングする

このエントリーをはてなブックマークに追加      

こんにちは、@yoheiMuneです。
今日はReact.jsなどのJavascriptでページをレンダリングするページについて、スクレイピングを行う方法をブログに書きたいと思います。
画像

目次




スクレイピング対象のページ

今回は以下のJavaScriptで、画像を追加して表示するようなページを対象にします。

画像 http://yoheim.net/work/async_page.html


上記のページでは以下のようなJSで、ページ表示時に画像を動的に読み込みます。
<ul id="imageRoot">
    <li>ここにJavaScriptでレンダリングします.</li>
</ul>

<script>
window.addEventListener('DOMContentLoaded', function() {

    urls = [
        '//yoheim.net/image/s156.png',
        '//yoheim.net/image/s157.png',
        '//yoheim.net/image/s158.png'
    ];

    var ul = document.getElementById('imageRoot');
    ul.innerHTML = '';

    urls.forEach(function(url) {
        var image = new Image();
        image.src = url;
        ul.appendChild(image);
    });
});
</script>
そのためurllib.requestなどで単純にHTMLを取得しただけだとダメで、Javascriptを評価して実行する必要があります。



準備

JSの実行も含めてスクレイピングを行うために、以下の3つの技術要素を利用します。
BeautifulSoup
スクレイピングライブラリ
PhantomJS
ヘッドレスブラウザ
Selenium
ブラウザの自動操作を行うツール
PhantomJSを使ってHTMLの取得からJavascriptの実行を行い、その結果をBeautifulSoupに渡すことでスクレイピングを行います。Seleniumは、PhantomJSの制御に利用します。


BeautifulSoupのインストール

BeautifulSoupはpipで導入することができます。
$ pip install --upgrade beautifulsoup4


PhantomJSのインストール

PhantomJSは以下のサイトから実行ファイルをダウンロードして、そのファイルにパスを通すことで動かせるようにします。

画像 http://phantomjs.org/

ダウンロードしてきたファイルを、例えば以下のようにすることで、パスを通すことができます。
# ダウンロードしてきたディレクトリに移動
# 以下の場合は、Downloadフォルダにある例です
cd ~/Downloads/phantomjs-2.1.1-macosx/

# /usr/local/bin にコピー
cp bin/phantomjs /usr/local/bin/
もしくは~/.bash_profileなどでパスを通すのでも良いです。お好みの方法でパスを通してください。

最後に以下のコマンドが動けばOKです。
$ phantomjs
phantomjs> 


Selenimのインストール

Seleniumはpipからインストールすることができます。
$ pip install --upgrade selenium
以上で準備は完了です。



JSでレンダリングするページをスクレイピングする

やっと本題です。JSレンダリングを含めてスクレイピングする場合には、以下のように実装します。
from pprint import pprint
from selenium import webdriver
from bs4 import BeautifulSoup
import time

# PhantomJSをSelenium経由で利用します.
driver = webdriver.PhantomJS()

# PhantomJSで該当ページを取得&レンダリングします
driver.get("http://yoheim.net/work/async_page.html")

# ちょっと待つ
# (ページのJS実行に時間が必要あれば)
# time.sleep(5) # 5s

# レンダリング結果をPhantomJSから取得します.
html = driver.page_source

# 画像のURLを取得する(JSでレンダリングしたところ).
bs = BeautifulSoup(html, "html.parser")
img_urls = [img.get("src") for img in bs.select("#imageRoot img")]
pprint(img_urls)

# ついでにスクリーンショットも取れます.
driver.save_screenshot("ss.png")

# 終了
driver.quit()
とこんな感じでデータを取得できます。実装自体はシンプルでいいですね!



最後に

Javascriptの実行結果をスクレイピングできると、より多くのサイトのデータを取得できるので楽しい限りです。Pythonについてはまだまだいっぱいブログを書こうと思います。

最後になりますが本ブログでは、Python・Linux・Node.js・フロントエンド・インフラ・Go言語・開発関連・Swift・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSTwitterをフォローして頂けると幸いです ^ ^。

最後までご覧頂きましてありがとうございました!





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。