【Python Selenium】UnexpectedAlertPresentException:Chromeポップアップ操作

時計 2021.06.10 / 時計

【Python Selenium】UnexpectedAlertPresentException:Chromeポップアップ操作

本記事ではPythonのSeleniumを使った、ブラウザの自動操作を行っているときに発生する、UnexpectedAlertPresentExceptionについて解説していきます。

ChromeをSeleniumで自動化している際にUnexpectedAlertPresentExceptionが発生し、プログラムが途中で止まってしまうことが何度もありました。

この問題を解決するために使った方法を本記事でみなさんにご紹介していきたいと思います。

UnexpectedAlertPresentException発生時の操作

PythonのSeleniumモジュールで作成したブラウザ自動化ソフトを動かしているときにこのエラーが発生しました。

エラー内容は次のようになります。

selenium.common.exceptions.UnexpectedAlertPresentException: Alert Text:〇〇〇.
Message: unexpected alert open: {Alert text : 〇〇〇}

特定の情報をWebアプリケーションのフォームに入力し、「登録」ボタンを押した次の操作時にこのエラーが毎回発生していました。

UnexpectedAlertPresentExceptionの原因

UnexpectedAlertPresentExceptionはChromeのAlert(アラートモーダル)によって処理が止められたときに発生します。

Chromeのアラートモーダルとは次のようなポップアップです。

Chromeのポップアップするアラートモーダル

このようなAlertを表示するサイトは少なくありません。
そのためSeleniumでスクレイピングやブラウザの自動操作をする際には、このAlertを操作する知識は知っておく必要があります。

UnexpectedAlertPresentExceptionの解決には、Seleniumでalertオブジェクトを操作する必要があります。

UnexpectedAlertPresentExceptionの解決方法

すでに述べておりますが、UnexpectedAlertPresentExceptionを解決するにはSeleniumでalertオブジェクトを操作する必要があります。

いきなり結論に入りますが、Chromeのアラートが発生する可能性が高い操作の後に、以下のコードを記述することで、UnexpectedAlertPresentExceptionを発生させることなく、アラートを閉じることができます。

# サンプルコード
from selenium.webdriver.support.ui import WebDriverWait
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
chromedriver = 'chromedriver.exe'
driver = webdriver.Chrome(executable_path=chromedriver, chrome_options=options)
…
try:
  wait = WebDriverWait(driver, 30)
  wait.until(EC.alert_is_present())
  alert = driver.switch_to.alert
  print(alert.text)
  alert.accept()
except TimeoutException:
    print("アラートは発生しませんでした")
except Exception as e:
  print(e)

上記の操作について次項より詳しく解説していきます。

例外処理:tyr、except

Chromeのポップアップ(アラート)をキャッチするコードは例外処理(tryやexcept)の中に記載します。

例外処理とは、例外(エラー)が発生してもプログラムの処理を止めずに、プログラムの処理を継続させるための方法です。

例外処理については、以下の記事をご参照ください。

例外処理により、例外(エラー)が発生してもプログラムを止めることなく処理を続けることができます。

サンプルコードでは、もしChromeアラート(ポップアップ)が表示しなくても、例外処理でTimeoutExceptionをキャッチするので、プログラムが止まることを防いでいます。

アラート表示までの待機処理:wait.until(EC.alert_is_present())

サンプルコードでは、例外処理の中にChromeによるポップアップのアラートが表示されるまでの待機処理を記載しています。
ここでの待機処理は明示的な待機を使います。

明示的な待機とは、定義された特定の条件が満たされるまで待機することで、WebDriverのDOM要素が対象となります。
つまりDOM要素が、ある状態(条件)になるまで待機するということです。

Seleniumの待機処理(明示的な待機と暗黙的な待機)については以下の記事をご参照ください。

サンプルコードでは次のように待機処理を行っています。

wait = WebDriverWait(driver, 30)
wait.until(EC.alert_is_present())

WebDriverWait()の第二引数にはタイムアウト時間を指定し、until()の引数にはEC(expected_conditions)のメソッドalert_is_presentを指定します。

WebDriverWait(driver, 待機する秒数).until(EC.メソッド)

Alert_is_presentを指定することで、アラートが表示するまで待機するようになります。

タイムアウト時間を超えたら、TimeoutExceptionが発生するので、例外処理のexceptでキャッチされます。

ここで紹介したWebDriverWait()とEC(expected_conditions)を使用するには、以下のようにインポートしておく必要があります。

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

アラートモーダルへ作業ウィンドウの移動:switch_to.alert

表示されたアラートポップアップ(アラートモーダル)をSeleniumで操作できるようにするため、switch_to.alertを使ってalertオブジェクトを取得します。

alert = driver.switch_to.alert

このalertオブジェクトからアラートモーダルのテキストや閉じる操作などを行えます。

アラートモーダルのテキストを取得

取得したalertオブジェクトに.textを使うことでアラートモーダルのテキストを取得できます。

alert.text

アラートモーダルを閉じる:alert.accept()

Chromeにポップアップで表示されたアラートモーダルを閉じる場合は、alertオブジェクトに対してaccept()を使って閉じることができます。

alert.accept()

confirmの場合は、dismiss()でキャンセルを押せます。

alert.dismiss()

まとめ

本記事「【Python Selenium】UnexpectedAlertPresentException:Chromeポップアップ操作」はいかがでしたか。

このUnexpectedAlertPresentException 以外にも、Seleniumで自動化をしていると、たくさんの思わぬエラーに遭遇します。

本サイトでは様々なケースのエラー解決を紹介していますので、ぜひ参考にしてください。