Scrapy导入items类遇ModuleNotFoundError:'scraper'非包问题求助
解决Scrapy导入Item时的ModuleNotFoundError问题
错误核心原因
出现ModuleNotFoundError: No module named 'scraper.items'; 'scraper' is not a package的关键问题:
- 你误将运行脚本
scraper.py的文件名当作包名来导入,但scraper.py是单个脚本文件,并非Python包(包必须包含__init__.py文件)。 - 使用
from ..items import...的相对导入不适用当前目录结构,因为你是直接运行脚本,而非在包内部调用。
具体修复步骤
1. 修正导入语句
由于items.py和scraper.py处于同一目录,直接使用同级导入即可:
# 替换原有的 from scraper.items import ScraperItem from items import ScraperItem
2. 修复代码缩进与逻辑错误
你的start_requests和parse方法未缩进,不属于ScrapySpider类,同时存在Item实例化和yield对象的错误,修正后代码如下:
import scrapy from scrapy.crawler import CrawlerProcess from scrapy.loader import ItemLoader from items import ScraperItem class ScrapySpider(scrapy.Spider): name = 'scraper' def start_requests(self): # 缩进,归属类方法 yield scrapy.Request('https://www.thewhiskyexchange.com/c/639/bourbon-whiskey') def parse(self, response): # 缩进,归属类方法 products = response.css('li.product-grid__item') for item in products: # 循环内每次实例化新的Item,避免数据覆盖 whisky_item = ScraperItem() whisky_item['name'] = item.css('p.product-card__name::text').get().strip() whisky_item['price'] = item.css('p.product-card__price::text').get().strip().replace('£', '') whisky_item['perL'] = item.css('p.product-card__unit-price::text').get().strip().replace('per litre', 'per L').replace('(', '').replace(')', '') yield whisky_item # yield实例化的Item对象,而非循环变量item for x in range(2, 7): yield scrapy.Request(f'https://www.thewhiskyexchange.com/c/639/bourbon-whiskey?pg={x}', callback=self.parse) process = CrawlerProcess(settings = { 'FEED_URI': 'whiskey.csv', 'FEED_FORMAT': 'csv' }) process.crawl(ScrapySpider) process.start()
3. 确认目录结构
你的项目目录应保持如下结构(无需额外包结构):
你的项目文件夹/ ├── scraper.py └── items.py
无需添加__init__.py,因为你是直接运行脚本,不需要将当前目录作为包。
4. 正确运行脚本
在VS Code终端中切换到项目文件夹目录,执行命令:
python scraper.py
额外注意事项
- 避免脚本文件名与潜在包名冲突,比如不要用
scraper这类可能和爬虫项目名重复的文件名。 - 爬虫类的所有方法必须正确缩进,确保属于类的一部分,否则Scrapy无法识别。
- 循环内必须重新创建
ScraperItem实例,否则所有数据会被覆盖到同一个对象中。
内容的提问来源于stack exchange,提问作者Ego0r
相关产品推荐
相关产品推荐

