第2章 PubMed数据库详解:结构、检索语法与API归纳总结
做药物靶点关系的文献挖掘,PubMed是你绕不开的第一站。说实话,很多人都只是把它当普通文献搜索引擎——输入关键词、点搜索、看摘要。但我告诉你,如果你只停留在表面,那抓回来的数据质量大概率不靠谱。
这一章,我会带你拆开PubMed的底层结构,把它的字段、检索语法、API调用规则讲清楚。嗯,全是干活用得着的东西。
2.1 PubMed记录的内部结构
PubMed里的每篇文章,对应一条记录。每条记录由多个字段组成。我刚开始用NCBI E-utilities时,最头疼的就是搞不清字段名——同样的信息,在XML里可能叫PMID,也可能叫MedlineTA,稍不注意就写错。
下面这张表,是我自己整理的核心字段清单,你用API时一定会碰到。
| 字段名 | 全称 | 用途说明 |
|---|---|---|
| PMID | PubMed Identifier | 文章唯一标识号 |
| TI | Title | 文章标题 |
| AB | Abstract | 摘要全文 |
| AU | Author | 作者列表 |
| AD | Affiliation | 作者机构 |
| MH | MeSH Terms | 医学主题词(我最爱用的字段) |
| RN | Registry Number | 化学物质登记号(药物靶点必备) |
| PT | Publication Type | 文献类型(例如Review、Clinical Trial) |
| DP | Date of Publication | 发表日期 |
| SO | Source | 期刊名、卷期页码 |
MH字段。你想想看,同一个靶点蛋白在不同文章里可能有不同写法——“EGFR”“ErbB1”“HER1”,但MeSH词会统一成一个节点。如果你只用自由词,漏掉一半文章是常有的事。
2.2 检索语法:从入门到避坑
PubMed的检索语法说实话并不难,但它有一些藏得很深的坑。我早年写过一个爬虫,因为没处理引号里的短语,结果把“NPY receptor”拆成了“NPY”和“receptor”,召回了一堆不相关的神经肽论文。
核心语法规则就这么几条:
- 布尔逻辑: NOT
- 短语检索: 用英文双引号包裹,例如
"angiotensin converting enzyme" - 字段限定: 字段名加中括号,例如
diabetes[TIAB] - 截词检索: 星号
*代表任意字符,例如therap*匹配 therapy, therapeutic, therapist - 范围检索: 用方括号和冒号,例如
2000[DP] : 2020[DP] - 索引自动扩展: PubMed默认会对单词做MeSH扩展和自动短语映射,如果不想要,加引号就行
我个人常用的一个小技巧:把MeSH词和自由词组合起来,用OR连接。举个例子:
("Dopamine D2 receptor"[MH] OR "DRD2"[TIAB]) AND ("Schizophrenia"[MH] OR "psychosis"[TIAB])
这样既不会漏掉标了MeSH的文献,也能抓住那些还没标引的新文章。
*不能和字段限定同时写在同一个词上。比如 kinase*[TIAB] 是不被支持的——PubMed会报错。正确的做法是写成 kinase[TIAB] OR kinases[TIAB],或者直接用不带字段的截词检索。2.3 E-utilities:API调用实战
药物靶点关系挖掘,不能靠手动到网页上复制粘贴。必须上API。NCBI提供的E-utilities是一组RESTful接口,完全免费,但限制频率——每秒最多3次请求(如果没有API Key的话)。
整个调用流程就像一条管道:
- 用
esearch.fcgi发送检索请求,得到PMIDs列表 - 用
efetch.fcgi根据PMIDs拉取完整的XML记录 - 解析XML提取你需要的字段
核心参数就这么几个:
| 参数 | 说明 | 示例值 |
|---|---|---|
| db | 数据库名称 | pubmed |
| term | 检索表达式(需URL编码) | cancer[TI] AND p53 |
| retmax | 最大返回记录数(默认20) | 10000 |
| retmode | 返回格式 | xml 或 json |
| rettype | 返回内容类型 | abstract, medline, xml |
| api_key | (可选)提升频率限制到10次/秒 | 你的key |
下面是我最常用的一段检索请求示例(用Python的requests库):
import requests
import urllib.parse
base = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils"
query = '(("angiogenesis"[MeSH] OR "VEGF"[TIAB]) AND "receptor"[TIAB])'
params = {
"db": "pubmed",
"term": query,
"retmax": 5000,
"retmode": "json",
"api_key": "你的NCBI API Key(可省略)"
}
resp = requests.get(f"{base}/esearch.fcgi", params=params)
data = resp.json()
pmids = data["esearchresult"]["idlist"]
print(f"共找到 {len(pmids)} 条记录")
print(pmids[:10]) # 前10个PMID
得到PMIDs后,再用efetch拉数据:
efetch_params = {
"db": "pubmed",
"id": ",".join(pmids[:100]), # 一次最多拉200条
"retmode": "xml",
"rettype": "abstract"
}
resp = requests.get(f"{base}/efetch.fcgi", params=efetch_params)
with open("records.xml", "w", encoding="utf-8") as f:
f.write(resp.text)
retmode=xml。因为XML里包含的字段最全,包括MeSH词、化学物质注册号、出版类型等关键信息。JSON格式虽然解析简单,但某些字段会被省略或展开成奇怪的结构。2.4 整章知识结构一览
说到这儿,我把这一章的核心逻辑画成一张图。你看完就能明白,从检索到API再到数据解析,每一步该做什么。
你看,整个流程并不复杂。关键是每一步都有细节——比如词汇选MeSH还是自由词、API返回的XML怎么解析、频率限制怎么绕过。这些坑我在项目里都挨个踩过,现在写出来,你就不用再走一遍弯路了。
2.5 关于API Key的补充
最后多说一句API Key的事。NCBI现在要求每个请求最好都带上api_key参数,哪怕是免费注册的。为什么要这么做?
- 无Key:每秒最多3次,日均约26万次,超限返回HTTP 429
- 有Key:每秒最多10次,日均86万次,基本够用
https://www.ncbi.nlm.nih.gov/account/ 登录后进入API Key管理页面,一键生成。免费,不到5分钟搞定。我建议你在写代码之前就先注册好,因为一旦批量检索被限流,重新跑一遍很浪费时间。好了,PubMed的核心结构、检索语法、API调用方法,我都给你理清楚了。下一步就是拿着这些知识,去获取真实的药物-靶点文献数据。你在实际检索时如果遇到奇怪的结果,十有八九是字段没写对或者引号漏了——回头再翻翻这一章的表格和代码示例,基本都能解决。