Scrapy Pipeline中MongoDB连接失败主因是配置未显式指定host/port及认证参数,且Client未复用;字段不匹配需确保Item键名与MongoDB文档完全一致;批量写入应缓存后insert_many并设ordered=False;去重须建唯一索引配合upsert=True。

Scrapy Pipeline里用pymongo.MongoClient连不上数据库?
常见现象是爬虫跑完没报错,但MongoDB里空空如也,或者直接卡在MongoClient初始化那行。根本原因通常是连接配置没走通,而不是Pipeline逻辑写错了。
- 默认
MongoClient会尝试连localhost:27017,但Docker或远程部署时这地址大概率不存在——得显式传host和port - 如果MongoDB启用了认证,光配地址不够,必须加
username、password、authSource(通常是admin) - 别在
process_item里每次新建MongoClient,连接对象要复用;建议在__init__里初始化,顺便做一次server_info()探测,失败就抛异常,别让爬虫静默失败
Scrapy Item字段和MongoDB文档字段对不齐怎么办?
Scrapy的Item是类字典结构,但字段名、类型、嵌套深度跟MongoDB实际存的文档不一致,会导致写入后查不到、或字段被忽略。
-
Item里定义的字段名必须和item.get("xxx")里的键完全一致,MongoDB不会自动映射snake_case到camelCase - 如果Item字段是
None,PyMongo默认不写入该键(不是存null),想强制保留得手动设成None或""再update_one(..., upsert=True) - 嵌套字段比如
item["author"]["name"],得先确保item["author"]不是None,否则TypeError: 'NoneType' object is not subscriptable
为什么insert_one慢得像卡住,而insert_many又丢数据?
这不是PyMongo的问题,是Scrapy并发和MongoDB写入语义没对齐导致的典型性能陷阱。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
-
insert_one在高并发下会触发大量小IO,尤其当MongoDB不在本地时延迟飙升;但盲目换insert_many会有风险:Scrapy可能在一批item还没发完时就结束,导致最后一批不满阈值的item丢失 - 稳妥做法是自己缓存item,达到N个(比如100)再批量写,同时在
close_spider里清空剩余缓存 - 记得给
insert_many加ordered=False,否则一个document校验失败(比如重复key),整批都写不进去
Scrapy中间件和Pipeline谁该负责去重?MongoDB里怎么防重复插入?
别指望Pipeline靠find_one查重再决定是否insert——这在并发下必然漏判。真正可靠的去重必须落到数据库层。
立即学习“Python免费学习笔记(深入)”;
- 在MongoDB集合上建唯一索引,比如
db.mycol.create_index("url", unique=True),然后用update_one(..., upsert=True)替代insert_one - 如果去重依据是多个字段(如
title + pub_date),索引要建复合的:create_index([("title", 1), ("pub_date", 1)], unique=True) - PyMongo遇到重复键错误会抛
pymongo.errors.DuplicateKeyError,可以在Pipeline里捕获并pass,但更推荐直接让upsert=True吞掉它
真正麻烦的是索引建晚了——等爬了一半才补,历史数据得手动去重;还有ObjectId自增ID和时间戳混用时,更新逻辑容易写错。这些细节不提前想清楚,后期修数据比重爬还累。

















