📎

[Python] Selenium: execute_async_script()のメモ

2022/06/23に公開

はじめに

Seleniumのexecute_async_script()が分かりづらかったのでメモ

環境

Python 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit (AMD64)]
selenium 4.2.0
geckodriver 0.31.0 (b617178ef491 2022-04-06 11:57 +0000)

コード

execute_async_script()は、Seleniumが呼び出したJavaScriptの引数の最後にコールバック関数を自動で渡す。
それを任意のタイミングで実行する必要がある。
コールバック関数が終了した時点でPythonに制御が戻る。

以下の例では、実質的にexecute_script()と同じ動作になる。

import datetime
from selenium import webdriver
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium.webdriver.firefox.service import Service as FirefoxService

def getNowTime():
  return datetime.datetime.now().strftime('%H:%M:%S.%f')[:-3]

def printTime(string):
  print(f"{getNowTime()}: {string}")

def getDriver():
  options = FirefoxOptions()
  options.add_argument('-safe-mode')
  options.set_preference("browser.cache.disk.enable", False)
  service = FirefoxService(executable_path=const.ExecutablePath, log_path=os.path.devnull)
  driver = webdriver.Firefox(service=service, options=options)
  driver.set_page_load_timeout(300)
  return driver

driver = getDriver()
driver.get(r"file:///D:\test.html")

printTime("start")
result = driver.execute_async_script("""\
console.log('abc');
arguments[arguments.length-1]("ok");
""")
print(result)
printTime("end")

もう少し非同期らしい例としては以下のようなものがある。
この場合は、JavaScriptを実行してすぐにPythonに制御が戻り、10秒後にコンソールログが実行される。

printTime("start")
result = driver.execute_async_script("""\
setTimeout(() => {
  console.log('abc');
  }, 10000);
  arguments[arguments.length-1]("ok");
""")
printTime(result)
printTime("end")

蛇足としては、以下の様にすると、10秒待つ事になる。

printTime("start")
result = driver.execute_async_script("""\
setTimeout(() => {
  console.log('abc');
  arguments[arguments.length-1]("ok");
  }, 10000);
""")
printTime(result)
printTime("end")

Discussion