Scrapy爬虫报错:'BookSpider'对象无'crawler'属性求助
问题原因
你遇到的 AttributeError: 'BookSpider' object has no attribute 'crawler' 是因为重写了Scrapy Spider的from_crawler类方法,但没遵循Scrapy的初始化规则——没有给Spider实例绑定crawler属性。
Scrapy默认的from_crawler方法会自动把crawler对象赋值给Spider的self.crawler属性,这个属性是Scrapy内部很多组件(比如去重过滤器、统计模块)的依赖项。而你自定义的from_crawler只返回了传入stats的Spider实例,完全跳过了这个绑定步骤,导致后续代码访问spider.crawler时触发报错。
修复方案
有两种简单的修复方式,任选其一即可:
方案1:手动在from_crawler中绑定crawler属性
修改from_crawler方法,创建实例后手动添加crawler属性再返回:
class BookSpider(scrapy.Spider): name = "books" @classmethod def from_crawler(cls, crawler): spider = cls(crawler.stats) spider.crawler = crawler # 手动绑定核心的crawler属性 return spider def __init__(self, stats): self.stats = stats self.visited_pages = []
方案2:调用父类from_crawler方法再扩展(推荐)
这种方式能继承父类的所有默认初始化逻辑,避免遗漏其他必要属性,更稳妥:
class BookSpider(scrapy.Spider): name = "books" @classmethod def from_crawler(cls, crawler, *args, **kwargs): # 先让父类完成默认初始化,保证crawler等核心属性被设置 spider = super().from_crawler(crawler, *args, **kwargs) # 再添加自定义的属性 spider.stats = crawler.stats spider.visited_pages = [] return spider
如果确实需要保留自定义的__init__方法,可以这样写:
class BookSpider(scrapy.Spider): name = "books" @classmethod def from_crawler(cls, crawler, *args, **kwargs): # 将stats作为参数传递给__init__ kwargs['stats'] = crawler.stats # 调用父类方法完成核心初始化 spider = super().from_crawler(crawler, *args, **kwargs) return spider def __init__(self, stats, *args, **kwargs): # 先调用父类的__init__,确保默认属性都被初始化 super().__init__(*args, **kwargs) self.stats = stats self.visited_pages = []
为什么这样有效?
父类scrapy.Spider的from_crawler方法会负责初始化self.crawler、self.settings等核心属性,调用父类方法能保证这些属性都被正确设置,避免出现类似的缺失属性错误。手动绑定crawler虽然能解决当前问题,但如果后续Scrapy更新默认初始化逻辑,可能会引入新问题,因此优先推荐方案2。
内容的提问来源于stack exchange,提问作者Nuccy
相关产品推荐
相关产品推荐

