Scrapy翻页功能实现报错,求正确实现方向指引
解决Scrapy抓取商品+自动翻页的问题
看起来你在使用Scrapy的CrawlSpider时,遇到了商品链接抓取和翻页逻辑冲突的问题——要么抓不到商品,要么拿不到下一页链接。我来给你梳理两种可行的实现方案,分别适配不同的场景:
方案一:CrawlSpider+双Rule(适合页面结构简单的场景)
核心思路是分开定义两个Rule规则:一个专门抓取商品链接并交给parse_items处理,另一个专门跟进下一页链接,避免互相干扰。之前的问题大概率是你只用了一个LinkExtractor,没精准区分商品和翻页链接,导致下一页被误排除了。
完整代码示例:
from scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LinkExtractor from scrapy.item import Item, Field # 先定义商品数据结构 class ProductItem(Item): title = Field() price = Field() # 根据你的需求添加其他字段,比如描述、sku等 class UrlLinkSpider(CrawlSpider): name = "urllink" allowed_domains = ['url.com'] start_urls = ['https://url.com/your-start-page'] # 替换成你的起始页URL # 规则1:抓取所有商品链接,交给parse_items处理 product_rule = Rule( LinkExtractor( allow=r'/product/\d+' # 替换成商品链接的正则匹配规则,比如/product/12345 deny=r'page=' # 明确排除翻页链接,避免被误抓取 ), callback='parse_items', follow=False # 商品页不需要继续跟进内部链接 ) # 规则2:抓取下一页链接,自动跟进 next_page_rule = Rule( LinkExtractor( allow=r'page=\d+' # 替换成翻页链接的正则,比如?page=2 # 也可以用XPath精准定位下一页按钮,比如:restrict_xpaths=['//a[@class="next"]'] ), follow=True, callback=None # 翻页只需要跟进,不需要处理页面内容 ) # 把两个规则组合起来 rules = (product_rule, next_page_rule) def parse_items(self, response): item = ProductItem() # 这里根据目标页面的HTML结构提取数据,示例用XPath item['title'] = response.xpath('//h1[@class="product-title"]/text()').get(default='').strip() item['price'] = response.xpath('//span[@class="product-price"]/text()').get(default='').strip() # 提取其他字段... # 用yield返回item,Scrapy可以自动帮你导出为JSON(推荐用命令行参数:scrapy crawl urllink -o products.json) yield item
关键注意点:
- 两个Rule的
LinkExtractor要精准匹配各自的链接格式,用allow和deny做区分 - 翻页规则一定要设置
follow=True,这样Scrapy才会自动请求下一页并继续抓取商品 - 保存JSON推荐用Scrapy自带的Feed Exporter(上述命令行方式),比手动写文件更稳定,避免并发写入的问题
方案二:普通Spider手动处理翻页(适合复杂翻页场景)
如果目标网站的翻页逻辑比较复杂(比如AJAX加载、需要登录验证、翻页链接是动态生成的),用普通Spider手动控制请求流程会更灵活,也更容易调试。
代码示例:
from scrapy import Spider, Request from scrapy.item import Item, Field class ProductItem(Item): title = Field() price = Field() class UrlLinkSpider(Spider): name = "urllink" allowed_domains = ['url.com'] start_urls = ['https://url.com/your-start-page'] def parse(self, response): # 第一步:抓取当前页的所有商品链接 product_links = response.xpath('//a[contains(@href, "/product/")]/@href').getall() for link in product_links: # 把相对链接转成绝对链接,交给parse_items处理 yield Request(response.urljoin(link), callback=self.parse_items) # 第二步:获取下一页链接,继续请求 next_page_href = response.xpath('//a[@class="next-page-btn"]/@href').get() if next_page_href: next_page_url = response.urljoin(next_page_href) yield Request(next_page_url, callback=self.parse) def parse_items(self, response): item = ProductItem() item['title'] = response.xpath('//h1[@class="product-title"]/text()').get(default='').strip() item['price'] = response.xpath('//span[@class="product-price"]/text()').get(default='').strip() yield item
这种方式的优势:
- 完全掌控请求流程,翻页逻辑可以自由调整(比如处理翻页次数限制、添加请求头/cookie)
- 调试更方便,能清晰看到每一步的请求和响应
总结建议
- 如果网站的翻页链接有固定规律(比如?page=1、?page=2),页面结构简单,优先用方案一,代码更简洁
- 如果翻页逻辑复杂(比如需要点击按钮加载、动态生成链接),或者需要自定义请求参数,用方案二更可控
- 不管用哪种方式,保存JSON都推荐用Scrapy的Feed Exporter,执行命令:
scrapy crawl urllink -o products.json,自动帮你处理编码和格式问题
内容的提问来源于stack exchange,提问作者DatCra
相关产品推荐
相关产品推荐

