ファイルのダウンロードが終わるまで待機して、ダウンロードが完了したら次の操作を行うスクリプトを書こうとしたのですが、WebDriverにはダウンロード完了まで待ってくれる機能は用意されていません。
それを解決するのに、Watchdogを利用したら?みたいな記事もあったのですが、普通にWebDriverWaitでカスタム待機条件を作ればいいんじゃないかと思うので、そのように実装してみました。
なお、ダウンロード時にダイアログが出ないことが前提で話を進めていますので、Firefoxを使っている場合はプロファイルをいじる必要があると思います。
このあたりの記事を参考にすると幸せになれるかも……
http://tbpgr.hatenablog.com/entry/20140203/1391431135
https://developer.mozilla.org/ja/docs/Download_Manager_preferences
さて、非公式リファレンスにカスタム待機条件を実装する方法が書いてあったので、そちらを参考にしながら書いてみます。
https://kurozumi.github.io/selenium-python/waits.html
import os
class file_existed(object):
def __init__(self, path):
self.path = path
def __call__(self, driver):
# 指定したファイルパスが存在していたら待機を抜ける
if os.path.isfile(self.path):
return driver
else:
return False
どうも、一定期間ごとに__call__
が呼ばれるみたいです。引数driverにはwebdriverオブジェクトが渡されます。指定した条件に合致して待機から抜けるときにはdriverを返して、条件に合致せず、まだ待機する場合はFalseを返すように実装すれば動きます。
先程作ったクラスの使い方は以下のとおりです。
import os
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import custom_expected_conditions
# WebDriverWaitにはdriverと最大待機時間(秒)を渡す
WebDriverWait(driver, 10).until(
custom_expected_conditions.file_existed(FILE_DIR + os.sep + "filename.hoge")
)
なお、__init__
は__call__
で使う値を格納するときぐらいにしか使わないので、__call__
さえしっかり実装されていれば動くみたいです。
ですので、以下のようなてきとう実装でも動きます。
import random
class itsuka_nukeru(object):
def __init__(self):
pass
def __call__(self, driver):
if random.randint(1, 10) > 5:
return driver
else:
return False
driverとFalseさえ返せれば、副作用盛りだくさんなクラスを作ったってWebDriverさんには怒られないですぜ!!まぁレビュアー様はどうしようもないので付け届けでも送っとけばいいんじゃないですかね( ゚Д゚)y─┛~~