第 4 章 数据源收集与整合:从哪里找,怎么拿
做知识图谱,80% 的精力其实都花在数据上。这不是夸张。你算法再牛,模型再花哨,喂进去的数据是脏的、不全的,最后出来的东西肯定没法用。
我个人习惯先把数据源摸清楚再动手。癌症药物领域,公开数据源其实不少,但各有各的脾气。今天咱们就聊聊三个最核心的数据源——DrugBank、NCI Thesaurus、PubMed,以及怎么把它们的数据搞到手。
4.1 公开数据源概览:三巨头各有分工
你想想看,要构建一个完整的癌症药物知识图谱,至少需要三类信息:药物本身的信息、癌症相关的术语体系、以及临床证据。这三样正好对应三个数据源。
| 数据源 | 定位 | 核心内容 | 获取方式 |
|---|---|---|---|
| DrugBank | 药物综合数据库 | 药物靶点、作用机制、适应症、化学结构 | XML/CSV 下载、REST API |
| NCI Thesaurus | 癌症术语本体 | 癌症类型、药物分类、基因、生物过程 | OWL/RDF 下载、SPARQL 查询 |
| PubMed | 生物医学文献 | 临床研究、病例报告、综述 | E-utilities API、批量下载 |
说白了,DrugBank 告诉你“这个药是干什么的”,NCI Thesaurus 告诉你“这个癌是什么”,PubMed 告诉你“这个药治这个癌有没有人用过”。三者的关系,我画了张图帮你一目了然。
4.2 DrugBank:药物数据的黄金标准
DrugBank 是我最常打交道的数据源。它由加拿大阿尔伯塔大学维护,收录了 14000 多种药物,包括 FDA 批准的、实验性的甚至已经退市的。
关键点:DrugBank 提供了两种数据获取方式。我个人建议:如果你做的是静态分析,直接下载完整 XML 文件;如果需要实时查询,用 REST API。
4.2.1 下载 XML 数据
访问 drugbank.ca,注册学术账号后,可以在 Downloads 页面获取完整数据包。XML 文件结构清晰,每个药物条目包含以下主要字段:
<drug type="biotech">
<drugbank-id primary="true">DB00001</drugbank-id>
<name>Trastuzumab</name>
<description>... 曲妥珠单抗用于治疗HER2阳性乳腺癌 ...</description>
<targets>
<target>
<id>BE0000001</id>
<name>Receptor tyrosine-protein kinase erbB-2</name>
<organism>Human</organism>
<actions>
<action>antagonist</action>
</actions>
</target>
</targets>
<pathways>
<pathway>
<name>HER2 signaling pathway</name>
</pathway>
</pathways>
</drug>
注意:XML 文件很大,解压后可能超过 2GB。解析时建议使用流式解析器(比如 SAX),别一次性加载到内存里。我曾经有一次图省事用 DOM 解析,结果服务器直接 OOM 了。
4.2.2 REST API 调用
如果你的场景需要实时查询,API 更合适。需要先申请 API Key。调用方式很简单:
curl -X GET "https://api.drugbank.com/v1/drugs?q=trastuzumab&limit=10" \
-H "Authorization: Bearer YOUR_API_KEY"
返回的是 JSON 格式,可以直接用 Python 的 requests 库处理。
4.3 NCI Thesaurus:癌症术语的权威词典
NCI Thesaurus(简称 NCIt)是美国国家癌症研究所维护的癌症本体库。它不仅仅是术语表,而是一个完整的 OWL 本体,包含了癌症类型、药物、基因、解剖部位等概念的层次关系和属性。
为什么要用这个?因为知识图谱中的实体需要标准化。你不能让一个节点叫“非小细胞肺癌”,另一个节点叫“NSCLC”,它们应该是同一个东西。NCIt 提供了这种标准化的概念编码。
4.3.1 获取 OWL 文件
NCIt 每个月更新一次,OWL 文件可以从 https://evs.nci.nih.gov/ftp1/NCI_Thesaurus/ 下载。文件大小约 500MB,包含超过 10 万个类定义。
4.3.2 SPARQL 端点查询
NCIt 提供了 SPARQL 端点,可以直接查询。举个例子,查询“所有已知与肺癌相关的药物”:
PREFIX ncit: <http://ncicb.nci.nih.gov/xml/owl/EVS/Thesaurus.owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?drug ?label
WHERE {
?drug a ncit:C1909 . # C1909 = Therapeutic Agent
?drug rdfs:label ?label .
?drug ncit:P2175 ncit:C3400 . # P2175 = Disease_Has_Associated_Treatment
# C3400 = Non-Small Cell Lung Cancer
}
我个人习惯把 NCIt 的 OWL 文件加载到本地的 RDF 数据库中(比如 Apache Jena 或 Virtuoso),这样查询速度快得多,也方便和 DrugBank 的数据做交叉引用。
4.4 PubMed:临床证据的宝库
PubMed 是最庞大的生物医学文献数据库,收录了超过 3500 万篇文献摘要。做知识图谱的时候,经常需要从文献中抽取药物-疾病-靶点的关系。
PubMed 提供了一组叫 E-utilities 的 API,非常实用。嗯,这里要注意,E-utilities 有调用频率限制,每秒最多 3 次请求,没有 API Key 的话限制更严格。
4.4.1 使用 E-utilities 批量查询
一个典型的查询流程:先用 ESearch 找到文献 ID,再用 EFetch 获取详细数据。比如搜索“trastuzumab AND breast cancer”:
# 第一步:搜索文献 ID
curl "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi? \
db=pubmed&term=trastuzumab+AND+breast+cancer&retmax=20&format=json"
# 返回结果示例(简化)
{
"esearchresult": {
"count": "15234",
"idlist": ["38212345", "38209876", "38199432", "..."]
}
}
# 第二步:根据 ID 获取摘要
curl "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi? \
db=pubmed&id=38212345,38209876&retmode=xml&rettype=abstract"
返回的 XML 包含标题、作者、摘要、MeSH 主题词等。MeSH 主题词尤其重要——它是经过标准化的医学主题词表,直接可以作为知识图谱中的实体标签。
4.4.2 数据存储建议
我一般会把抓取到的 PubMed 数据用 Parquet 格式存储,而不是存成一大堆 JSON 文件。Parquet 列式存储,查询速度快,而且天然支持 schemas,后续用 Spark 或者 Pandas 处理都很方便。
4.5 数据爬取与整合:避坑指南
数据源找到了,API 也会调了,接下来就是头疼的整合阶段。这里我踩过不少坑,挑几个典型的说说。
我的经验:不要试图一口气把所有数据都整合好。分阶段进行:先整合 DrugBank 和 NCIt,把药物-癌症的静态关系建好;再加入 PubMed 的文献证据,作为关系边界的权重属性。
4.5.1 实体对齐问题
同一个药物,在 DrugBank 里叫“Trastuzumab”,在 NCIt 里叫“Trastuzumab”,在 PubMed 里可能叫“Herceptin”(商品名)。怎么对齐?
我通常靠统一标识符来解决。DrugBank 的 ID 和 NCIt 的代码(比如 C1647)是可以互相映射的,市面上也有现成的映射表。PubMed 则通过 MeSH ID 来做映射。先把所有实体映射到统一的 ID 空间,后面的融合就省心了。
4.5.2 数据质量检查
检查清单很简单,但容易忽略:
- 字段缺失情况:比如有些药物没有靶点信息
- 数据一致性:同一种癌症在不同数据源里的名称是否一致
- 时间戳:PubMed 的文献是有发表时间的,别用过期数据
避坑指南:我曾经做过一个项目,直接用 NCIt 的 OWL 文件里的 rdfs:label 当实体名称,结果发现里面混了少量的拼写错误和过时的术语。后来我加了一步清洗流程——用 MeSH 的最新版本做一次校正。这个步骤虽然多花了一天,但确实救了不少下游的推理任务。
4.6 本章小结
数据源收集与整合听起来基础,但它是知识图谱的根基。三个数据源各有侧重:DrugBank 管药物,NCIt 管术语,PubMed 管证据。把这三者打通,你的图谱就有了骨架、肌肉和血液。
工具方面,Python 的 requests 和 BeautifulSoup 处理 API 和网页抓取,xml.etree.ElementTree 解析 DrugBank 的 XML,rdflib 处理 NCIt 的 OWL,pymed 或 biopython 对接 PubMed。这些组合足够覆盖 80% 的日常需求了。