2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Selenium ChromeDriverで60秒のタイムアウトが発生する

Last updated at Posted at 2021-07-28

1.ChromeDriverのタイムアウト

SeleniumでChromeを自動操作している時に、ファイルアップロード等で60秒以上かかる場合に、タイムアウトが発生します。
これを回避するには、new ChromeDriver()で第3引数(TimeSpan)にタイムアウト時間を指定します。
海外のサイトで--no-sandboxオプションをつけたらうまくいったという話も見かけましたが、私はうまくいきませんでした。
アップロードの場合には、併せてページロードタイムアウトも設定が必要です。
C#で確認しています。

2.セッション0で実行時にnew ChromeDriver()でタイムアウトまで待たされて例外が発生することがある

Windowsサービス(セッション0で動作)からセッション0にC# exeを起動し、そのexeでnew ChromeDriver()を行うと、数回~数十回に一度、上記のタイムアウトまで待たされてから例外が発生します。
new ChromeDriver()の第3引数タイムアウトの指定の有無に関わらず発生します。
ChromeとChromeDriverのバージョン91と92で確認しています。
サービスをLocalSYSTEMで動作させた場合と、Administratorsに所属するユーザーで動作させた場合のどちらでも発生します。
LocalSYSTEMで動作しているサービスからCreateProcessしてexeをLocalSYSTEMで実行させた場合と、CreateProcessAsUserでAdministratorsに所属するユーザーで動作させた場合のどちらでも発生します。

HttpWebRequestのGetResponse()で例外と出力されるので、ChromeDriverとchromedriver.exeが通信できていないのではないかと推測。

サービスを経由しないでexeを実行した場合(セッション1)や、サービスからコンソールユーザーのセッション(セッション1)に起動した場合には100回実行しても発生しません。

画面表示なしで実行させるためにセッション0で実行させたいため、new ChromeDriver()が済んでいるexeをプールしてワーカープロセスとして利用するようにして回避しました。そのまま半常駐として動かすとメモリリークが怖いので、一定時間でリサイクルさせています。

画面表示なしにするためには、セッション1でChromeのheadlessモードを使用する手もありますが、ファイルのダウンロードが失敗するので使用していません。回避方法もあるようですが、未確認です。ログオンしていない状態で動かしたいのでheadlessモードは使用しません。

ただ、このタイムアウトが発生した場合なのか、chromedriver.exeとchrome.exe複数が残る場合があります。 ChromeDriver初期化を一度に1つしかしないようにして、ChromeDriver初期化前と初期化後のchromedriver.exeとchrome.exeのプロセスID一覧を取得して、タイムアウト発生時に増加した分のchromedriver.exeとchrome.exe複数をKILLするようにしました。 サービス側にKILL処理を入れたのですが、それだとサービス停止タイミングによってchromedriver.exeとchrome.exe複数が残る場合があるので、ワーカープロセス側にセマフォを導入し、最後のワーカープロセスの終了時にKILL処理を追加しました。それでもワーカープロセスの起動停止を短時間で繰り返すと半日でなぜかchromedriver.exeとchrome.exeが増えるので、ワーカープロセスの実行Windowsユーザーを2つにして 一定時間で起動ユーザーを変更し 、ユーザー1のワーカープロセスのみを実行しているはずなのにユーザー2のchromedriver.exeとchrome.exeが残っていたらKILLするようにしました。

KILLするプロセスはセッション0のもののみとし、セッション1以降のプロセスはKILLしないようにしています。

Chrome 93にしたら、セッション0の場合にPCによって上記動作だったり、new ChromeDriver()が全てタイムアウトになったりしました。Chromeを92に戻して、gpedit.mscを使用する公式手順で自動アップデートを無効にしました。

3.セッション0で実行時に?GoToUrl()が例外を返し続けることがある

4秒くらいかかって、例外が発生します。一度発生したらそのプロセスでは発生し続けるので、終了させて別プロセスを起動しています。
→「ChromeDriver初期化前と初期化後のchromedriver.exeとchrome.exeのプロセスID一覧を取得して、タイムアウト発生時に増加した分のchromedriver.exeとchrome.exe複数をKILLするようにしました。」が必要なchromedriver.exeとchrome.exeをKILLしていたっぽいです。これをなくすと安定しました。

4.セッション0で実行時に?ChromeDriverのメソッドがlocalhost:XXXXXに繋がらずに例外を返すことがある

PC環境によって、セッション0でも正常に動作し続けるPCと、例外が頻発するPCがあり、現在調査中です。例外の内容(覚えていないので後で追記します)から、ChromeDriverがchromedriver.exeに接続できなさそうです。例外が発生するとサイトからログアウトできなくなり、次回二重ログインとなってログインできず、困っています。
→これも上記のKILL処理を省いたら直りました。

WebDriverWaitのポーリング間隔(メソッドは後で追記します)を設定しましたが、変わらず。

localhostの名前解決に時間がかかっているのかと思い、hostsに 127.0.0.1 localhost を記述しましたが、変わらず。IPv6を無効化しても変わらず。netsh interface ipv6 set prefixpolicy でIPv4を優先させても変わらず。

例外発生時に新しいChromeDriverをnewして、既存のChromeのポートに接続して操作を続行できないか検討中です。短いテストプログラムで下記のコードは動作しました。
→念のため実装しましたが、いまのところ必要なさそうなのでコンフィグで殺しています。

.cs
ChromeDriver driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));

Dictionary<string, object> chromeOptions = (Dictionary<string, object>)driver.Capabilities["goog:chromeOptions"];
string debuggerAddress = (string)chromeOptions["debuggerAddress"];



ChromeOptions chromeOptions2 = new ChromeOptions();
chromeOptions2.DebuggerAddress = debuggerAddress ;
ChromeDriver driver2 = new ChromeDriver(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), chromeOptions2);
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?