これは、Selenium + Python で Chrome を自動操作してファイルをダウンロードしようと思ったときの話です。テストでは上手くいくのに本番環境にいくとダウンロードされない。エラーも発生しない。ぜんぜん分からず調べること数時間…。
結局原因はヘッドレスモードでした。本番時にのみ--headless
オプションをつけていたことが仇になりました。Chrome の初期設定では(セキュリティのためか)ヘッドレスモードではファイルをダウンロードできないようです。それならそれでエラーで落としてほしいものです。
Webにあった情報を参考にプログラムを修正したら解決。無事にダウンロードができました。
ヘッドレスモードでのダウンロード方法
まずは必要なパッケージのインポート。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
次にオプションの生成。パス関係はそれぞれの環境に応じて適宜変更してください。--headless
オプションでヘッドレスモードを指定します。
opt = Options()
exec_path = '/usr/bin/chromedriver'
opt.binary_location = '/usr/bin/google-chrome'
## Windows の場合
#exec_path = 'C:\\bin\\chromedriver_win32\\chromedriver.exe'
#opt.binary_location = 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'
opt.add_argument('--headless')
次にダウンロードに関する詳細設定を生成します。download.default_directory
という保存先を指定する項目もありますが、これは後から別の方法で指定するので、ここでは不要です。ここでやっているのは簡単に言うと「保存先を毎回確認しない」ようにしつつ「選択した保存先が保持される」ようにしています。
prefs = {}
prefs['download.prompt_for_download'] = False
prefs['download.directory_upgrade'] = True
opt.add_experimental_option('prefs', prefs)
ここまでやってとりあえずChromeを起動します。
driver = webdriver.Chrome(chrome_options=opt, executable_path=exec_path)
そして本題のダウンロードの有効化です。ここではchromedriverに直接コマンドを投げます。download_path
はダウンロードファイルの保存先ディレクトリーの絶対パスです。Seleniumでダウンロードする場合は都度保存パスを指定することはできませんので、こうしてデフォルトのパスを指定します。残念ながら保存するファイル名も指定することができません。
driver.command_executor._commands["send_command"] = (
'POST',
'/session/$sessionId/chromium/send_command'
)
driver.execute(
"send_command",
params={
'cmd': 'Page.setDownloadBehavior',
'params': { 'behavior': 'allow', 'downloadPath': download_path }
}
)
これでヘッドレスモードでもファイルのダウンロードができるようになりました。