Scrapyでクローリングをするときにダウンロード間隔をどうするべきかは悩ましい問題です。
クローリング対象のシステムの負荷を考えると、短すぎるダウンロード間隔は避けるべきです。
ですが、適切な間隔値は対象サイトごとに異なり、また時間帯によっても異なります。
そのため、サーバーのレスポンスタイムやレスポンスコードによってダウンロード間隔を動的に変えることが出来れば便利です。
Scrapyにはそのための機能であるAutoThrottle Extentionがあるため、これを利用してみます。
使い方
使い方はかなり簡単で、settings.pyに以下の設定を書くだけです。
AUTOTHROTTLE_ENABLED = True
あとはこれだけで自動的にダウンロード間隔を調整してくれます。
仕組み
さて、この拡張機能はどのように動作しているのでしょうか?
以降ではその仕組を説明していきます。
まずクローリング対象サイトに対して並列リクエストをしたい目標値 AUTOTHROTTLE_TARGET_CONCURRENCY
があり、1回のリクエストのダウンロード時間が latency
秒だとすると、以下の時間間隔でダウンロードを実行すればいいことになります。
latency / AUTOTHROTTLE_TARGET_CONCURRENCY
そして、最近のダウンロード処理のlatencyを使いながらこの値を常に計算し直すことでダウンロード速度が自動的に調整されます。
実際には現在の設定値と上記で計算した目標設定値の平均を次回のダウンロード間隔として使うことで急激な変化を防いでいます。
この方法は一見すると、対象サイトの並列リクエスト数を指定してリクエストしているだけな気もします。
ですが、その単に並列リクエスト数を指定する方法はエラー発生時にバースト的なリクエスト増加が発生する危険があります。
ステータスコード200以外のエラーレスポンスが返される時は、latencyが短くなることがしばしばあります。
そのようなケースではリクエスト頻度を落とすことで対象サーバーの負荷を減らすべきですが、単に並列リクエスト数を指定する方法ですと逆の動きをします。
AuthThrottleExtentionはエラーレスポンスのlatencyを無視し、正常レスポンスのレイテンシーのみでダウンロード間隔を決定するため、このような問題を起こしません。
他の設定値
基本的には AUTOTHROTTLE_ENABLED
の設定だけでいい感じにしてくれますが、他に設定できる値も紹介します。
AUTOTHROTTLE_START_DELAY
デフォルト: 5.0
ダウンロード間隔の初期値で単位は秒です。
AUTOTHROTTLE_MAX_DELAY
デフォルト: 60.0
ダウンロード間隔の最大値で単位は秒です。
AUTOTHROTTLE_TARGET_CONCURRENCY
デフォルト: 1.0
目標となる並列ダウンロード数です。
この値が大きくなるほどクローリング速度は上がりますが、対象のサーバーに負荷がかかるので注意が必要です。
また、この値はあくまで目標値でありこれ以上の並列度でリクエストを投げるケースもあるためその点も要注意です。
ハードリミットをかけたいときには、 CONCURRENT_REQUESTS_PER_DOMAIN
や CONCURRENT_REQUESTS_PER_IP
を使用しましょう。
AutoThrottleExtentionはそれらの設定値以上の並列度でリクエストをすることはありません。
AUTOTHROTTLE_DEBUG
デフォルト: False
Trueにするとダウンロード速度が変わっていく様子をログに出力します。