Scrapy中parse_cat函数else分支不触发的问题排查及可行性咨询
问题解答
核心错误原因
- 第一个错误:
response.css()返回的是SelectorList类型,哪怕没有匹配到任何元素,也永远不会等于None,所以你的if search_prod is not None判断永远为真,else分支完全不会触发。正确的判断方式是直接判断if search_prod:,空的SelectorList在布尔判断里会返回False。 - 第二个错误:你在else分支里发起的请求url是当前
parse_cat处理的分类页url,但是回调设置成了parse_sub_cat,parse_sub_cat的逻辑是提取子分类导航链接,用分类页的响应去跑子分类页的解析逻辑,完全匹配不到对应的XPath规则,不可能得到预期结果。 - 第三个错误:Scrapy默认开启请求去重,你重复请求同一个url会被自动过滤掉,哪怕逻辑对了请求也发不出去,需要加
dont_filter=True参数才能强制发起请求。 - 额外语法问题:你粘贴的代码没有遵守Python的缩进规则,函数体没有缩进会直接触发语法报错;同时变量名
ulr_product拼写错误,后续调用也会出现异常。
需求实现方案
你的需求完全可以实现,如果你要的效果是「当前分类页没有匹配到商品时,重试当前分类页请求」,修正后代码如下:
import scrapy def parse_sub_cat(self, response): # 修正缩进 for i in response.xpath('//a[@data-track-action="CategoryOverviewNavigation"]'): goods_url = response.urljoin(i.xpath("./@href").get()) product_parent = i.xpath("./text()").get() yield response.follow( url=goods_url, callback=self.parse_cat, # 新增重试次数字段,避免无限循环 cb_kwargs=dict(product_parent=product_parent, retry_count=0) ) def parse_cat(self, response, **cb_kwargs): # 修正缩进 search_prod = response.css('article.m-grid-tile').css('div.m-grid-tile--image') # 修正判断逻辑 if search_prod: for i in search_prod: # 修正变量名拼写 url_product = response.urljoin(i.css('a::attr("href")').get()) cb_kwargs['model'] = i.css('a::attr("aria-label")').get() yield response.follow( url=url_product, callback=self.parse_product, cb_kwargs=cb_kwargs ) else: retry_count = cb_kwargs.get('retry_count', 0) # 最多重试3次,避免页面本身无商品时进入死循环 if retry_count < 3: cb_kwargs['retry_count'] = retry_count + 1 yield scrapy.Request( url=response.url, callback=self.parse_cat, cb_kwargs=cb_kwargs, # 跳过请求去重 dont_filter=True )
如果你确实需要回退到上一级子分类列表页,只需要在parse_sub_cat跳转的时候把上级页面的url也通过cb_kwargs传下来,else分支里请求上级页面的url即可。
内容的提问来源于stack exchange,提问作者user16993750
相关产品推荐
相关产品推荐

