RetryMiddleware

class scrapy.downloadermiddlewares.retry.RetryMiddleware
接続タイムアウトやHTTP 500エラーなどの一時的な問題が原因である可能性のある失敗した要求を再試行するミドルウェア。

class scrapy.downloadermiddlewares.retry.RetryMiddlewareを使えば、Scrapyは失敗したリクエストを再実行してくれる。

Request.meta の dont_retry キーがTrueに設定されている場合、リクエストはこのミドルウェアによって無視されます。

リトライさせない指示も可能。

ソースコードも比較的コンパクトで読みやすい。

Splashのエラー

If main results in an unhandled exception then Splash returns HTTP 400 response with an error message.

SplashでError Handlingされていないエラーはステータスコード400でエラーとなる。

RetryMiddlewareの設定

RetryMiddlewareで設定できる項目は以下。

1
2
3
4
RETRY_ENABLED = True
RETRY_TIMES = 2
# 400は含まれていない
RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429]

デフォルトではリトライするエラーコードの対象として400は含まれていない。
400を含めてリトライさせるにはRETRY_HTTP_CODESに追記する。

RetryMiddlewareの実行結果

実行時のログで有効なミドルウェアを確認

1
2
3
4
5
6
7
8
9
10
11
12
13
14
2021-05-04 10:35:18 [scrapy.middleware] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
'scrapy.downloadermiddlewares.retry.RetryMiddleware',
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware',
'scrapy_splash.SplashCookiesMiddleware',
'scrapy_splash.SplashMiddleware',
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware',
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
'scrapy.downloadermiddlewares.stats.DownloaderStats']

リトライされるとデバッグログで出力される

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2021-05-04 10:35:22 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET https://xxxx.xxxxxx.xxxxx/xxxxxxxxxxxxxxx via http://splash:8050/execute> (failed 1 times): 500 Internal Server Error
2021-05-04 10:35:23 [scrapy.downloadermiddlewares.retry] DEBUG: Retrying <GET https://xxxx.xxxxxx.xxxxx/xxxxxxxxxxxxxxx via http://splash:8050/execute> (failed 2 times): 500 Internal Server Error
2021-05-04 10:35:23 [scrapy.downloadermiddlewares.retry] ERROR: Gave up retrying <GET https://xxxx.xxxxxx.xxxxx/xxxxxxxxxxxxxxx via http://splash:8050/execute> (failed 3 times): 500 Internal Server Error
2021-05-04 10:35:23 [scrapy.core.engine] DEBUG: Crawled (500) <GET https://xxxx.xxxxxx.xxxxx/xxxxxxxxxxxxxxx via http://splash:8050/execute> (referer: None)
2021-05-04 10:35:23 [xxxxxxxxxxxxxxxxxx] WARNING: <twisted.python.failure.Failure scrapy.spidermiddlewares.httperror.HttpError: Ignoring non-200 response>
2021-05-04 10:35:23 [xxxxxxxxxxxxxxxxxx] ERROR: Splash HttpError on https://xxxx.xxxxxx.xxxxx/xxxxxxxxxxxxxxx

リトライした場合、統計情報の`retry/xxxxxx`に記録される。

``` log
2021-05-04 10:35:27 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 21246,
'downloader/request_count': 4,
'downloader/request_method_count/POST': 4,
'downloader/response_bytes': 337118,
'downloader/response_count': 4,
'downloader/response_status_count/200': 4,
'elapsed_time_seconds': 8.372411,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2021, 5, 4, 1, 35, 26, 930365),
'log_count/DEBUG': 6,
'log_count/ERROR': 2,
'log_count/INFO': 13,
'log_count/WARNING': 2,
'memusage/max': 66347008,
'memusage/startup': 66347008,
'request_depth_max': 1,
'response_received_count': 2,
'retry/count': 2,
'retry/max_reached': 1,
'retry/reason_count/500 Internal Server Error': 2,