response.request.meta を変更しても変わるのは Python オブジェクトです。もう一度ダウンロードするには、スケジュールする別の Request を Scrapy に渡す必要があります。

callback が明示的に再試行を決めた GET では、Scrapy の公開リトライヘルパーが再試行の計数を新しいリクエストに引き継げます:

from scrapy.downloadermiddlewares.retry import get_retry_request

def retry_through(self, response, proxy_url):
    retry = get_retry_request(
        response.request,
        spider=self,
        reason='choose_another_proxy',
    )
    if retry is None:
        return None
    retry.meta['proxy'] = proxy_url
    retry.headers.pop('Proxy-Authorization', None)
    return retry

これは spider 用のヘルパーです。呼び出し側は、得られた Request が利用可能なときに返すか yield する必要があります。None は、適用される上限のもとでヘルパーがさらなる再試行を断ったことを意味します。

リトライヘルパーはリクエストをコピーし、再試行回数を更新し、再試行に適したスケジューラの挙動を提供します。同じ URL を通常の新しいリクエストとして yield すると、代わりに重複フィルタに当たる可能性があります。

有効な HttpProxyMiddleware が対応する プロキシ URL を使ってください。許可された公開 GET リクエストの再試行には、HTTP プロキシ一覧の認証不要の HTTP 候補が proxy_url を提供できます。以前に付けた proxy-authorization フィールドを消すことで、古い中継者のヘッダーをこの選択に持ち込まずに済みます。該当する場合は、新しいプロキシ URL から新しいアカウントをミドルウェアに導出させてください。

この callback レベルの選択は、RetryMiddleware が設定された失敗を自動処理する仕組みとは分けてください。どちらの層が再試行を持つかを決め、処理が二つの独立した予算を消費しないようにします。例は再生可能な GET 処理に関するものであり、任意の送信済みトランザクションの繰り返しが安全だという約束ではありません。

関連記事