今日も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の説明は国内の情報は少なめなので。
コメント