Pythonでwebページのキャプチャを取得

今日もPython

というわけで、PythonでChromeDriverを使って、キャプチャ取得する方法をまとめます。

PC/Mobileを引数で指定して、Mobileの場合はChromeのモバイルエミュレートで
取得する事にしました。

JavaでもChromeDriver使えるのですが、「すっごく重い」「メモリ食いまくり」でした。
代替案として出てきたのがPythonです。
以下、実際のコードを交えながら説明していきます。

まず。前提として、サーバーに導入されていないであろう、chromedriverはインストールしておいてください。
chromedriverは、apt-get, yum にて導入可能なはずです。

インストールできない場合は、こちら より、ダウンロードして任意のパスへ導入してください。

また、普通にpythonを使っているだけだと、python用のselenium, xvfbwrapperも入ってないはずなので
pip install selenium
pip install xvfbwrapper

をコンソールで実行し、インストールしてください(rootに準ずる権限が必要です)

# -*- coding: utf-8 -*-

import sys, time, glob, ConfigParser
from selenium.common.exceptions import WebDriverException
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from xvfbwrapper import Xvfb

if __name__ == "__main__":
    param = sys.argv
    if len(param) != 4:
        print "Usage: cap.py   "
        sys.exit()

    url = param[1]
    cappath = param[2]
    device = param[3]

    ini = ConfigParser.SafeConfigParser();
    ini.read('cap.py.ini')

    if device == "PC":
        userAgent = ini.get("capture", "useragent.pc")
        displaySize = ini.get("capture", "windowsize.pc")
    elif device == "Mobile":
        userAgent = ini.get("capture", "useragent.mobile")
        displaySize = ini.get("capture", "windowsize.mobile")
    else:
        print "Device require \"PC\" or \"Mobile\""
        sys.exit()

    driverPath = ini.get("capture", "chromedriver")

    vdi = Xvfb()
    vdi.start()

    chrome_options = Options()
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-setuid-sandbox")
    chrome_options.add_argument("--lang=ja")
    chrome_options.add_argument("--user-agent=" + userAgent)
    chrome_options.add_argument("--window-size=" + displaySize)

    if device == "Mobile":
        window_size_list = displaySize.split(",")
        mobile_emulation = {"deviceMetrics": { "width": int(window_size_list[0]), "height": int(window_size_list[1]), "pixelRatio": 3.0 }}
        chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)

    driver = webdriver.Chrome(driverPath, chrome_options=chrome_options)
    driver.get(url)

    try:
        alert = driver.switch_to_alert()
        alert.accept()
    except:
        print "no alert to accept"

    time.sleep(10)

    try:
        driver.save_screenshot(cappath)
    except WebDriverException as w:
        print "WebDriverException {0}: {1}".format(w.errno, w.strerror)

    driver.quit()
    vdi.stop()

 

さて。上記コードですが、重要な部分のみ取り上げ、解説します。
まずは

ini.read('cap.py.ini')

このコードで、設定を読み込んでいます。
設定内容は次の通りです。

[capture]
chromedriver = /usr/lib/chromium/chromedriver

useragent.pc = Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.10 Safari/537.36
windowsize.pc = 1920,1080

useragent.mobile = Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/46.0.2490.85 Mobile/12H143 Safari/600.1.4
windowsize.mobile = 375,667

chromedriverの場所、PCとMobileのUAと画面サイズの設定ですね。

    chrome_options = Options()
    chrome_options.add_argument("--no-sandbox")

chromeの各種設定です。
設定内容にについては、https://sites.google.com/a/chromium.org/chromedriver/capabilities

に一通り載っていますので、割愛させていただきます。

次が非常に大事ですね。DeviceをMobileとして指定したときに、chromeのmobile emulateを行っています。

    if device == "Mobile":
        window_size_list = displaySize.split(",")
        mobile_emulation = {"deviceMetrics": { "width": int(window_size_list[0]), "height": int(window_size_list[1]), "pixelRatio": 3.0 }}
        chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)

次に、driverのインスタンスを作成して、drver.get()でアクセスしています。

このコードが一発でわかる人はいないのではないか。というのが次のコードです。

    try:
        alert = driver.switch_to_alert()
        alert.accept()
    except:
        print "no alert to accept"

これは、モバイルへ誘導されるときにjsのalertがあがるサイトへの対策です。
アラートが存在すれば、、OKをエミュレートしています。
 

    time.sleep(10)
    try:
        driver.save_screenshot(cappath)
    except 

上記では、10秒スリープさせてますが、これは、ページの描画待ち処理です。
time.sleep(10)をなくして実行してみると、例えばjsでの遅延ロードなどがロードされないまま
キャプチャされてしまいます。

最後に、driver.quit() 及び vdi.stoip() でドライバの停止と仮想ディスプレイの停止を行って
処理終了です。

大まかな部分のみ説明しましたが、お役に立てれば何よりです。
chromedriverの説明は国内の情報は少なめなので。

  • entry29ツイート
  • Google+

PageTop