关于 chembl-database-bioactivity
chembl-database-bioactivity 是通过公开 REST API 查询 ChEMBL 化合物、靶点和生物活性数据的技能,面向药物发现与化学信息学研究。它使用 requests 即可调用 API,无需 SDK 或身份验证,并支持结构搜索及分页筛选。
主要功能
- 01按名称、编号和性质检索化合物
- 02查询靶点及生物活性记录
- 03按 SMILES 进行相似度与子结构搜索
- 04获取药物机制和适应症
- 05使用过滤条件和分页整理结果
适用场景
- 01查找特定靶点的抑制剂活性
- 02比较化合物系列的构效关系
- 03按药物相似性属性筛选分子
- 04检索已批准药物的机制与适应症
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill chembl-database-bioactivity安装后在 Claude Code 中输入/chembl-database-bioactivity确认已加载。
详细介绍
ChEMBL 数据库 — 生物活性查询
为什么没有 SDK?
chembl_webresource_client包为公开、无需身份验证的 REST/JSON API(地址为https://www.ebi.ac.uk/chembl/api/data/)提供了便捷的封装。当 SDK 不可用时,每项操作都可以通过普通的requests和 URL 参数复现。本 SKILL.md 全程使用 REST 接口,因此只要环境中安装了requests,代码就能运行。Django 风格的筛选语法(field__icontains=…、field__lte=…、field__range=a,b)可作为 URL 查询参数使用。
概述
ChEMBL 是 EMBL-EBI 的生物活性分子数据库:包含 200 多万种化合物、1,900 多万条生物活性测量数据(IC50、Ki、EC50、Kd 等)以及 1.3 万多个靶点。地址为 https://www.ebi.ac.uk/chembl/api/data/ 的 REST API 返回 JSON(追加 .json),也支持 XML/YAML;无需身份验证,并支持通过 URL 参数使用 Django 风格的查询筛选,以及通过 page_meta.next 进行游标式分页。
适用场景
- 按名称、ChEMBL ID 或理化性质查找化合物
- 查询特定靶点的生物活性数据(IC50、Ki、EC50)
- 使用 SMILES 执行相似性或子结构搜索
- 获取药物作用机制和临床适应症
- 识别针对某个靶点的抑制剂、激动剂或生物活性分子
- 分析化合物系列中的构效关系(SAR)
- 根据 Lipinski 五规则或其他类药性标准筛选分子
- 如需进行通用化学信息学处理(SMILES 操作、指纹、描述符),请改用
rdkit-cheminformatics - 如需使用其他化合物数据库(NIH,覆盖范围更广),请改用
pubchem-compound-search
前置条件
- Python 包:
requests(唯一必需项)。可选:用于表格分析的pandas。 - 无需 API 密钥:ChEMBL 可免费访问。
- 速率限制:未公布明确的硬性限制。基础设施为共享资源;在批量请求循环中,每次请求间加入
time.sleep(0.2-0.5);遇到 HTTP 429 时应退避。
pip install requests
# Optional, for DataFrame work:
pip install pandas
快速开始
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"
# Retrieve a molecule by ChEMBL ID
r = requests.get(f"{BASE}/molecule/CHEMBL25.json", timeout=15)
r.raise_for_status()
aspirin = r.json()
print(f"{aspirin['pref_name']}: MW={aspirin['molecule_properties']['mw_freebase']}")
# ASPIRIN: MW=180.16
# Search targets by full name (acronyms like 'EGFR' don't match pref_name — use full term)
r = requests.get(
f"{BASE}/target.json",
params={"pref_name__icontains": "epidermal growth factor receptor",
"target_type": "SINGLE PROTEIN", "limit": 5},
timeout=15,
)
targets = r.json()["targets"]
print(f"EGFR-like targets: {len(targets)}, first={targets[0]['target_chembl_id']}")
# Potent bioactivities: EGFR (CHEMBL203) IC50 <= 100 nM
r = requests.get(
f"{BASE}/activity.json",
params={"target_chembl_id": "CHEMBL203",
"standard_type": "IC50",
"standard_value__lte": 100,
"standard_units": "nM",
"limit": 5},
timeout=30,
)
data = r.json()
print(f"EGFR IC50 ≤ 100 nM records: {data['page_meta']['total_count']}")
核心概念
筛选运算符(Django 风格,作为 URL 参数使用)
SDK 的 field__operator=value 语法与 URL 查询参数一一对应。使用 & 组合筛选条件。
| 运算符 | URL 格式 | URL 片段示例 |
|---|---|---|
__exact | field=value | target_type=SINGLE+PROTEIN |
__iexact | field__iexact=value | pref_name__iexact=aspirin |
__contains / __icontains | field__icontains=value | pref_name__icontains=kinase |
__startswith / __endswith | field__startswith=Epi | pref_name__endswith=nib |
__gt / __gte / __lt / __lte | field__lte=100 | standard_value__lte=100 |
__range | field__range=lo,hi | molecule_properties__mw_freebase__range=300,500 |
__in | field__in=a,b,c | standard_type__in=IC50,Ki,Kd |
__isnull | field__isnull=False(Python 的 False/True 字符串) | pchembl_value__isnull=False |
__regex | field__regex=… | pref_name__regex=^EGF.*kinase$ |
__search | field__search=… | description__search=apoptosis |
通过 requests.get(..., params={...}) 传入参数时,库会自动处理 URL 编码(包括 __range 和 __in 中的逗号)。
核心端点
所有端点都接受 .json、.xml 或 .yaml 后缀。以下默认使用 JSON。
| 端点 URL | 返回内容 | 关键字段 |
|---|---|---|
/molecule/{chembl_id}.json | 按 ID 查询化合物 | pref_name、molecule_chembl_id、molecule_properties、molecule_structures |
/molecule.json?<filters> | 搜索化合物 | 分页的 molecules[] |
/target/{chembl_id}.json | 按 ID 查询靶点 | pref_name、target_type、organism、target_components |
/target.json?<filters> | 搜索靶点 | 分页的 targets[] |
/activity.json?<filters> | 生物活性记录 | 分页的 activities[] |
/assay.json?<filters> | 测定详情 | 分页的 assays[] |
/drug.json?<filters> | 已批准药物信息 | 分页的 drugs[];支持 /drug/{chembl_id}.json |
/mechanism.json?<filters> | 作用机制 | 分页的 mechanisms[] |
/drug_indication.json?<filters> | 治疗适应症 | 分页的 drug_indications[] |
/similarity/{smiles}/{tanimoto}.json | Tanimoto 相似度(0–100) | 分页的 molecules[],包含 similarity 字段 |
/substructure/{smiles}.json | 子结构搜索 | 分页的 molecules[] |
/image/{chembl_id}.svg | SVG 结构图像 | 二进制 SVG(非 JSON) |
/molecule_form/{chembl_id}.json | 母体/盐形式 | molecule_forms[] |
/protein_class.json | 蛋白质分类层级 | 分层浏览 |
/document.json?<filters> | 文献来源记录 | 分页的 documents[] |
响应结构
{
"page_meta": {
"limit": 20,
"offset": 0,
"total_count": 12145,
"next": "/chembl/api/data/activity.json?...&offset=20",
"previous": null
},
"activities": [ /* or molecules[], targets[], etc. */ ]
}
遍历 page_meta.next(相对 URL,需加上前缀 https://www.ebi.ac.uk),直到其值为 null。
分子属性
每条记录的 molecule_properties 中可访问以下属性:
| 字段 | 描述 |
|---|---|
mw_freebase | 分子量(游离碱) |
full_mwt | 完整分子量(包括盐) |
alogp | 计算得出的 LogP |
hba | 氢键受体数 |
hbd | 氢键供体数 |
psa | 极性表面积 |
rtb | 可旋转键数 |
num_ro5_violations | Lipinski 五规则违规数 |
ro3_pass | 是否符合三规则 |
cx_most_apka / cx_most_bpka | 最酸性/最碱性的 pKa |
靶点信息字段
| 字段 | 描述 |
|---|---|
target_chembl_id | ChEMBL 靶点标识符 |
pref_name | 首选(完整)靶点名称——缩写(如 “EGFR”)无法匹配;请使用拼写完整的名称 |
target_type | SINGLE PROTEIN、PROTEIN COMPLEX、ORGANISM 等 |
organism | 靶点生物(例如 Homo sapiens) |
tax_id | NCBI 分类 ID |
target_components[] | 组成部分(UniProt 登录号、序列等) |
生物活性数据字段
| 字段 | 描述 |
|---|---|
standard_type | 活性类型:IC50、Ki、Kd、EC50 等 |
standard_value | 数值型活性值 |
standard_units | 单位:nM、uM 等 |
pchembl_value | 归一化的 -log10 活性值(>6 表示效力强) |
activity_comment | 活性注释 |
data_validity_comment | 数据质量标记(分析前请检查) |
potential_duplicate | 重复标记 |
核心 API
1. 分子查询
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"
# By ChEMBL ID
r = requests.get(f"{BASE}/molecule/CHEMBL25.json", timeout=15)
aspirin = r.json()
print(f"{aspirin['pref_name']}: MW={aspirin['molecule_properties']['mw_freebase']}")
# By name (case-insensitive substring)
r = requests.get(f"{BASE}/molecule.json",
params={"pref_name__icontains": "imatinib", "limit": 5},
timeout=15)
for mol in r.json()["molecules"]:
print(f" {mol['molecule_chembl_id']} {mol.get('pref_name')!r}")
# By Lipinski-compliant property ranges
r = requests.get(f"{BASE}/molecule.json",
params={"molecule_properties__mw_freebase__range": "300,500",
"molecule_properties__alogp__lte": 5,
"molecule_properties__hba__lte": 10,
"molecule_properties__hbd__lte": 5,
"limit": 3},
timeout=15)
print(f"Lipinski-compliant total: {r.json()['page_meta']['total_count']}")
2. 靶点查询
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"
# By ChEMBL ID
r = requests.get(f"{BASE}/target/CHEMBL203.json", timeout=15)
egfr = r.json()
print(f"{egfr['pref_name']} ({egfr['organism']}) — type={egfr['target_type']}")
# Search by full name (NOT acronym) + type
r = requests.get(f"{BASE}/target.json",
params={"pref_name__icontains": "kinase",
"target_type": "SINGLE PROTEIN", "limit": 5},
timeout=15)
d = r.json()
print(f"Kinase SINGLE_PROTEIN targets: total={d['page_meta']['total_count']}")
for t in d["targets"][:5]:
print(f" {t['target_chembl_id']:12s} {t.get('pref_name')!r} ({t['organism']})")
# By organism
r = requests.get(f"{BASE}/target.json",
params={"organism": "Homo sapiens", "limit": 3},
timeout=15)
print(f"Human targets: total={r.json()['page_meta']['total_count']}")
3. 生物活性数据
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"
# Potent inhibitors for a target (EGFR = CHEMBL203)
r = requests.get(f"{BASE}/activity.json",
params={"target_chembl_id": "CHEMBL203",
"standard_type": "IC50",
"standard_value__lte": 100,
"standard_units": "nM",
"limit": 5},
timeout=30)
data = r.json()
print(f"EGFR IC50≤100nM: total={data['page_meta']['total_count']}")
for act in data["activities"][:5]:
print(f" {act['molecule_chembl_id']:14s} IC50={act['standard_value']} nM "
f"pChEMBL={act.get('pchembl_value')}")
# All pChEMBL-tagged activities for a compound
r = requests.get(f"{BASE}/activity.json",
params={"molecule_chembl_id": "CHEMBL25",
"pchembl_value__isnull": "False",
"limit": 5},
timeout=30)
print(f"Aspirin pChEMBL activities: total={r.json()['page_meta']['total_count']}")
# Multiple activity types (CHEMBL240 = D2 dopamine receptor)
r = requests.get(f"{BASE}/activity.json",
params={"target_chembl_id": "CHEMBL240",
"standard_type__in": "IC50,Ki,Kd",
"limit": 5},
timeout=30)
print(f"D2 receptor IC50/Ki/Kd: total={r.json()['page_meta']['total_count']}")
4. 基于结构的搜索
import requests
from urllib.parse import quote
BASE = "https://www.ebi.ac.uk/chembl/api/data"
# Similarity search (Tanimoto ≥ 85%)
# Path-style endpoint: /similarity/{smiles}/{threshold}
# The SMILES MUST be URL-encoded (it contains '/', '(', ')' etc.)
aspirin_smiles = quote("CC(=O)Oc1ccccc1C(=O)O", safe="")
r = requests.get(f"{BASE}/similarity/{aspirin_smiles}/85.json",
params={"limit": 5}, timeout=30)
data = r.json()
print(f"Similar to aspirin (≥85% Tanimoto): total={data['page_meta']['total_count']}")
for m in data["molecules"][:5]:
print(f" {m['molecule_chembl_id']} similarity={m.get('similarity')}")
# Substructure search
benzimidazole = quote("c1ccc2[nH]cnc2c1", safe="")
r = requests.get(f"{BASE}/substructure/{benzimidazole}.json",
params={"limit": 3}, timeout=30)
print(f"Benzimidazole substructure total: {r.json()['page_meta']['total_count']}")
5. 药物和作用机制数据
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"
# Drug record (max clinical phase, ATC class, etc.)
r = requests.get(f"{BASE}/drug/CHEMBL941.json", timeout=15) # imatinib
drug = r.json()
print(f"Imatinib max_phase={drug.get('max_phase')}")
# Mechanisms of action — note: not every drug has mechanism records.
# Imatinib (CHEMBL941) returns 0 mechanism rows; sunitinib (CHEMBL535) has many.
r = requests.get(f"{BASE}/mechanism.json",
params={"molecule_chembl_id": "CHEMBL535"}, timeout=15)
for m in r.json()["mechanisms"]:
print(f" {m['mechanism_of_action']} → target {m.get('target_chembl_id')}")
# Therapeutic indications
r = requests.get(f"{BASE}/drug_indication.json",
params={"molecule_chembl_id": "CHEMBL941", "limit": 5},
timeout=15)
for ind in r.json()["drug_indications"]:
print(f" {ind.get('mesh_heading')!r} max_phase_for_ind={ind.get('max_phase_for_ind')}")
# SVG molecular structure image — direct binary response, NOT JSON
# Do NOT call /image/{cid}.json — that endpoint raises JSONDecodeError.
r = requests.get(f"{BASE}/image/CHEMBL25.svg", timeout=15)
r.raise_for_status()
with open("aspirin.svg", "w") as f:
f.write(r.text)
print(f"Saved aspirin.svg ({len(r.text)} bytes, looks_svg={'<svg' in r.text})")
常见工作流
工作流 1:查找靶点抑制剂
注意: pref_name__icontains 会匹配拼写完整的名称。缩写(如 'EGFR' 或 'BRAF')会返回 0 条结果;请使用 'epidermal growth factor receptor' 或 'B-raf'(带连字符)。
import requests, pandas as pd, time
BASE = "https://www.ebi.ac.uk/chembl/api/data"
# Step 1: Resolve the target by full name
r = requests.get(f"{BASE}/target.json",
params={"pref_name__icontains": "B-raf",
"target_type": "SINGLE PROTEIN", "limit": 5},
timeout=15)
targets = r.json()["targets"]
human_braf = next(t for t in targets if t["organism"] == "Homo sapiens")
target_id = human_braf["target_chembl_id"]
print(f"Using {target_id} — {human_braf['pref_name']}")
# Step 2: Paginate all potent IC50 activities (cap at 500 for demo)
url = (f"{BASE}/activity.json"
f"?target_chembl_id={target_id}"
f"&standard_type=IC50"
f"&standard_value__lte=100"
f"&standard_units=nM"
f"&pchembl_value__isnull=False"
f"&limit=200")
records = []
while url and len(records) < 500:
r = requests.get(url, timeout=30)
r.raise_for_status()
data = r.json()
records.extend(data["activities"])
nxt = data["page_meta"].get("next")
url = f"https://www.ebi.ac.uk{nxt}" if nxt else None
time.sleep(0.2)
df = pd.DataFrame(records)
df["standard_value"] = pd.to_numeric(df["standard_value"])
print(f"Retrieved {len(df)} potent {target_id} compounds")
print(df[["molecule_chembl_id", "standard_value", "pchembl_value"]].head(10))
工作流 2:分析已知药物
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"
# Sunitinib (CHEMBL535) — has documented mechanisms + indications.
# Imatinib (CHEMBL941) sometimes returns 0 mechanism rows depending on ChEMBL release.
chembl_id = "CHEMBL535"
# Molecule record
m = requests.get(f"{BASE}/molecule/{chembl_id}.json", timeout=15).json()
print(f"Name: {m['pref_name']}")
print(f"MW : {m['molecule_properties']['mw_freebase']}")
# Mechanisms
mechs = requests.get(f"{BASE}/mechanism.json",
params={"molecule_chembl_id": chembl_id},
timeout=15).json()["mechanisms"]
for mc in mechs:
print(f" Mechanism: {mc['mechanism_of_action']}")
# Indications
inds = requests.get(f"{BASE}/drug_indication.json",
params={"molecule_chembl_id": chembl_id, "limit": 5},
timeout=15).json()["drug_indications"]
for ind in inds:
print(f" Indication: {ind.get('mesh_heading')} "
f"(Phase {ind.get('max_phase_for_ind')})")
# Bioactivity record count
total = requests.get(f"{BASE}/activity.json",
params={"molecule_chembl_id": chembl_id,
"pchembl_value__isnull": "False",
"limit": 1},
timeout=30).json()["page_meta"]["total_count"]
print(f"Total bioactivity records (pChEMBL-tagged): {total}")
工作流 3:构效关系研究
import requests, pandas as pd, time
from urllib.parse import quote
BASE = "https://www.ebi.ac.uk/chembl/api/data"
# Step 1: Similar compounds to a lead (e.g., quinoline scaffold)
lead_smiles = "c1ccc2c(c1)cc(nc2N)c3ccc(cc3)NC(=O)c4ccccc4"
r = requests.get(f"{BASE}/similarity/{quote(lead_smiles, safe='')}/80.json",
params={"limit": 20}, timeout=30)
analogs = r.json()["molecules"]
print(f"Analogs found: {len(analogs)}")
# Step 2: Collect bioactivities for each analog
records = []
for compound in analogs[:20]:
cid = compound["molecule_chembl_id"]
acts = requests.get(f"{BASE}/activity.json",
params={"molecule_chembl_id": cid,
"standard_type": "IC50",
"pchembl_value__isnull": "False",
"limit": 20},
timeout=30).json()["activities"]
for act in acts:
records.append({
"chembl_id": cid,
"target": act.get("target_pref_name"),
"IC50_nM": act.get("standard_value"),
"pchembl": act.get("pchembl_value"),
"mw": (compound.get("molecule_properties") or {}).get("mw_freebase"),
"alogp": (compound.get("molecule_properties") or {}).get("alogp"),
})
time.sleep(0.2)
df = pd.DataFrame(records)
if not df.empty:
df["IC50_nM"] = pd.to_numeric(df["IC50_nM"])
print(df.groupby("target")["IC50_nM"].describe())
常见示例
示例:虚拟筛选过滤器(Lipinski 五规则)
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"
r = requests.get(f"{BASE}/molecule.json",
params={"molecule_properties__mw_freebase__range": "300,500",
"molecule_properties__alogp__lte": 5,
"molecule_properties__hba__lte": 10,
"molecule_properties__hbd__lte": 5,
"molecule_properties__num_ro5_violations": 0,
"limit": 1},
timeout=15)
print(f"Drug-like candidates: {r.json()['page_meta']['total_count']}")
示例:将活性数据分页导出为 CSV
import requests, pandas as pd, time
BASE = "https://www.ebi.ac.uk/chembl/api/data"
url = (f"{BASE}/activity.json"
f"?target_chembl_id=CHEMBL203"
f"&standard_type=IC50"
f"&pchembl_value__isnull=False"
f"&limit=500")
all_acts = []
while url:
r = requests.get(url, timeout=60)
r.raise_for_status()
data = r.json()
all_acts.extend(data["activities"])
nxt = data["page_meta"].get("next")
url = f"https://www.ebi.ac.uk{nxt}" if nxt else None
time.sleep(0.3)
df = pd.DataFrame(all_acts)
df.to_csv("egfr_activities.csv", index=False)
print(f"Exported {len(df)} records → egfr_activities.csv")
示例:配置带重试机制的稳健会话
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
def chembl_session(retries=3, backoff=1.0):
s = requests.Session()
s.headers.update({"Accept": "application/json"})
s.mount("https://", HTTPAdapter(max_retries=Retry(
total=retries, backoff_factor=backoff,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["GET"])))
return s
session = chembl_session()
r = session.get("https://www.ebi.ac.uk/chembl/api/data/molecule/CHEMBL25.json", timeout=15)
print(r.json()["pref_name"])
示例:下载 SVG 结构图像
import requests
r = requests.get("https://www.ebi.ac.uk/chembl/api/data/image/CHEMBL25.svg", timeout=15)
r.raise_for_status()
with open("aspirin.svg", "w") as f:
f.write(r.text)
关键参数
| 参数 | 端点 | 默认值 | 说明 |
|---|---|---|---|
limit | 所有列表端点 | 20 | 每页大小;最大为 1000 |
offset | 所有列表端点 | 0 | 分页偏移量(或跟随 page_meta.next) |
format | 所有端点 | json(通过 .json 后缀) | 也支持 .xml、.yaml |
pref_name__icontains | /target、/molecule | — | 完整名称中的子字符串;不匹配缩写,请使用完整名称 |
target_chembl_id | /activity | — | 例如:CHEMBL203(EGFR)、CHEMBL240(D2 受体) |
molecule_chembl_id | /activity、/mechanism、/drug_indication | — | 例如:CHEMBL25(阿司匹林) |
standard_type | /activity | — | IC50、Ki、Kd、EC50 |
standard_value__lte | /activity | — | 活性值上限(与 standard_units 搭配使用) |
pchembl_value__isnull | /activity | — | 使用 "False" 要求数据带有 pChEMBL 标记 |
target_type | /target | — | SINGLE PROTEIN、PROTEIN COMPLEX、ORGANISM、… |
{tanimoto}(路径) | /similarity/{smiles}/{tanimoto} | — | Tanimoto 阈值,范围为 0–100 |
{smiles}(路径) | /similarity、/substructure | — | URL 编码的 SMILES(urllib.parse.quote(s, safe="")) |
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
pref_name__icontains=EGFR(或 BRAF)返回 0 条结果 | ChEMBL 存储的是完整名称;不匹配缩写 | 使用 "epidermal growth factor receptor";查询 BRAF 时,使用带连字符的 "B-raf" |
mechanism.json?molecule_chembl_id=CHEMBL941 返回空结果 | 并非每种药物在每个版本中都有机制记录(例如,当前数据中伊马替尼有 0 条记录) | 使用 CHEMBL535(舒尼替尼)或 CHEMBL192(西地那非)作为已知有数据的示例 |
/image/{cid}.json 出现 JSONDecodeError | 图像端点返回的是二进制数据,而非 JSON | 始终使用 .svg 或 .png 后缀:/image/{cid}.svg |
/molecule/{id} 返回 404 | ChEMBL ID 格式无效 | ID 必须包含前缀:CHEMBL25,而非 25 |
| 相似性搜索返回 400 | SMILES 未编码(/ 会与 URL 路径冲突) | 进行 URL 编码:urllib.parse.quote(smiles, safe="") |
next 页为空,但 total_count 更高 | 已达到内部上限(使用 offset 分页时通常为 10000) | 缩小筛选范围(日期范围、靶标类别)并重新分页;或使用 ChEMBL FTP 下载获取超过 100K 条记录 |
HTTP 429 Too Many Requests | 请求过于密集 | 添加 time.sleep(0.3);挂载 Retry 适配器(参见示例) |
activity 记录中的单位混杂 | 不同实验报告的单位为 nM / µM / % inhibition | 筛选 standard_units="nM",并优先使用 pchembl_value 进行跨实验比较 |
data_validity_comment 不为空 | 数据整理标记(例如,“可能存在转录错误”“超出典型范围”) | 在进行 SAR / 回归分析前剔除这些行 |
| 活性记录重复 | 同一测量值由多个来源报告 | 检查 potential_duplicate=True 并去重 |
最佳实践
- 使用
pchembl_value进行跨研究比较——它会将 IC50/Ki/EC50 标准化为可比较的 -log10 刻度。 - 计算汇总值前务必检查
data_validity_comment——带标记的行可能会使分布产生偏差。 - 在活性查询中固定
standard_units="nM",避免混用 nM 和 µM。 - 使用
page_meta.next进行分页,不要手动递增offset——该 URL 已包含正确的游标。 - 在路径式端点(
/similarity/{smiles}/...、/substructure/{smiles})中对 SMILES 进行 URL 编码,使用urllib.parse.quote(smi, safe="")。 - 批量处理时使用带重试适配器的
Session(参见 Recipe)——ChEMBL 可以处理相当大的流量,但偶尔会返回 502/503。 - 对于超过 100K 条记录,优先使用 ChEMBL FTP 下载,而不是分页 API 调用。
- 谨慎使用
pref_name__icontains中的首字母缩写——EGFR、BRAF、HER2都会返回 0 条结果。请使用完整术语,或通过target_components__accession=<UniProt>进行筛选。
相关技能
rdkit-cheminformatics— SMILES 操作、指纹、描述符datamol-cheminformatics— 分子预处理与特征化pubchem-compound-search— 备用化合物数据库(NIH;覆盖范围更广,但生物活性信息较少)pdb-database— 通过 RCSB PDB REST API 获取 ChEMBL 靶点的 3D 结构opentargets-database— 将 ChEMBL 药物-靶点证据与疾病关联相链接
参考资料
- ChEMBL 网站:https://www.ebi.ac.uk/chembl/
- REST API 根地址:https://www.ebi.ac.uk/chembl/api/data/
- API 文档:https://www.ebi.ac.uk/chembl/api/data/docs
- 接口文档(Django 筛选语法):https://chembl.gitbook.io/chembl-interface-documentation/web-services
- 批量下载(适用于超过 100K 条记录):https://chembl.gitbook.io/chembl-interface-documentation/downloads
- 如需基于 SDK 的用法,请参阅 PyPI 软件包
chembl_webresource_client;此 SKILL.md 直接使用底层 REST API,因此无需安装 SDK。