Scrapy爬虫yield新Request未执行、parse方法仅调用一次问题
问题原因梳理
- 直接修改私有属性
_cb_kwargs无效:Scrapy 不允许用户直接修改以下划线开头的内部属性,你给_cb_kwargs赋值的操作会被内部逻辑覆盖,轻则参数丢失,重则直接导致请求被丢弃。 - 跨域请求被过滤:你配置的
allowed_domains = ['some_domain'],后续yield的https://jsonplaceholder.typicode.com/posts域名不在允许列表中,会被Scrapy的OffsiteMiddleware直接过滤,不会执行请求。 - 重复请求被过滤:Scrapy默认开启重复请求过滤机制,你两次生成的curl请求地址、参数完全一致的话,第二次请求会被判定为重复请求直接过滤,不会触发回调。
- 未显式指定回调:
from_curl方法生成的请求默认回调是parse,但如果curl命令解析异常可能会导致回调丢失,建议显式指定callback参数。
修复后的正确代码
curl_command = "curl blah blah" class MySpider(scrapy.Spider): name = 'myspider' # 添加所有用到的域名,调试阶段也可以直接注释掉这行关闭域过滤 allowed_domains = ['some_domain', 'jsonplaceholder.typicode.com'] start_urls = ['someurl', ] postal_codes = ['some_postal_code', ] def start_requests(self): for postal_code in self.postal_codes: # 构造请求时直接指定cb_kwargs、callback,不要修改私有属性 curl_req = scrapy.Request.from_curl( curl_command=curl_command, callback=self.parse, cb_kwargs={'page': 0}, # 调试阶段可加dont_filter=True关闭重复过滤,确认逻辑正常后按需移除 dont_filter=True ) yield curl_req def parse(self, response, **kwargs): cur_page = kwargs.get('page', 1) logging.info("Doing some logic") num_pages = do_some_logic() yield mySpiderItem if cur_page < num_pages: logging.info("New Request") curl_req = scrapy.Request.from_curl( curl_command=curl_command, callback=self.parse, cb_kwargs={'page': cur_page + 1}, dont_filter=True ) yield curl_req yield scrapy.Request( url="https://jsonplaceholder.typicode.com/posts", callback=self.parse # 需要自定义处理逻辑的话替换为其他回调函数即可 )
额外排查建议
- 把
settings.py中的日志级别调整为LOG_LEVEL = 'DEBUG',可以看到请求被过滤的具体原因,快速定位是重复过滤还是跨域过滤问题 - 确认
do_some_logic()返回的num_pages数值确实大于1,否则分页逻辑本身就不会触发
内容的提问来源于stack exchange,提问作者Danial
相关产品推荐
相关产品推荐

