4. 药物与靶点数据获取

药物重定位的第一步不是建模,而是把“药—靶—疾病”三类实体及其证据从多个公共数据源中稳定地取回来。不同数据源的定位差异很大:DrugBank 偏药物与靶点的机制注释,ChEMBL 偏活性测定与化合物结构,TTD 偏已知和潜在的治疗靶点关系,PubChem 偏化合物身份、生物测定与文献关联。若把它们当成同质数据直接拼接,后续会出现 ID 冲突、活性单位混乱、靶点命名不一致等问题。因此本节的核心任务是:理解各源的数据模型与接口,设计可复现的采集流程,并在入库前完成标识归一与证据标注。

一、四个数据源的角色分工

DrugBank 以 DrugCard 为中心,提供药物通用名、商品名、CAS、适应症、作用靶点、酶、转运体和通路信息,其 drug_target 关系带有作用类型(激动、拮抗、抑制剂等)和已知/预测标记,适合构建药物—靶点机制边。ChEMBL 以化合物(molecule_chembl_id)和靶点(target_chembl_id)为核心,通过 activities 表记录 standard_type、standard_value、standard_units、pChEMBL 等标准化活性,是定量证据的主要来源。TTD 聚焦药物—靶点—疾病三元关系,区分“已上市”“临床”“研究”等开发阶段,适合补充治疗方向。PubChem 则以 CID 为化合物主键,提供 BioAssay 活性结果和 Substance 来源信息,常用于结构去重与活性交叉验证。

四源采集与归一化数据流 DrugBank DrugCard / 靶点机制 作用类型 · 已知/预测 XML 全量下载 ChEMBL molecule / target activities 标准化活性 REST API / SQL dump TTD 药物—靶点—疾病 开发阶段标注 文本/表格下载 PubChem CID / BioAssay 结构去重 · 活性交叉 PUG-REST / FTP 采集适配层:分页请求 · 限速重试 · 原始快照落盘(保留 source_id 与采集时间) 每个源独立解析器,输出统一中间格式:drug_raw / target_raw / activity_raw 标识归一与证据整合层 药物:InChIKey / CAS / 名称 → 统一 drug_uid 靶点:UniProt AC / 基因名 → 统一 target_uid 活性:单位换算为 nM,保留 pChEMBL;冲突记录标记来源优先级与置信度 标准化关系表:drug_target_evidence 字段:drug_uid · target_uid · relation_type · standard_value · unit · source · evidence_level 可直接供后续重定位打分与网络构建使用

二、采集前的关键约定

在写采集脚本之前,先固定三件事。第一是主键策略:药物以 InChIKey 为结构主键、CAS 为化学主键、通用名为展示名;靶点以 UniProt AC 为蛋白主键、基因名为常用别名。第二是活性单位:ChEMBL 的 standard_units 常见为 nM,若出现 µM 或 mg/mL,需统一换算为 nM 后再比较,并保留原始值。第三是证据等级:把“已上市药物的已知靶点”与“细胞实验预测靶点”分开标注,避免后续把弱证据当成强证据。

三、以 ChEMBL 为例的采集实现

ChEMBL 提供 REST API,适合按靶点或按化合物增量拉取。下面示例按靶点拉取其活性记录,并只保留人源、结合实验、有标准值的数据。示例参数为教学假设,实际使用时需替换为真实靶点 ID。

import requests, time

BASE = "https://www.ebi.ac.uk/chembl/api/data"
target_id = "CHEMBL203"   # 示例:EGFR

def fetch_activities(target_id, limit=1000):
    url = f"{BASE}/activity.json"
    params = {
        "target_chembl_id": target_id,
        "standard_type__in": "IC50,Ki,Kd",
        "standard_units": "nM",
        "assay_organism": "Homo sapiens",
        "limit": limit,
        "offset": 0
    }
    rows = []
    while True:
        r = requests.get(url, params=params, timeout=30)
        r.raise_for_status()
        data = r.json()
        rows.extend(data["activities"])
        if not data["page_meta"]["next"]:
            break
        params["offset"] += limit
        time.sleep(0.3)   # 限速,避免触发封禁
    return rows

acts = fetch_activities(target_id)
print(len(acts), acts[0]["molecule_chembl_id"], acts[0]["standard_value"])

返回记录中需要重点保留的字段包括:molecule_chembl_id、target_chembl_id、standard_type、standard_value、standard_units、pchembl_value、assay_chembl_id、document_chembl_id。其中 pchembl_value 是 ChEMBL 已按 -log10(mol/L) 换算的负对数活性,可直接用于跨实验比较;若为空,则用 standard_value 自行换算。

四、多源合并时的冲突处理

同一药物—靶点对可能同时出现在多个源中,且活性值不同。常见处理顺序是:先按 drug_uid + target_uid + relation_type 分组;组内优先保留 ChEMBL 的定量活性,DrugBank 提供机制类型,TTD 提供疾病方向,PubChem 用于结构确认。若同一组内出现多个活性值,取中位数或最优值,并记录来源数量作为置信度。对于只有 DrugBank 预测关系、没有实验活性的边,标记为低证据等级,不参与定量排序。

采集时务必保存原始响应快照(JSON/XML)与采集时间戳。公共数据库会更新,保留快照才能在结果异常时回溯是数据变化还是解析逻辑变化。

五、采集结果的自检清单

  • 药物主键是否可解析:InChIKey 缺失时能否回退到 CAS 或名称匹配。
  • 靶点主键是否唯一:同一 UniProt AC 是否被不同基因名重复映射。
  • 活性单位是否统一:是否存在 µM、mg/mL 未换算的记录。
  • 证据来源是否可追溯:每条边是否保留 source 与原始记录 ID。
  • 重复边是否已合并:同一药物—靶点对是否因不同实验被重复计数。

完成上述步骤后,得到的 drug_target_evidence 表即可作为后续重定位打分的基础输入。下一阶段将在此基础上引入疾病关联与网络传播,但前提是本节的数据采集与归一化已经稳定、可复现。