フリーランチ食べたい

No Free Lunch in ML and Life. Pythonや機械学習のことを書きます。

【Selenium】 UnexpectedAlertPresentExceptionが出るケースとその対応

Seleniumで思わぬエラーが発生したのでメモとして残しておきます。

TL;DR

  • UnexpectedAlertPresentExceptionはalertに処理がブロックされているときに起きます。
  • seleniumのalertオブジェクトを操作することで解消します。

こんなケースで発生

自分の場合では、JSのコードを実行する処理でこのエラーが発生しました。

driver.get(url)
js = "console.log('hello');"
driver.execute_script(js)
# => UnexpectedAlertPresentException Error!

どういうエラーなのか

ドキュメントを参照すると、下のような記述があります。

https://seleniumhq.github.io/selenium/docs/api/py/common/selenium.common.exceptions.html?highlight=unexpectedalertpresentexception

Thrown when an unexpected alert is appeared. Usually raised when when an expected modal is blocking webdriver form executing any more commands.

アラートモーダルが何か処理をブロックしている場面で起こるようです。今回だとアラートモーダルがJSの実行がブロックしてしまっていたようです。 ※ ちなみにdocsではwhenが重なってしまっていますが、master repositoryを見に行ったら治ってました。

検証

とても簡単な検証ですが、アラートモーダルがJS実行をブロックする様子を見てみたいと思います。

f:id:mergyi:20190118232233g:plain
アラートモーダルが出ているとJSが実行できない

このように、アラートを消さないとJSは実行されません。

対応

下のようにalertオブジェクトからacceptを呼び出すとアラートモーダルで「OK」を押した動作と同じことになります。

alert = driver.switch_to_alert()
alert.accept()

さらに、「もしアラートが出ていたらOKを押してもう一度、本来のJSを実行したい」場合は下記のような実装になると思います。

while True:
    try:
        driver.execute_script("console.log('hello');")
    except UnexpectedAlertPresentException:
        alert = driver.switch_to_alert()
        alert.accept()
        print("Alert accepted")
    else:
        break

さいごに

以上、Seleniumネタでした。

関係ないですが、2月3日にPythonもくもく会をつくばで開催します!今回はまだ席が若干余っているのでもし興味ある方は是非ご参加ください〜。

tskubapy.connpass.com