Puppeteerで特定要素の値が変わるまでウェイトを掛ける

4/5 - (2 votes)

業務で本格的にPuppeteerにて処理の自動化を実装していますが、時々問題になるのが「ウェブサービス側の処理が重くて、タイムアウトする」という症状。直近でぶつかったのは、SalesforceのTeamSpiritにて特定のレポートをダウンロードするシーンにて、クエリが重くなかなか処理が終わらず、待機してるPuppeteerがタイムアウトで処理を中断してしまう(特定の要素がその処理が終わらないと有効にならない為)。

幸い、TeamSpiritの場合、クエリの処理中はIDがStatusの項目があるので、コレを基準に処理が終わるまで無限ループで待機させる事でエラーを回避することが出来ました。今回はこの特定要素の値を元に無限ループでウェイトを掛ける方法を作ってみました。

今回使用するライブラリ

今回のダウンロード上の問題点

今回対象にしてるTeamSpiritは、様々な勤怠レポートを作成しデータをCSVでダウンロードすることが出来ます。しかし、作成するレポートによっては以下のような問題が含まれているため、Puppeteerで自動ダウンロードを実装する場合、時々エラーが発生して止まるケースがあります。

  • レポートの処理中はIDがstatusの要素内の文字列が「処理中」となっている
  • 処理中が完了やその他の表記に変わるまで、期間条件の開始と終了のテキストボックスが使えない(値を入れようとするとエラーとなる)
  • ページのロードが終わった段階で完了表記になっていないとNGなので、await page.waitForNavigation({ waitUntil: “networkidle2” });などでは、対処しきれない
  • 開始日のtbody #colDt_sの要素が完了前に入れようとしてエラーが発生して止まってしまう

コンソールに表示されるエラーとしては、以下のようなものが表示されます。

図:レポート生成状況がポイント

コードと解説

ソースコード

解説

  • 対象のページの読み込みが完了したら、まずはIDがstatusの要素内の文字列を取得し、checkwordに格納する
  • Whileループにてcheckwordの値が処理中の場合は無限ループとしておく
  • 処理中であった場合には、page.waitForTimeoutにて2秒間意図的にウェイトを掛ける
  • 再度、冒頭と同じくIDがStatusの要素内の文字列を取得し、checkwordに格納する
  • checkwordの値が「処理中」でなくなったら処理を抜けて、開始日のテキストボックスに日付を入れる処理へ移る
  • 現在はこのコードのおかげでとりあえず、完了するまできちんと待ってくれるので、ストップすることはありません。

上記のコードではページがネットワーク不良で止まった場合に備えて、page.reloadを含めていますが、この処理は今回のテーマとは別の問題の対処用です。

page.waitForがDeprecatedな件

ウェブを見ていると、意図的に指定秒数でウェイトを掛ける場合には、page.waitFor(3000)といった形でウェイトを掛けるといった表記がありますが、現在すでにこのメソッドはDeprecatedになっており使えません。現在は、page.waitForTimeout(3000);に置き換えて、利用する事になります。

単純に置き換えるだけでOKなので、今後はこのメソッドを使います。

尚、本件に関するIssueについては、こちらのエントリーにて記述されているので、参照してみてください。

関連リンク

共有してみる:

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。