为何Scrapy在循环未完成时关闭我的爬虫?
爬虫中断循环的原因及解决方法
核心原因:Scrapy默认URL去重机制拦截了重复请求
你每次请求的都是同一个URL https://api.ipify.org/,Scrapy默认启用的URL去重功能(由DUPEFILTER_CLASS控制,默认实现为scrapy.dupefilters.RFPDupeFilter)会自动过滤重复的请求。第一次请求完成后,后续yield的相同URL请求会被直接丢弃,爬虫没有待处理任务就会直接关闭。
次要排查点:代理中间件有效性
如果你的代理地址proxy_ip:proxy_port无效或无法正常连接,也可能导致请求失败,但从日志来看没有报错信息,该可能性较低。可以在代理中间件中添加日志,确认代理是否被正确设置到请求的meta中:
def process_request(self, request, spider): if spider.use_proxy: request.meta['proxy'] = 'proxy_ip:proxy_port' spider.logger.info(f"Proxy set for request: {request.meta['proxy']}") return None
解决办法
方法1:禁用当前爬虫的去重功能
在Spider类中添加custom_settings,全局关闭去重:
class IpSpider(scrapy.Spider): name = "ip" n = 0 use_proxy = True custom_settings = { 'DUPEFILTER_CLASS': 'scrapy.dupefilters.BaseDupeFilter', } # 原有start_requests和parse_ip代码不变
方法2:给请求添加随机参数绕过去重
在URL后拼接随机参数,让每次请求的URL唯一:
import random def parse_ip(self, response): if self.n < 10: self.n += 1 self.logger.info(self.n) self.logger.info(response.body) # 添加随机参数避免URL重复 url = f"https://api.ipify.org/?t={random.randint(1, 100000)}" yield scrapy.Request(url, callback=self.parse_ip)
方法3:针对单个请求禁用去重
在yield Request时设置dont_filter=True,仅让当前请求跳过去重:
yield scrapy.Request( "https://api.ipify.org/", callback=self.parse_ip, dont_filter=True )
内容的提问来源于stack exchange,提问作者samuel guedon
相关产品推荐
相关产品推荐

