ユーザーが検索値とキャプチャを入力する必要があるサイトをスクレイピングしようとしています。キャプチャ用の光学式文字認識(OCR)ルーチンがあり、これは約33%の時間成功します。キャプチャは常にアルファベットのテキストなので、OCR関数がアルファベット以外の文字を返した場合は、キャプチャをリロードしたいと思います。 「Word」というテキストを入手したら、検索フォームを送信します。
結果は同じページに戻り、フォームは新しい検索と新しいキャプチャの準備ができています。そのため、検索語句がなくなるまですすぎ、繰り返す必要があります。
最上位のアルゴリズムは次のとおりです。
CAPTCHAを取得するためにパイプラインを使用しようとしましたが、フォーム送信の値がありません。フレームワークを経由せずに画像をフェッチするだけの場合、urllibなどを使用すると、セッションのCookieが送信されないため、サーバーでのキャプチャ検証が失敗します。
これを行うための理想的なScrapyの方法は何ですか?
それはたくさんの解決策がある本当に深いトピックです。ただし、投稿で定義したロジックを適用する場合は、スクレイピー Downloader Middlewares を使用できます。
何かのようなもの:
class CaptchaMiddleware(object):
max_retries = 5
def process_response(request, response, spider):
if not request.meta.get('solve_captcha', False):
return response # only solve requests that are marked with meta key
catpcha = find_catpcha(response)
if not captcha: # it might not have captcha at all!
return response
solved = solve_captcha(captcha)
if solved:
response.meta['catpcha'] = captcha
response.meta['solved_catpcha'] = solved
return response
else:
# retry page for new captcha
# prevent endless loop
if request.meta.get('catpcha_retries', 0) == 5:
logging.warning('max retries for captcha reached for {}'.format(request.url))
raise IgnoreRequest
request.meta['dont_filter'] = True
request.meta['captcha_retries'] = request.meta.get('captcha_retries', 0) + 1
return request
この例では、すべての応答をインターセプトし、キャプチャを解決しようとします。失敗した場合は、新しいキャプチャのページを再試行し、成功した場合は、解決されたキャプチャ値を使用して応答にメタキーを追加します。
クモでは、次のように使用します。
class MySpider(scrapy.Spider):
def parse(self, response):
url = ''# url that requires captcha
yield Request(url, callback=self.parse_captchad, meta={'solve_captcha': True},
errback=self.parse_fail)
def parse_captchad(self, response):
solved = response['solved']
# do stuff
def parse_fail(self, response):
# failed to retrieve captcha in 5 tries :(
# do stuff