Scrapy无法爬取下一页,仅能获取第一页结果的问题解决
Scrapy 无法爬取后续分页问题的修复方案
现有代码的核心问题
- 回调职责混乱:
parse方法同时承担搜索结果列表页解析、分页跳转、商家详情页解析三类完全独立的逻辑。当爬虫跟随商家链接跳转到详情页时,会在详情页DOM中错误执行列表页的选择器匹配、分页查找逻辑,打乱全流程爬取节奏。 - 选择器作用域错误:遍历每个商家数据块时,
avg_rating字段直接从全局响应页面取值,未绑定到当前循环的单个商家节点下,导致所有条目拿到的都是页面第一个匹配到的评分,和对应商家不匹配。 - 分页逻辑存在死循环风险:直接对选择器提取结果做
urljoin拼接,当选择器未匹配到内容时,extract_first()返回None,response.urljoin(None)会直接返回当前页面URL,导致if next_page is not None判断永远成立,爬虫会在同一个页面无限重复请求,根本无法正常跳转到下一页。 - URL格式错误:初始URL中带了HTML转义字符
&,实际请求时会导致参数识别错误。
修复后可实现全分页爬取的代码实现
import scrapy class QuoteSpider(scrapy.Spider): name = 'quotes' base_url = 'https://www.yell.com' start_urls = [ 'https://www.yell.com/ucs/UcsSearchAction.do?scrambleSeed=770796459&keywords=hospitals&location=united+kingdom' ] def parse(self, response): # parse方法仅负责列表页逻辑:提取当前页所有商家条目、处理分页跳转 all_data = response.css('div.row.businessCapsule--mainRow') for data in all_data: title = data.css('.text-h2::text').get(default='').strip() business_url = data.css('a.businessCapsule--title::attr(href)').get() avg_rating = data.css('span.starRating--average::text').get(default='') final_url = self.base_url + business_url # 跳转到商家详情页时,指定专门的详情解析回调,避免和列表页逻辑混用 yield response.follow(final_url, callback=self.parse_detail) # 直接输出列表页可获取的字段 yield { 'Title': title, 'Title Url': final_url, 'Average Rating': avg_rating } # 分页逻辑仅在列表页执行 next_href = response.css('a.pagination--next::attr(href)').extract_first() # 先校验是否匹配到有效下一页链接,再做URL拼接,避免无限循环 if next_href: next_page = response.urljoin(next_href) yield response.follow(next_page, callback=self.parse) def parse_detail(self, response): # 专门处理商家详情页的解析逻辑,可在此处补充详情页需要提取的字段 pass
优化注意事项
- 不同页面的解析逻辑必须拆分到独立的回调方法中,避免单个方法承担多场景逻辑引发的流程混乱。
- 单值字段提取优先使用
.get()方法,可通过default参数设置匹配失败时的返回值,避免程序因选择器匹配不到内容抛出异常。 - 分页跳转前必须先校验选择器是否匹配到了有效链接,不能直接对
None做URL拼接。 - 列表页能直接获取的字段,不需要额外发请求跳转详情页时,直接在列表页解析环节提取即可,减少无意义的请求量。
内容的提问来源于stack exchange,提问作者lonewolf_7
相关产品推荐
相关产品推荐

