なりせなるてず

技術ブログにしたい

ヘッドレスChrome+Selenium+Pythonでファイルダウンロード

業務に必要なレポートを毎日ダウンロードして加工して別レポート作成する、
みたいな作業を自動化して欲しいとのことでSeleniumでサクッと作ろうと思ったんですが、ヘッドレスChromeだとデフォルトではファイルダウンロードができなくて半日費やしました。

その時の解決方法のメモ。

環境

CentOS7.2
Python2.7.5 (小学生に笑われるやつ)
Selenium
Google Chrome 66.0.3359.117

現象

vaaaaaanquish.hatenablog.com
上記の記事を参考にさせてもらって普通にページの取得とかはできたんですが、ダウンロードボタンを押しても何も起こりませんでした。
正確に言うと、処理の時間としてはダウンロードしてるのとほぼ同じ時間かかっているものの実際のファイルはどこにも無い、かつエラーも出てないという現象でした。

CentOSで使ってたソースをMacに持ってきてヘッドレスじゃないChrome+Seleniumだと普通にダウンロード出来たのでヘッドレスChrome特有の問題かなと当たりをつけました

結論 & 解決

調べてみるとヘッドレスChromeではセキュリティのためデフォルトでファイルのダウンロードが出来ないようになってるみたいでした
stackoverflow.com

上記のstackoverflowに載ってる解決方法とほぼ同じなんですが以下の様にすることでファイルをダウンロード出来ました。
以下の例はヘッドレスChromeChromeをダウンロードしてます。

# -*- coding: utf-8 -*-
from selenium import webdriver
from time import sleep

chromeOptions = webdriver.ChromeOptions()
chromeOptions.add_argument('--headless')
chromeOptions.add_argument('--window-size=1280,1024')

driver = webdriver.Chrome(chrome_options=chromeOptions)

# ヘッドレスChromeでファイルダウンロードするにはここが必要だった
driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')
driver.execute("send_command", {
    'cmd': 'Page.setDownloadBehavior',
    'params': {
        'behavior': 'allow',
        'downloadPath': './' # ダウンロード先
     }
})

# ヘッドレスChromeでChromeをダウンロードしてみる
driver.get('https://www.google.co.jp/chrome/index.html')
sleep(3)

# Chromeをダウンロードボタンをクリック
driver.find_element_by_css_selector('#marquee > a').click()
sleep(1)

# 同意してインストールボタンをクリック
driver.find_element_by_css_selector('#eula-accept').click()
sleep(15)

driver.close()


ヘッドレスChromeでファイルダウンロードできた!
ちなみにChrome62から追加されたっぽい?機能なのでそれ未満はダメかもです