splinterによるブラウザ制御(1)

ウェブアプリケーションの開発をする際に、実際のブラウザで動作確認を行う、といった場面があるかと思います。

単純なHTTPの通信テストであればスクリプトでもなんとかなる場合もありますが、javascriptを使用している場合、javascriptの動作結果や挙動についても検証する必要があります。

こういったテストを行う場合、大抵は外部からブラウザを制御して行います。

有名どころとしてはSeleniumだと思いますが、今回はあえてsplinterを使用してみました。

インストールは pip から。

> pip install splinter

ちなみに標準ではfirefoxを使用しますので、 firefoxのインストールをしておく必要があります。

簡単な使用方法

# -*- coding: utf-8 -*-
import splinter

BROWSER = "firefox"
URL = "http://mizuvm01.cloudapp.net/wp"
oCBrowser = splinter.Browser(BROWSER)
oCBrowser.visit(URL)

こんな感じに記述します。

上の例では、firefoxを開き http://mizuvm01.cloudapp.net/wp を開きます。

ページ遷移後はhtmlやタグやIDの検索をする事が出来ます。

単純な表示だけでは面白くないので、うちのサイトから画像を取得するプログラムなんぞを作ってみます。

やることは以下の三つです。

  • 水凪工房のウェブサイトを開く。
  • 「魔法少女リリカルなのは」を検索する。
  • 表示されている画像をダウンロードする。

画像のダウンロードについてはsplinterで処理するのは困難なため、requestsモジュールを追加します。

> pip install requests

インストール出来たところで、早速こんな感じのコードを書きます。

# -*- coding: utf-8 -*-
import sys
import splinter
import re
import requests

URL = "http://mizuvm01.cloudapp.net/wp"
# ユーザーエージェントはサンプルを兼ねて明示的に指定しています。
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0) Gecko/20100101 Firefox/35.0"

def main():

    oCBrowser = splinter.Browser("firefox", user_agent=USER_AGENT)
    oCBrowser.visit(URL)

    oCBrowser.type("s", u"魔法少女リリカルなのは\n")

    oCReP = re.compile("(" + URL + "/[0-9]{4}/[0-9]{2}/[0-9]{2}/.*)")
    oCReI = re.compile("(" + URL + "/wp/wp-content/uploads/[0-9]{4}/[0-9]{2}/.*)")

    listHref = [r["href"] for r in oCBrowser.find_by_tag("a")]

    for strHref in listHref:
        oCResult = oCReP.search(strHref)
        if(oCResult is None):
            continue

        strBlogPage = oCResult.group(1)

        oCBrowser.visit(strBlogPage)

        listImage = oCBrowser.find_by_tag("a")

        for o in listImage:
            try:
                s = oCReI.search(o["href"])
            except:
                s = None

            if(s is None):
                continue

            strImageUrl = s.group(1)

            # ユーザーエージェントはsplinterで制御しているブラウザと同じにする。
            # リファラーを現在ページからとする。
            # クッキーの値をブラウザから取得して、requestsに反映させる。
            dictCookie = {}
            dictHeader = {
                "User-Agent": USER_AGENT,
                "Referer": strBlogPage
            }

            for k, v in oCBrowser.cookies.all().items():
                dictCookie[k] = v

            oCRes = requests.get(
                strImageUrl,
                headers=dictHeader,
                cookies=dictCookie,
                stream=True
            )

            # requestsが戻す結果のrawをファイルに書き出す事で実際に保存可能です。
            print strImageUrl.split("/")[-1], len(oCRes.raw.read())

    oCBrowser.quit()

if(__name__ == "__main__"):
    main()

かなりいい加減なコードですが、こんな感じとなります。