目录
2026 年 2 月,我整理过一份 PubMed XML 批量下载方案。最初目标是为本地文本处理准备结构化文献数据,但真正需要设计的并不是一条下载命令,而是一条能够校验、更新、重建和追踪版本的数据管道。
文件数量、容量和编号范围会随年度发布变化,实际执行时应以 NLM 当期目录及 README 为准。
为什么选择 XML,而不是从 PDF 开始
如果目标是题录检索、文献筛选或构建元数据索引,PubMed XML 已经提供了相对清晰的结构,包括 PMID、标题、摘要、作者、期刊、日期、出版类型和 MeSH 等字段。
与 PDF 相比,它有几个工程优势:
- 不需要先解决版式解析和 OCR;
- 可以按记录流式处理;
- 字段来源和层级更明确;
- 更容易做增量更新和删除记录处理;
- 适合转换成数据库表或列式文件。
但 XML 结构化并不等于字段永远完整。标题中可能包含内联标记,摘要可能分段,日期可能只有年份或季节,作者也可能缺失部分姓名字段。解析程序必须允许不完整记录。
数据管道的七个阶段
我把完整流程拆成:
发现版本
→ 下载
→ 校验
→ 流式解析
→ 规范化
→ 存储与索引
→ 应用增量更新
每个阶段都应留下清单和日志,而不是把下载目录直接当成数据库。
1. 年度基线与增量文件分开保存
年度基线用于构建完整快照,updatefiles 用于加入新增、修订和删除记录。两者应进入不同目录:
pubmed/
├── source/
│ ├── baseline/
│ └── updatefiles/
├── manifests/
├── normalized/
├── index/
└── logs/
source/ 保存未经修改的下载文件;规范化结果和索引可以随时从源文件重建。
2. 下载前生成 manifest
manifest 至少记录:
- 远端文件名与地址;
- 文件所属发布批次;
- 下载时间;
- 本地文件大小;
- 官方提供的校验信息;
- 下载状态与重试次数;
- 解析状态;
- 解析程序版本。
这样才能区分“没有下载”“下载不完整”和“下载完成但解析失败”。
3. 完整性校验是下载流程的一部分
断点续传只能避免重复下载,不能证明文件内容正确。每个文件下载完成后,应使用发布方提供的校验信息进行验证;校验失败的文件不能进入解析队列。
批量任务还需要处理:
- 临时文件与最终文件分离;
- 校验成功后再原子改名;
- 下载失败时限制重试次数;
- 日志中记录 HTTP/FTP 状态与失败原因;
- 再次运行时跳过已经验证的文件。
4. XML 应当流式解析
年度数据不适合一次性读入内存。更合适的方式是按 PubmedArticle 或相关记录节点迭代:
from lxml import etree
context = etree.iterparse(
"pubmed.xml",
events=("end",),
tag="PubmedArticle",
)
for _, element in context:
record = normalize_article(element)
write_record(record)
element.clear()
示意代码省略了解压、异常记录和父节点清理。真正运行时需要使用小文件测试内存是否稳定,并记录解析失败的 PMID 或源文件位置。
5. 先建立稳定的规范化层
在进入全文检索或向量库之前,我会先生成一套稳定记录:
pmid
record_version
record_status
title
abstract_sections
authors
journal
publication_date
publication_types
mesh_terms
source_file
ingested_at
复杂的作者、摘要分段和 MeSH 可以保留为子表或嵌套字段。关键是不要在第一版中为了“表格整齐”而丢掉原始结构。
6. 存储方式取决于查询方式
- SQLite:适合单机原型、状态清单和中等规模元数据查询。
- PostgreSQL:适合团队协作、事务更新和较复杂的检索服务。
- Parquet:适合批量统计、机器学习数据准备和快照归档。
- 全文搜索引擎:适合复杂关键词检索,但增加了部署与同步成本。
一个实用组合是:数据库维护当前记录和更新状态,Parquet 保存可复现快照;只有在需求明确后再增加向量索引。
7. 增量更新必须理解“删除”
更新文件不仅包含新增记录,也可能修订或删除既有 PMID。增量程序不能只做追加:
读取更新批次
→ 对新增或修改记录执行 upsert
→ 处理删除标记
→ 写入批次日志
→ 生成更新后的快照版本
每个快照都应能回答“包含到哪个更新批次”,否则后续检索结果无法复现。
不要直接把原始 XML 倒进 RAG
在建立向量索引之前,至少要解决:
- 重复和修订记录;
- 空摘要与分段摘要;
- 文本语言;
- 标题中的内联标记;
- 检索单元与 PMID 的稳定关联;
- 重新嵌入时的版本管理;
- 来源展示与数据使用边界。
向量库只是检索层,不应承担数据清洗和版本控制。
使用边界
PubMed 数据的不同字段和关联资源可能有不同使用要求。公开服务或再分发前,应核对当期 NLM README、DTD 文档和相关条款,注明数据来源,不使用官方标识暗示背书。
参考入口:
讨论
评论使用 GitHub Discussions。首次加载需要访问 GitHub。