5月31日 01:07

Scrapy Item 和 Item Loader 应该怎么分工使用?

Scrapy 里的 Item 更像数据结构声明,Item Loader 更像数据清洗和装配工具。Item 负责告诉项目“我要采集哪些字段”,例如标题、价格、链接、发布时间;Item Loader 负责把页面上脏兮兮的原始文本变成可存储、可复用的数据。两者不是二选一关系,常见做法是先定义 Item,再用 Item Loader 填充字段。

如果页面字段很少,直接返回字典也能跑;如果项目要长期维护,Item 能让字段边界更清楚。Item Loader 的价值主要出现在字段来源复杂、需要去空格、拼接、取第一个值、统一格式时。它的坑也很明显:处理器写得太“聪明”,后面调试时很难判断数据是在 xpath、loader 还是 pipeline 阶段变坏的。

python
# items.py import scrapy class ProductItem(scrapy.Item): title = scrapy.Field() price = scrapy.Field() url = scrapy.Field()
python
from itemloaders.processors import TakeFirst, MapCompose from scrapy.loader import ItemLoader from .items import ProductItem def strip_text(v): return v.strip() loader = ItemLoader(item=ProductItem(), response=response) loader.default_input_processor = MapCompose(strip_text) loader.default_output_processor = TakeFirst() loader.add_css('title', 'h1::text') loader.add_css('price', '.price::text') loader.add_value('url', response.url) yield loader.load_item()

追问

什么时候直接用 dict,什么时候定义 Item?

临时脚本、一次性抓取或者字段只有两三个时,直接 yield dict 成本最低,也方便快速验证选择器。项目进入多人维护、字段会被多个 spider 或 pipeline 共享时,Item 更稳,因为字段名集中在一个地方,不容易写成 titel 这种隐蔽错误。取舍点在于维护成本:Item 多一层定义,但能换来更清楚的数据契约。边界是 Scrapy 不会强制校验字段类型,Item 不是 Pydantic,真要类型校验还得放到 loader 或 pipeline 里。

Item Loader 的输入处理器和输出处理器有什么区别?

输入处理器会作用在每一次 add_cssadd_xpathadd_value 收进来的原始值上,适合做去空格、去货币符号、日期字符串预处理。输出处理器会在 load_item() 时统一收口,适合做 TakeFirst()、列表去重、拼接多个值。踩坑最多的是把“取第一个值”放进输入处理器,结果后续再追加字段时数据被提前截断。实践里可以把输入处理器写轻一点,把最终决策留给输出处理器。

Item Loader 会不会让代码变复杂?

小页面上它确实可能显得啰嗦,尤其是字段只有标题和链接时,直接写字典更直观。复杂页面就不一样了,同一个字段可能来自 meta、页面文本和接口返回,Loader 能把这些来源集中到一个字段收集流程里。它的边界是不要把业务规则全塞进去,比如“库存为 0 就丢弃商品”更适合 pipeline,而不是 loader。否则 spider、loader、pipeline 的职责会混在一起,排查问题时只能一路打日志。

如何避免 Item Loader 清洗后数据不符合预期?

第一步是让处理器足够小,每个函数只做一件事,例如只去空格、只解析价格、只标准化 URL。第二步是在关键字段上加单元测试,尤其是价格、时间、地区这种容易受页面格式影响的字段。第三步是保留少量原始字段或调试日志,线上数据突然异常时能反查来源。取舍是日志和原始字段会占存储空间,但对长期运行的爬虫来说,这点成本通常比盲查问题低得多。

Item、Loader 和 Pipeline 的边界怎么划?

Item 定义“有什么字段”,Loader 解决“字段如何从页面变干净”,Pipeline 处理“这条数据能不能入库、入哪儿、是否重复”。这个边界不是绝对的,但越早统一越省事。比如价格文本转数字可以放 Loader,价格小于 0 的异常数据丢弃更适合 Pipeline。常见坑是 Pipeline 里再做大量字符串清洗,导致同一套清洗逻辑无法被多个 spider 复用。

标签:Scrapy