重写start_requests后Scrapy爬虫无法爬取起始URL外页面求助
问题分析与解决方案
你遇到的问题核心有两点:
- 重写
start_requests时直接指定callback=parse_item,跳过了CrawlSpider内置的parse方法,导致定义的Rules链接提取规则完全失效,爬虫只会处理起始URL,不会跟进其他页面。 - 即便Rules生效,LinkExtractor生成的后续请求也不会自动携带起始URL元数据,需要手动传递。
修改后的完整代码
from scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LinkExtractor from scrapy.http import Request class TSpider(CrawlSpider): name = 't' allowed_domains = ['books.toscrape.com'] # 修正原域名拼写错误,多了一个"s" start_urls = ['https://books.toscrape.com'] # 自定义请求处理方法,传递起始URL元数据 def pass_start_url(self, request, response): request.meta['start_url'] = response.meta['start_url'] return request rules = ( Rule(LinkExtractor(allow=[r'.*page.*']), callback='parse_item', follow=True, process_request='pass_start_url'), # 绑定元数据传递方法 ) def start_requests(self): for url in self.start_urls: # 起始请求回调用CrawlSpider默认的parse方法,触发Rules生效 yield Request(url, callback=self.parse, meta={'start_url': url}) def parse_item(self, response): item = {} item['title'] = response.xpath('//head/title/text()').get() # get()更适合提取单个文本节点 item['url'] = response.url item['start_url'] = response.meta['start_url'] yield item
关键修改说明
- 修正域名错误:原代码
allowed_domains写成了books.toscrapes.com,多了一个s,会导致后续请求被爬虫过滤。 - 恢复Rules触发逻辑:起始请求的
callback改为self.parse,这是CrawlSpider处理Rules的入口方法,能自动执行链接提取和跟进逻辑。 - 传递元数据:通过Rule的
process_request参数绑定自定义方法pass_start_url,将起始URL从响应的meta中传递给新生成的请求,确保所有页面的请求都携带start_url元数据。 - 优化数据提取:把
extract()改为get(),更简洁地提取单个文本节点结果。
内容的提问来源于stack exchange,提问作者John M.
相关产品推荐
相关产品推荐

