直接用elasticsearch-py的index()方法写入易丢字段或报错,因其默认不校验schema,字段类型冲突时静默失败或触发illegal_argument_exception;需手动定义mapping、清洗字段、禁用dynamic、绑定ik分词器并验证分词效果。

为什么直接用 elasticsearch-py 写入容易丢字段或报错?
因为默认的 index() 方法不校验 schema,字段类型冲突时会静默失败或写入失败(比如把字符串当数字索引),尤其在爬虫数据结构松散时更明显。常见错误是 illegal_argument_exception 或 mapper_parsing_exception,本质是 mapping 不匹配。
实操建议:
- 先用
PUT /my_index手动定义 mapping,明确指定title、content为text类型,并开启"analyzer": "ik_max_word"(如用 IK 分词器) - 爬虫入库前加一层字段清洗:用
dict.get(key, "")替代直接取值,避免KeyError导致整条丢弃 - 禁用自动 mapping:在 index settings 中设
"dynamic": "strict",强制所有字段必须预定义
如何让爬虫数据进 Elasticsearch 后支持中文分词检索?
不是装了 IK 插件就自动生效——必须在创建 index 时把 analyzer 绑定到具体字段。否则即使内容是中文,也会按默认 standard 分词器切分成单字或乱码。
实操建议:
- 检查 IK 是否加载成功:
GET /_cat/plugins?v,确认有ik行 - 建索引时显式声明:
"mappings": {"properties": {"content": {"type": "text", "analyzer": "ik_max_word"}} - 验证分词效果:
POST /my_index/_analyze {"analyzer": "ik_max_word", "text": "Python爬虫实战"},看是否返回["Python", "爬虫", "实战"]
批量写入(bulk)时为什么部分文档失败但不报错?
helpers.bulk() 默认遇到单条失败就跳过,继续处理后续,且不抛异常——这会让爬虫看似“成功”入库,实际大量数据丢失。
实操建议:
- 始终捕获并检查
bulk()返回的(success_count, failed_items),打印failed_items[0]["index"]["error"]定位具体哪条、什么错 - 对每条文档加
_id(比如用 URL 的hashlib.md5(url.encode()).hexdigest()),避免重复插入触发 version conflict - 控制批量大小:100–500 条/批较稳;超过 1MB 单批体积易触发
es_rejected_execution_exception
爬虫字段和 ES mapping 对不上怎么办?
比如爬到的 publish_time 是字符串 "2024-03-15 14:22",但 mapping 定义的是 date 类型,就会写入失败。
实操建议:
- 统一转换时间字段:
datetime.strptime(s, "%Y-%m-%d %H:%M").isoformat()→ 存为 ISO8601 字符串,ES 能自动识别 - 数值字段用
float()/int()包裹并加try/except,失败则设为None(前提是 mapping 允许 null_value) - 保留原始字段名不变,新增清洗后字段(如
publish_time_clean),避免污染原始数据流
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











