chore: initialize lawyers crawler project
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
"""
|
||||
全局请求速率限制器
|
||||
确保代理每秒不超过5次请求
|
||||
"""
|
||||
import time
|
||||
import threading
|
||||
from collections import deque
|
||||
|
||||
|
||||
class RateLimiter:
|
||||
"""
|
||||
令牌桶算法实现的速率限制器
|
||||
"""
|
||||
def __init__(self, max_requests_per_second: int = 5):
|
||||
"""
|
||||
初始化速率限制器
|
||||
|
||||
Args:
|
||||
max_requests_per_second: 每秒最大请求数
|
||||
"""
|
||||
self.max_requests = max_requests_per_second
|
||||
self.requests = deque()
|
||||
self.lock = threading.RLock()
|
||||
|
||||
def acquire(self):
|
||||
"""
|
||||
获取请求权限,如果需要则等待
|
||||
"""
|
||||
with self.lock:
|
||||
now = time.time()
|
||||
|
||||
# 清理超过1秒的请求记录
|
||||
while self.requests and now - self.requests[0] >= 1.0:
|
||||
self.requests.popleft()
|
||||
|
||||
# 如果当前请求数已达上限,等待
|
||||
if len(self.requests) >= self.max_requests:
|
||||
# 计算需要等待的时间
|
||||
wait_time = 1.0 - (now - self.requests[0])
|
||||
if wait_time > 0:
|
||||
time.sleep(wait_time)
|
||||
return self.acquire() # 递归调用以重新检查
|
||||
|
||||
# 记录这次请求
|
||||
self.requests.append(now)
|
||||
|
||||
def can_make_request(self) -> bool:
|
||||
"""
|
||||
检查是否可以立即发起请求(非阻塞)
|
||||
"""
|
||||
with self.lock:
|
||||
now = time.time()
|
||||
|
||||
# 清理超过1秒的请求记录
|
||||
while self.requests and now - self.requests[0] >= 1.0:
|
||||
self.requests.popleft()
|
||||
|
||||
return len(self.requests) < self.max_requests
|
||||
|
||||
|
||||
# 全局速率限制器实例
|
||||
global_rate_limiter = RateLimiter(max_requests_per_second=5)
|
||||
|
||||
|
||||
def wait_for_request():
|
||||
"""
|
||||
等待直到可以发起请求
|
||||
"""
|
||||
global_rate_limiter.acquire()
|
||||
|
||||
|
||||
def can_request_now() -> bool:
|
||||
"""
|
||||
检查是否可以立即发起请求
|
||||
"""
|
||||
return global_rate_limiter.can_make_request()
|
||||
Reference in New Issue
Block a user