私は現在、エラーをログに記録するか、成功した結果を保存するために、すべてのリクエストが適切に処理されるようにするために非常に重要なスクレイパー プロジェクトに取り組んでいます。私はすでに基本的なスパイダーを実装しており、リクエストの 99% を正常に処理できるようになりましたが、キャプチャ、50x、30x、または結果に十分なフィールドがないなどのエラーが発生する可能性があります (その後、別の Web サイトを試してみます不足しているフィールドを見つけます)。
最初は、解析コールバックで例外を発生させ、それらをすべて errback で処理する方が「論理的」であると考えていました。これにより、コードが読みやすくなります。しかし、errback が 200 以外の応答ステータスなどのエラーをダウンローダ モジュールでしかトラップできないことを確認しようとしました。コールバックで自己実装の ParseError を発生させた場合、スパイダーはそれを発生させて停止します。
解析リクエストをコールバックで直接処理する必要があるとしても、コールバックですぐにクリーンな方法でリクエストを再試行する方法がわかりません。別のリクエストを送信したり、リクエストヘッダーを変更したりするために、別のプロキシを含める必要があるかもしれません。
私はスクレイピーに比較的慣れていないことを認めますが、何日も行ったり来たりしてみましたが、まだこれを機能させることができません... SOに関するすべての質問をチェックしましたが、誰も一致しませんでした。
更新:これは非常に複雑な質問になる可能性があることを認識しているため、次の擬似コードでシナリオを説明しようとしています。これが役立つことを願っています:
from scraper.myexceptions import *
def parseRound1(self, response):
.... some parsing routines ...
if something wrong happened:
# this causes the spider raises a SpiderException and stops
raise CaptchaError
...
if no enough fields scraped:
raise ParseError(task, "no enough fields")
else:
return items
def parseRound2(self, response):
...some other parsing routines...
def errHandler(self, failure):
# how to trap all the exceptions?
r = failure.trap()
# cannot trap ParseError here
if r == CaptchaError:
# how to enqueue the original request here?
retry
elif r == ParseError:
if raised from parseRound1:
new request for Round2
else:
some other retry mechanism
elif r == HTTPError:
ignore or retry