実装時にはWindowsに普通にPythonとVSCodeをインストールして開発を行っていたある日のこと。
私: ヨシ!完成。お客さん先のリポジトリにプルリクかけるぞー!
客: 動作確認ヨシ! ありがとうございます!!
客: 運用環境でしばらく動かしてるとエラーが起きます
そこらへんに転がっているChrome起動時のオプション引数は試したけどだめ!!
何をやってもだめ!!
そんな貴方におくる最果ての記事です。
環境による差異
- 私と相手方は動作確認時にWindowsで確認していた。
- 運用は Docker + Ubuntu の環境で動かしていた。
- RAMもSWAPも十分にあり実行中も空きがある
- 当初はDockerで動かしていなかったけれど運用コストがかさむため、いつのまにかDockerで動かしていた。
現象
- 最初のうちは正常に動作している。
- だんだん動作が重くなっていく。
- 実行時間がだいぶ経過するとランダムにエラーが発生する。
- エラーは様々
- ウェブページの読み込みが終わらずにエラー
- 取得対象要素がレンダリングされる前に取得しようとした
- クラッシュする
- Chromeと通信できなくてurllibからエラーが飛んでくる
原因
- Chromeが共有メモリを使用している。
- コンテナ環境における共有メモリのデフォルトサイズが64MBであり不足していた。
- 共有メモリを使用しないようにオプションを指定しても結局は使用されている...
解決方法 (最終手段)
そこらじゅうに書かれているChromeのオプション(引数)を追加するなどを試してもダメな場合の最終手段です。
OSの共有メモリ増やす
PCに自前でDocker入れている場合はこの手段が取れますが、
クラウド環境(Azure)のコンテナ環境は共有メモリサイズの変更は行えません...
Seleniumのタイムアウト時間を延ばす
重くなったChromeはfind_elementsに30秒以上かかることもあります。
(だから、タイムアウトがデフォルト値だと要素が見つからないと言われたりするんですね)
Requests + BeautifulSoup にリプレースする
スクレイピングロジックに限ってですが、意外とSeleniumからRequests + BeautifulSoupへのリプレースがしやすいです。
私の実績値ですが、なれた人が行えば500行ぐらいのロジックであれば半日ぐらいでリプレースできてしまいます。
結論
お客さん先の開発支援業務だったりすると、なかなか運用環境に関する情報が得られなかったりするので、なるようになるしかないというのが正直なところです。
実際、VPSなどの単純なVMで動かしてたところ、運用コストを抑えるためにDockerに移行したいとなる可能性もあります。
スクレイピングってバッチ処理みたいなものなので、動かしていない間もVMだとお金がもったいないのでコンテナで運用したい気持ちは分かるんですよね^^;
これを見た皆さんがスクレイピングプロジェクトのPMになってSeleniumを使おうとしたときに、この投稿を思い出してくれれば幸いです。