[Scrapy]複数spiderを実行する際の実行可否判断の注意点
本記事は SimpleForm Advent Calendar 2024 の 18 日目の記事です。
シンプルフォーム株式会社、新卒の中村です。
弊社ではネット上から法人の情報収集するため多くのクローラを作成しており、
そのほとんどにScrapyを使用しております。
入社後初めて書いたpythonコードがscrapyを使用したクローラだったのですがその中で、
Scrapyを用いた複数spiderの外部実行において、ECSタスクが正常終了しない問題に直面しました。本記事ではその原因とリファクタリングによる解決策を共有します。
対象読者
・Scrapyで複数のspiderを作成し、効率的に運用したい方
・複数のspiderを外部スクリプトで制御したい方
・ECSタスクの実行後に正常終了しないエラーで困っている方
Scrapyでspiderを複数作成したい場合
spiderを複数作成することはある程度一般的だと思いますが、
筆者がつまずいたケースが少し特殊だったので状況を事前に記載します。
- 集めたい情報があるが、情報を公表しているサイトが複数ある
- 情報の公表方法はpdf,csvなどサイトでバラバラ
- 公表されている項目もサイトでバラバラ
- クローラを作成し、AWS上で1つのECSタスクとして定期実行したい。
- 情報の更新頻度がサイトで異り、収集頻度を揃えるため、
サイト毎にDBを確認して実行の可否を判断したい
複数spiderの外部実行方法
spiderの外部実行の方法は、
公式ドキュメントやすでにある記事で記載されておりますので省略させて頂きます。
私がコードを書く際に参考にした記事を以下に乗せておきますので、
気になる方は以下を参考にしてください。
公式ドキュメント
直列実行の方法
最初に考えた設計
初めての設計だった為、この記事を読んでいる方からするとツッコミどころ満載かもしれませんが、
当初実装した際の設計を示します。
- spiderをサイトの分だけ作成(各サイト毎に専用の処理を書く)
- 共通する処理はpipelinesで行う
・DBとの接続
・URLが有効か確認
・公表資料のカラムに変化がないか - 各spiderを1つのファイルから外部実行する
起きた問題
・ECSタスクとして定期実行したところ、2回目の実行からタスクが正常終了しない。
・ログを確認すると、maybeDeferred(self.engine.stop)のエラーが出ている
・(DBにデータは問題なく入っている)
起きていたこと
spiderを外部実行した際、pipelinesの初期化(初期設定)の部分で書いた実行可否の判断の部分で
実行しないと判断した場合にclose_spiderを呼び出していた。
pipelinesの初期化の部分では、未だscrapyの動作を制御するengineは起動していないためclose_spiderを呼び出すことで、動いていないengineに対してstopを求めていた結果エラーが起きていた。
リファクタリング
上記の問題を解決する方法で思いついたのは以下の2点です。
・適切にspiderの実行を終了できるように、カスタムエラークラスを作成する
・pipelinesで実行可否の判断をやめる
カスタムエラークラスを作成するほうがリファクタリングの工数が少なく簡単に実装できますが、
事前に実行可否の判断を行う処理を行い実行するspiderのみを実行とするほうが、
コードの可読性や保守性などが高まるためpipelinesで実行可否の判断をやめるという判断をしました。
まとめ
pipelinesはspider全てに適用でき、非常に便利ですが、Scrapyで複数のspiderを外部実行する際には、pipelinesに過度に依存するのではなく、事前に実行可否を判断する設計を採用することで、エラーを未然に防げます。また、カスタムエラークラスや外部制御スクリプトを組み合わせることで、運用効率と保守性を高めることができます。ぜひご参考ください!
終わりに
いかがだったでしょうか。
あまり同じ問題に直面する方は少ないかもしれませんが、同じような状況で悩んでいる方の参考になれば幸いです。
サンプルコードなどがなく分かりづらかったらすみません。
ここまでご一読頂きありがとうございました。
また明日以降も SimpleForm Advent Calendar 2024続きますのでお楽しみに!
リアルタイム法人調査システム「SimpleCheck」を開発・運営するシンプルフォーム株式会社の開発チームのメンバーが、日々の開発で得た知見や試してみた技術などについて発信していきます。 Publication 運用への移行前の記事は zenn.dev/simpleform からご覧ください。
Discussion