はじめに
スクレイピングを行う際のマナーとして、各リクエスト間最低1秒は開けようというものがありますね。
そんなときはtime.sleep(1)
がデフォだと思いますが、その他の処理を行うと1秒+$\alpha$の時間が毎ループかかってチリツモで結構な時間ロスになります。
無駄な時間ロスはなるべく少ないほうがいいに決まってますので、ちゃんと等間隔で実行したいですね。
また、それ以外にも等間隔で処理を行いたい場面は多いと思います。
実装も使用も楽な解決策
こんな関数を用意すれば簡単に実現できます。
import time
def wait(wait_time=1, delay=1e-3):
while (time.time() - wait.time) < wait_time:
time.sleep(delay)
wait.time = time.time()
return
wait.time = time.time()
解説
あまり使用しているところは見ませんが、関数にも固有の変数を定義することが可能です(上記プログラム中のwait.time
)。
ここに前回呼び出し時の時間を記録しておくことで、そこからの時間差を利用することができます。
あとは指定の時間が過ぎたら処理を返してあげるだけです。
また、wait.time = time.time()
などと関数の外側から基準時間を設定することもできます。
使用例
import requests
url = "https://***.com/******/****/?p={}"
wait.time = time.time()
for i in range(1, 101):
wait(1)
resp = requests.get(url.format(i))
# wait.time = time.time() # 本当はここで基準点を再設定したほうがよい
# .
# .
# .
一応テスト
wait.time = time.time()
t = time.time()
for i in range(3, 10):
time.sleep(2.71828) # 時間がかかる処理の代わり
wait(i)
print(time.time()-t)
out
3.000946283340454
7.001208782196045
12.001968383789062
18.002827167510986
25.003514051437378
33.00419735908508
42.00518202781677
注意
プログラムの内容を見れば自明ですが、間に挟まっている処理が設定した待ち時間より長い場合はタイミングはズレます。
そういう意味では、等間隔を管理する関数というより最低待ち時間を設定する関数と言ったほうが正確ですね。