Scrapy:如何在发起Request前等待时长以规避HTTP 429错误?
解决Scrapy子请求快速触发导致的429错误问题
1. 确认DOWNLOAD_DELAY的正确配置
首先确保你在settings.py中正确设置了延迟,同时限制单域名并发请求数,避免同时发起多个请求:
DOWNLOAD_DELAY = 3.0 # 限制同一域名下同时仅发起1个请求,保证延迟生效 CONCURRENT_REQUESTS_PER_DOMAIN = 1
如果CONCURRENT_REQUESTS_PER_DOMAIN大于1,即使设置了DOWNLOAD_DELAY,Scrapy仍会同时发起多个请求,短时间内请求量依旧会触发网站的429限制。
2. 给每个子请求手动添加延迟
如果配置层面的延迟不生效,可以在生成子请求时,通过延迟提交的方式确保每个请求间隔指定时间:
先导入所需模块:
from twisted.internet import reactor from scrapy.utils.defer import deferLater
修改你的parse方法:
def parse(self, response): print(response.request.headers['User-Agent']) for index, info in enumerate(response.css('div.infolist')): item = MasterdataScraperItem() info_url = BASE_URL + info.css('a::attr(href)').get() print('Subpage: ' + info_url) item['name'] = info.css('img::attr(alt)').get() # 按顺序延迟发送请求,每个间隔3秒 yield deferLater(reactor, 3 * index, lambda url=info_url, item=item: scrapy.Request( url, callback=self.parse_info, meta={'item': item} ))
这种方式会让第一个请求立即发送,第二个延迟3秒,第三个延迟6秒,以此类推,严格保证子请求的间隔时间。
3. 自定义下载中间件控制请求间隔
编写一个下载中间件,在每次请求发送前强制等待指定时长:
在项目的middlewares.py中添加如下代码:
import time from scrapy import signals class DelayMiddleware: def __init__(self, delay): self.delay = delay self.last_request_time = 0 @classmethod def from_crawler(cls, crawler): delay = crawler.settings.getfloat('CUSTOM_DOWNLOAD_DELAY', 3.0) return cls(delay) def process_request(self, request, spider): now = time.time() # 计算需要等待的时间,确保两次请求间隔达标 if now - self.last_request_time < self.delay: time.sleep(self.delay - (now - self.last_request_time)) self.last_request_time = time.time() return None
然后在settings.py中启用该中间件并设置延迟:
DOWNLOADER_MIDDLEWARES = { '你的项目名.middlewares.DelayMiddleware': 543, } # 自定义延迟时间,单位为秒 CUSTOM_DOWNLOAD_DELAY = 3.0
这个中间件会全局控制所有请求的发送间隔,避免短时间内请求量过高。
内容的提问来源于stack exchange,提问作者csphmay
相关产品推荐
相关产品推荐

