何时使用
适用:
- 把化合物在 ChEMBL、DrugBank、PubChem、ChEBI、PDB(RCSB/PDBe)、SureChEMBL、HMDB、DrugCentral、BindingDB 等 20+ 公开库间的 ID 互转。
- 用标准 InChIKey 解析到某化合物出现的全部库及其各自 ID。
- 已知某库 source ID(如
CHEMBL192)反查其全部交叉引用。 - 按连接性(connectivity)找同骨架但立体/盐/同位素/质子化不同的结构相关物。
- 合并多库数据集前校验化合物身份;为药物发现项目搭交叉引用表(把 ChEMBL 活性数据接到 PDB 结构数据)。
- 按 InChIKey 检查合成物/供应商化合物是否存在于任一公开库。
不该用(负边界):
- 取完整生物活性(IC50/Ki/Kd)——用
chembl-bioactivity-database;UniChem 只给 ID 交叉引用,不含实验数据。 - 性质预测、子结构/相似性搜索、本地指纹描述符——用
pubchem-compound-search、cheminformatics-toolkit;UniChem 仅做标识符翻译。
步骤 / 指令
API 根:https://www.ebi.ac.uk/unichem/api/v1,无需 API key,限速约 10 req/s(批量循环加 time.sleep(0.1))。
- 除
/sources外全部用 POST:GET /compounds返回 405;GET /compounds/{src}/{id}、GET /connectivity/{key}返回 404。唯一 GET 端点是/sources。 - 三类查询选端点:
- InChIKey → 全部库:
POST /compounds,body{"type":"inchikey","compound":"<27 字 InChIKey>"}。 - 某库 ID → 全部库:
POST /compounds,body{"type":"sourceID","compound":"CHEMBL192","sourceID":1}。 - 结构相关物:
POST /connectivity,body 同 InChIKey 形式。
- InChIKey → 全部库:
- 读返回时用对字段名(最高频错误):
POST /compounds、POST /connectivity返回的sources列表里每条命中的库标识符是id(小写),不是sourceID;只有GET /sources目录里才用sourceID(大写 ID)。迭代命中用src["id"],迭代目录用s["sourceID"]。 - 必须传完整 27 字标准 InChIKey:
/connectivity拒绝 14 字连接性片段,返回{"response":"Not found"};UniChem 内部自行剥离立体/电荷层。 - 无批量端点:body 传
{"compounds":[...]}或{"inchikeys":[...]}返回 400illegal_argument_exception。多输入须逐条 POST 循环。 - 只索引标准 InChIKey:非标准 InChIKey 查无结果,先用 RDKit
MolToInchiKey(mol)规范化。 - 精确查不到就退连接性:若你手上是游离酸/碱 InChIKey 而库里收的是盐(如盐酸盐),
/compounds会漏,改跑/connectivity兜底。 - 缓存 source 表:启动时调一次
/sources建{sourceID: nameLabel}字典,别硬编码 ID。 /connectivity在常见骨架上较慢,timeout提到 30s。
常用 source ID(以 /sources 实时核对为准)
| ID | 库 | ID | 库 |
|---|---|---|---|
| 1 | ChEMBL | 15 | SureChEMBL(专利) |
| 2 | DrugBank | 18 | HMDB |
| 3 | RCSB PDB | 22 | PubChem |
| 5 | PDBe | 31 | BindingDB |
| 7 | ChEBI | 34 | DrugCentral |
| 14 | FDA SRS | 49 | Probes-and-Drugs |
示例
通用 POST 助手 + InChIKey 查全部库:
import requests, pandas as pd
UNICHEM = "https://www.ebi.ac.uk/unichem/api/v1"
def lookup_by_inchikey(inchikey: str) -> pd.DataFrame:
"""返回某 InChIKey 在各库的全部交叉引用。"""
r = requests.post(f"{UNICHEM}/compounds",
json={"type": "inchikey", "compound": inchikey}, timeout=20)
r.raise_for_status()
compounds = r.json().get("compounds", [])
if not compounds:
return pd.DataFrame()
rows = [{"source_id": s["id"], "short_name": s.get("shortName", ""),
"compound_id": s["compoundId"]} # 注意是 s["id"],不是 s["sourceID"]
for s in compounds[0].get("sources", [])]
return pd.DataFrame(rows).sort_values("source_id")
df = lookup_by_inchikey("XEFQLINVKFYRCS-UHFFFAOYSA-N") # triclosan
# ChEMBL=CHEMBL849, DrugBank=DB08604, RCSB PDB=TCL, ChEBI=CHEBI:164200 ...
按某库 ID 反查(type=sourceID):
body = {"type": "sourceID", "compound": "CHEMBL192", "sourceID": 1} # sildenafil, from ChEMBL
sources = requests.post(f"{UNICHEM}/compounds", json=body, timeout=20).json()["compounds"][0]["sources"]
连接性搜索(同骨架的盐/立体异构/外消旋体):
def connectivity_search(inchikey: str) -> dict:
"""传完整 27 字 InChIKey;返回 totalCompounds/totalSources 与扁平 sources 列表,每条带 comparison 层匹配信息。"""
r = requests.post(f"{UNICHEM}/connectivity",
json={"type": "inchikey", "compound": inchikey}, timeout=30)
r.raise_for_status()
return r.json()
data = connectivity_search("PJVWKTKQMONHTI-UHFFFAOYSA-N") # warfarin
print(data["totalCompounds"], "unique compounds,", data["totalSources"], "records")
# 每条 src["comparison"] 含 stereoSp3 / protonation / isotope,可筛"骨架同、立体异"的相关物
批量翻译(无批量端点,逐条循环 + 限速):
import time
def batch_translate(inchikeys, target=(1, 2, 7, 22)): # ChEMBL/DrugBank/ChEBI/PubChem
rows = []
for ik in inchikeys:
row = {"inchikey": ik}
try:
c = requests.post(f"{UNICHEM}/compounds",
json={"type": "inchikey", "compound": ik}, timeout=20).json().get("compounds", [])
hits = {s["id"]: s["compoundId"] for s in c[0]["sources"]} if c else {}
for sid in target:
row[f"src_{sid}"] = hits.get(sid)
except requests.RequestException as e:
row["error"] = str(e)
rows.append(row); time.sleep(0.1) # 尊重 ~10 req/s
return pd.DataFrame(rows)
列出全部数据源(唯一 GET 端点,目录里用大写 sourceID):
srcs = requests.get(f"{UNICHEM}/sources", timeout=15).json()["sources"]
src_map = {s["sourceID"]: s.get("nameLabel", str(s["sourceID"])) for s in srcs}
注意事项
idvssourceID是头号坑:命中记录读src["sourceID"]会KeyError,只能用src["id"];sourceID仅存在于/sources目录。- InChIKey 结构:27 字分三段——前 14 字连接性层(重原子与键),中 8 字立体与电荷,末 1 字版本标志。
/compounds要求标准 InChIKey 完全一致(同立体/盐/同位素);/connectivity只比连接性层。 - 连接性结果可能过多:同骨架常匹配大量 SureChEMBL 专利 ID——按
src["id"]==15过滤掉,或按comparison.stereoSp3==True收窄。 - 空结果排查:非标准 InChIKey、盐型不符或库未收。先 RDKit 校验 InChIKey,再退
/connectivity捕捉盐/立体变体。 - URL/超时:
/connectivity慢时把timeout提到 30s,429/503 退避重试一次;部分 source 不提供 url 模板,需用/sources的baseIdUrl拼compoundId手工构链。 - PubChem CID → InChIKey 起步:手上只有 CID 时,先经 PubChem PUG-REST
compound/cid/{cid}/property/InChIKey/JSON取 InChIKey,再喂给 UniChem。
互见
- requires:(无)
- related:
pubchem-compound-search—— 拿到 PubChem CID 后查性质/同义词;scientific-database-lookup—— 更广的多库 REST 取数总入口;cheminformatics-toolkit—— 本地 RDKit 规范化 InChIKey/SMILES。 - combines_with:
chembl-bioactivity-database—— 用 UniChem 解出的 ChEMBL ID 拉 IC50/Ki 活性;autodock-vina-docking—— 用解出的 PDB 配体码取共晶结构做对接;deepchem-drug-discovery—— 跨库 ID 对齐后喂入建模管线。
采编自 jaechang-hits/SciAgent-Skills(CC-BY-4.0)。