4. COVID-19相关药物数据源介绍:DrugBank、PubMed、ClinicalTrials
做知识图谱,数据源就是你的“弹药库”。弹药质量决定了下游能打出什么样的子弹。这一节,我把构建COVID-19药物知识图谱时,最常用的三种数据源梳理一遍。
4.1 数据源概述与选择取舍
先说结论:没有哪个数据源是万能的。DrugBank擅长大分子药理,PubMed是文献海洋,ClinicalTrials则聚焦临床试验。我习惯把它们组合起来用,形成一条数据采集流水线。
下表罗列了三者的核心维度对比:
| 数据源 | 数据类型 | 更新频率 | 获取方式 | 主要用途 |
|---|---|---|---|---|
| DrugBank | 结构化药物-靶点关系 | 约每季度 | API / XML 下载 | 药物实体、靶点关系、ADMET |
| PubMed | 文献元数据 & 摘要 | 每日 | NCBI E-utilities | 文本挖掘、关系抽取、证据溯源 |
| ClinicalTrials | 临床试验方案 & 结果 | 每周 | AACT 数据库 / API | 药物与疾病干预实验验证 |
你想想看,如果一个药物在DrugBank里有明确的靶点,在ClinicalTrials里有正在进行的临床试验,同时还有PubMed文献支撑其作用机制——那这个关系就非常可信了。在项目中我称之为“三源证据链”。
4.2 DrugBank:结构化药物知识的首选
DrugBank是我做药物KG时的起点。它本质上是一个手工审核的、结构化的药物-靶点数据库。对于COVID-19药物来说,它包含的信息非常规整。
4.2.1 数据特征
- 药物实体:药物名称、同义词、CAS号、UNII标识符
- 靶点关系:靶点名称、基因符号、UniProt ID、作用类型
- 关键字段:
type(small molecule / biotech),mechanism-of-action,category
我个人习惯直接下载XML dump做批量解析,而不是每次都调API。下面这个命令是我经常用的,用来提取所有COVID-19相关的药物条目:
# 下载DrugBank XML (需要注册获取API key)
wget --user=xxx --password=xxx https://go.drugbank.com/releases/latest/full.xml.gz
gunzip full.xml.gz
# 用xmlstarlet提取药物通用名和靶点名称(简化版)
xmlstarlet sel -t -v "//drugbank:drug[drugbank:categories/drugbank:category/@term='COVID-19']/drugbank:name" full.xml | head -20
4.2.2 在实际项目中的避坑
我曾经在解析DrugBank时踩过一个坑:它的小分子药物和生物药使用的是两套不同的XML schema。小分子药的靶点放在<targets>下,而生物药的靶点可能嵌套在<polypeptide>里。如果你直接用XPath一杆子打到底,会漏掉大量关系。嗯,这里一定要做分支处理。
drugbank:targets/drugbank:target,生物药走 drugbank:drugbank-polypeptide 下的 target 引用。
4.3 ClinicalTrials:真实世界的临床证据
如果说DrugBank告诉你能不能结合,ClinicalTrials就告诉你在人身上到底管不管用。这一步我在构建COVID-19知识图谱时特别看重,因为很多老药是在临床试验中才被发现有效的。
4.3.1 查询策略
我一般不会去爬全量数据,那太大了。通常的做法是,先用API按“COVID-19”作为Condition查询:
# 查询所有COVID-19相关的干预性临床试验 (JSON格式)
# 使用ClinicalTrials.gov API v2
curl "https://clinicaltrials.gov/api/query/study_fields?expr=COVID-19&fields=NCTId,BriefTitle,Condition,InterventionName,Phase,OverallStatus&min_rnk=1&max_rnk=100&fmt=json"
# 用jq提取药物干预列表
curl -s "https://clinicaltrials.gov/api/query/study_fields?expr=COVID-19&fields=InterventionName&fmt=json" | jq '.StudyFieldsResponse.StudyFields[] | .InterventionName[]'
返回的数据里,InterventionName字段经常会混入“Drug: Remdesivir”这样的格式。你需要做一次正则清洗才能映射到DrugBank的药物ID。这部分工作量很大,逃不掉的。
4.3.2 关键字段解析
| 字段 | 说明 | 在KG中的用途 |
|---|---|---|
NCTId |
试验唯一标识 | 作为“临床试验”节点的ID |
Phase |
Phase 1/2/3/4 | 指示证据级别 |
OverallStatus |
Completed / Recruiting | 指示活性状态 |
InterventionName |
药物干预名称 | 映射到药物节点 |
Condition |
疾病名称 | 映射到疾病节点 |
4.4 PubMed:非结构化证据的富矿
最后聊PubMed。说实话,这是最难处理的数据源,但也是信息最丰富的。DrugBank和ClinicalTrials给的是事实,PubMed给的则是上下文和机制解释。
4.4.1 检索与获取
我习惯用NCBI的E-utilities来做批量检索。先用ESearch找到相关文献ID,再用EFetch拿摘要。下面是我常用的三步走:
# 第一步:搜索COVID-19和相关药物的文献ID
curl "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed&term=COVID-19+AND+remdesivir&retmax=100&retmode=json"
# 第二步:获取摘要信息
curl "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=33258446,33258445&retmode=xml&rettype=abstract"
# 第三步:解析XML,提取PMID、Title、Abstract、MeshTerms
返回的XML结构比较复杂。我建议用Python的xml.etree.ElementTree或者BeautifulSoup来解析。核心是要提取AbstractText标签下的所有段落,再按标点符号拼回完整文本。
4.4.2 从摘要中提取关系
这一步是文本挖掘的活。对于COVID-19药物KG,我们主要关注三种语义关系:
- 治疗关系:文本中出现“treat COVID-19 with ...”
- 靶点关系:文本中出现“binds to ACE2”
- 疗效关系:文本中出现“reduced viral load”
我个人习惯的做法是先用规则匹配做一轮粗筛,再用预训练的BioBERT做精排。别一上来就上深度学习,成本太高,而且初期数据量不够的时候效果并不比规则好。
4.5 数据源整合框架图
下面这张SVG图,画的是三种数据源在知识图谱构建中的角色与数据流。你可以直观看到文本数据与结构化数据的汇合点。
4.6 数据获取与处理的实践技巧
说到底,数据源介绍得再清楚,最后还是得落到代码上。我把自己常用的Python工具链列在下面,你可以在项目中直接复用:
- DrugBank解析:
lxml+pandas,输出药物-靶点CSV - ClinicalTrials批量拉取:
ctg_utils(python包) 或直接请求AACT PostgreSQL dump - PubMed摘要提取:
biopython.Entrez+xmltodict - 命名实体对齐:用基本字符串匹配 + 标准API映射
unidecode对药物名做一次转写,然后使用最长的公共子串做模糊匹配,最后留一个手工审核队列兜底。