はじめに
日常的にやってる作業を自動化するためにSeleniumを使っているわけだけど、どうでもいいことで無駄なハマり方をしたのでメモしておく。基本的にChrome Driverしか使ってないので他のブラウザの挙動は知らない。
画面外にあるボタンをクリックする
「要素がクリックできる状態になったらクリックする」というコードを最初適当に書いていたけれど、それだとエラーが出てクリックできなかったので、なぜかなーと思っていた。 たとえばこういう感じでコードを書いて実行すると
button_path = '//path/to/xpath' WebDriverWait(driver, 10).until( expected_conditions.elements_to_be_clickable( (By.XPATH, button_path) ) ) button = driver.find_element_by_xpath(button_path) button.click()
次のようなエラーが出ていた。
Traceback (most recent call last): ... selenium.common.exceptions.WebDriverException: Message: unknown error: Element is not clickable at point (61, 6703) (Session info: chrome=61.0.3163.100) (Driver info: chromedriver=2.30.477690 (c53f4ad87510ee97b5c3425a14c0e79780cdf262),platform=Mac OS X 10.12.6 x86_64)
viewport外に要素がある場合にこういう挙動になる模様。ActionChainsで対応できるかなと思って次のようなコードに変更。
button = driver.find_element_by_xpath(button_path) actions = ActionChains(driver) actions.move_to_element(button) actions.click() actions.perform()
エラーは出なくなったけどダウンロード部分がうまくいかない。
ダウンロード用の設定と画面の調整
Chromeの起動オプションの変更
SeleniumでのChrome起動時にオプションを追加してダウンロードの際のプロンプトなどを滅殺する。
options = selenium.webdriver.ChromeOptions() download_dir = os.path.dirname(__file__) options.add_experimental_option("prefs", { "download.default_directory": download_dir, "download.prompt_for_download": False, "download.directory_upgrade": True }) driver = selenium.webdriver.Chrome(chrome_options=options)
画面を強制的にスクロールする
ActionChains#move_to_element はマウスをそこまで持ってってくれるだけで画面のスクロールをしてくれないので(どうもviewport内のクリックでしかダウンロードイベントが発生しない)、仕方なくJavaScriptを無理やり実行して動かす。
driver.execute_script("arguments[0].scrollIntoView()", button)