Scrapy爬虫可爬取单分类页面但无法爬取同分类下一页的问题求助
问题分析与解决方案
嘿,看了你的报错信息和代码,问题其实一目了然:你在请求下一页的时候,没有把category_name和Category_link这两个参数传递给info_parse方法,导致方法执行时缺少必填的位置参数,直接抛出了TypeError。
下面一步步给你解决问题,顺便优化下爬虫的效率:
1. 先搞定下一页的参数传递
你在parse方法里第一次调用info_parse时,用cb_kwargs传了参数,但处理下一页的时候只写了yield response.follow(url=final_url,callback=self.info_parse),完全没传那俩参数,这就是报错的根源。
把下一页的请求代码改成这样:
yield response.follow( url=final_url, callback=self.info_parse, cb_kwargs={'category_name': category_name, 'Category_link': Category_link} )
另外,其实你手动拼接下一页URL的逻辑完全可以简化——Scrapy的response.follow会自动基于当前页面的URL处理相对路径,直接传next_page就行,不用手动拆分拼接,省得出错:
# 替换你原来的下一页URL拼接逻辑 next_page = response.xpath('//*[@class="next"]/a/@href').get() if next_page: yield response.follow( next_page, callback=self.info_parse, cb_kwargs={'category_name': category_name, 'Category_link': Category_link} )
2. 优化书籍详情页的请求方式(非常重要!)
你现在在info_parse里用requests.get同步请求书籍详情页,这会彻底破坏Scrapy的异步并发机制,爬虫速度会慢得离谱,还容易被网站检测到反爬。
建议把书籍详情页的解析抽成单独的方法,用Scrapy的异步请求来处理:
def info_parse(self, response, category_name, Category_link): book_urls = response.xpath('//section/div/ol/li/article[@class="product_pod"]/h3/a/@href') for book_url in book_urls: book_info_url = response.urljoin(book_url.get()) # 用Scrapy异步请求代替requests同步请求 yield response.follow( book_info_url, callback=self.parse_book_detail, cb_kwargs={ 'category_name': category_name, 'Category_link': Category_link, 'Bookurl': book_info_url } ) # 下一页逻辑(已修复) next_page = response.xpath('//*[@class="next"]/a/@href').get() if next_page: yield response.follow( next_page, callback=self.info_parse, cb_kwargs={'category_name': category_name, 'Category_link': Category_link} ) # 新增书籍详情解析方法 def parse_book_detail(self, response, category_name, Category_link, Bookurl): bookprize = response.xpath('//p[@class="price_color"]/text()').get() yield { 'Category_Name': category_name, 'Category_link': Category_link, 'Bookurl': Bookurl, 'Bookprize': bookprize }
3. 额外的小修复
你代码里的"应该是转义错误,实际写代码时直接用双引号"就行,避免语法问题。
完整的修复后代码
import scrapy from ..items import ScrapybooksspiderItem class ScrapSpider(scrapy.Spider): name = 'scrapp' allowed_domains = ['books.toscrape.com'] start_urls = ['http://books.toscrape.com/'] def parse(self, response): # 定位Historical Fiction分类 categ = response.xpath('//div[@class="side_categories"]/ul[@class="nav nav-list"]/li/ul/li') category_name = categ.xpath('.//a[contains(text(),"Historical Fiction")]/text()').get().replace('\n', "").strip() category_link = categ.xpath('.//a[contains(text(),"Historical Fiction")]/@href').get().replace('\n', "").strip() yield response.follow( category_link, callback=self.info_parse, cb_kwargs={'category_name': category_name, 'Category_link': category_link} ) def info_parse(self, response, category_name, Category_link): book_urls = response.xpath('//section/div/ol/li/article[@class="product_pod"]/h3/a/@href') for book_url in book_urls: book_info_url = response.urljoin(book_url.get()) yield response.follow( book_info_url, callback=self.parse_book_detail, cb_kwargs={ 'category_name': category_name, 'Category_link': Category_link, 'Bookurl': book_info_url } ) # 处理下一页 next_page = response.xpath('//*[@class="next"]/a/@href').get() if next_page: yield response.follow( next_page, callback=self.info_parse, cb_kwargs={'category_name': category_name, 'Category_link': Category_link} ) def parse_book_detail(self, response, category_name, Category_link, Bookurl): book_prize = response.xpath('//p[@class="price_color"]/text()').get() yield { 'Category_Name': category_name, 'Category_link': Category_link, 'Bookurl': Bookurl, 'Bookprize': book_prize }
这样修改后,爬虫就能正常爬取下一页内容,同时保持Scrapy的异步高效性,不会再出现参数缺失的错误啦。
内容的提问来源于stack exchange,提问作者Abu Bakar Siddique
相关产品推荐
相关产品推荐

