关于 pubchem-compound-search
PubChem Compound Search 是通过公开的 PUG-REST JSON API 查询 PubChem 的 Python 技能,面向化学和生物医学工作流。它直接使用 requests 获取标识符、性质、结构、同义词和测定摘要,无需 API 密钥。
主要功能
- 01解析名称和化学标识符
- 02批量获取化合物性质
- 03按相似性或子结构搜索
- 04获取同义词和描述
- 05查询测定摘要并下载结构
适用场景
- 01比较一组化合物的性质
- 02查找先导化合物的类似物
- 03筛选含特定结构基序的化合物
- 04下载结构供后续分析
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill pubchem-compound-search安装后在 Claude Code 中输入/pubchem-compound-search确认已加载。
详细介绍
PubChem 化合物搜索
概述
PubChem(NCBI)是最大的免费化学数据库,包含 1.1 亿多个化合物、2.8 亿多个物质和数百万条生物测定记录。其 PUG-REST JSON API 是标准的编程接口,这里的所有示例都通过普通的 requests 直接使用该接口。无需使用 Python pubchempy 封装;PUG-REST 的 URL 语法足够简单,直接调用更加透明,也更容易重试和缓存,还能避免沙盒依赖问题(该库未列入 TOOL_STATUS.md)。
URL 模式固定且可预测:
https://pubchem.ncbi.nlm.nih.gov/rest/pug/<input>/<operation>/<output>
<input>=compound/{name,cid,smiles,inchikey,formula}/<value><operation>=cids、property/<list>、synonyms、description、assaysummary、JSON(完整记录)、SDF、PNG<output>=JSON、CSV、TXT、SDF、PNG
对于耗时较长的操作(相似性、子结构、分子式),API 会返回 HTTP 202 + {"Waiting": {"ListKey": "..."}};轮询 compound/listkey/{key}/cids/JSON,直到返回 IdentifierList。本技能会在模块 4 中处理此模式。
适用场景
- 按名称、SMILES、InChIKey 或分子式查询化合物,以获取其 PubChem CID
- 在单个请求中检索一个或多个 CID 的分子属性(分子量、XLogP、TPSA、氢键供体/受体数量、可旋转键、分子式、IUPAC 名称)
- 通过 Tanimoto 相似性查找结构相似的化合物(异步轮询 ListKey)
- 搜索含有特定子结构/药效团基序的化合物
- 获取某个 CID 的所有同义词/商品名/CAS 号
- 获取化合物的测定结果汇总表(筛选实验中的活性/非活性结果)
- 在一次 API 调用中转换不同标识符格式(名称 ↔ CID ↔ SMILES ↔ InChI ↔ InChIKey)
- 下载 2D SDF 或 PNG 结构图,用于插图或后续 RDKit 处理
- 如需本地化学信息学处理(指纹、描述符、3D 构象体、骨架提取),请使用
rdkit - 如需更深入的生物活性/靶点结合数据(针对特定靶点的 IC50、Ki),请使用
chembl-database-bioactivity
前提条件
- Python 包:
requests、pandas——标准环境中均已提供 - 无需 API 密钥——PubChem 完全公开
- 速率限制:每个 IP 每秒最多 5 个请求、每分钟最多 400 个请求。在循环中使用
time.sleep(0.25)控制请求频率;返回代码 503 表示触发了限制。
如果你使用的 pixi/conda 环境已提供 requests 和 pandas,则无需安装,可使用 pixi run python ... 调用脚本。
pip install requests pandas
快速入门
import requests
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
# name → CID
cid = requests.get(f"{BASE}/compound/name/aspirin/cids/JSON").json()["IdentifierList"]["CID"][0]
# CID → properties (single call, many fields)
r = requests.get(
f"{BASE}/compound/cid/{cid}/property/"
"MolecularWeight,XLogP,TPSA,HBondDonorCount,HBondAcceptorCount,SMILES,IUPACName/JSON")
p = r.json()["PropertyTable"]["Properties"][0]
print(f"CID {cid} — {p['IUPACName']}")
print(f" MW={p['MolecularWeight']} XLogP={p['XLogP']} TPSA={p['TPSA']}")
print(f" HBD={p['HBondDonorCount']} HBA={p['HBondAcceptorCount']}")
print(f" SMILES={p['SMILES']}")
核心 API
模块 1:标识符查询
通过 /compound/{namespace}/{value}/cids/JSON 将任意外部标识符解析为 PubChem CID。命名空间包括:name、cid、smiles、inchikey、inchi、formula。
import requests
from urllib.parse import quote
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
# By name (returns all matching CIDs as a list)
cids = requests.get(f"{BASE}/compound/name/caffeine/cids/JSON").json()["IdentifierList"]["CID"]
print(f"caffeine CIDs: {cids}")
# By canonical SMILES (URL-encode!)
smi = quote("CC(=O)OC1=CC=CC=C1C(=O)O", safe="")
cid = requests.get(f"{BASE}/compound/smiles/{smi}/cids/JSON").json()["IdentifierList"]["CID"][0]
print(f"aspirin SMILES → CID {cid}")
# By InChIKey (exact match, fastest if you already have one)
ikey = "BSYNRYMUTXBXSQ-UHFFFAOYSA-N"
cid = requests.get(f"{BASE}/compound/inchikey/{ikey}/cids/JSON").json()["IdentifierList"]["CID"][0]
print(f"InChIKey → CID {cid}")
模块 2:属性检索
/compound/cid/{cid_or_csv}/property/<csv-list>/JSON 可在一次请求中返回所有所需属性。CID 和属性名称都可以用 CSV 格式组合——一次最多可批量查询约 200 个 CID 和多个属性。
import requests
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
# Full property set for a single compound (ibuprofen CID 3672)
url = (f"{BASE}/compound/cid/3672/property/"
"MolecularWeight,XLogP,TPSA,HBondDonorCount,HBondAcceptorCount,"
"RotatableBondCount,SMILES,InChIKey,IUPACName,MolecularFormula/JSON")
p = requests.get(url).json()["PropertyTable"]["Properties"][0]
print(f"{p['IUPACName']} formula={p['MolecularFormula']}")
print(f" MW={p['MolecularWeight']} XLogP={p['XLogP']} TPSA={p['TPSA']}")
print(f" HBD={p['HBondDonorCount']} HBA={p['HBondAcceptorCount']} RotB={p['RotatableBondCount']}")
import requests, pandas as pd
# Batch: 4 CIDs, 3 properties — one request, one round trip
cids = "2244,3672,2157,2662" # aspirin, ibuprofen, naproxen, celecoxib
r = requests.get(
f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/{cids}/property/"
"MolecularWeight,XLogP,TPSA/JSON")
df = pd.DataFrame(r.json()["PropertyTable"]["Properties"])
print(df.to_string(index=False))
模块 3:同义词和描述
同义词(商品名、CAS 号、其他拼写形式)和编辑整理的描述位于 /compound/{ns}/{value}/{synonyms|description}/JSON。
import requests
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
# Full synonym list (aspirin has ~700)
info = requests.get(f"{BASE}/compound/cid/2244/synonyms/JSON").json()["InformationList"]["Information"][0]
print(f"aspirin synonyms: {len(info['Synonym'])}")
for s in info["Synonym"][:8]:
print(f" {s}")
import requests
# Curated descriptions (NCBI MeSH, CAMEO, etc.)
r = requests.get("https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/aspirin/description/JSON")
for item in r.json()["InformationList"]["Information"]:
if "Description" in item:
print(f"[{item.get('DescriptionSourceName','?')}]")
print(f" {item['Description'][:200]}…")
print()
模块 4:相似性和子结构搜索(异步 ListKey 模式)
结构搜索会返回 HTTP 202 + {"Waiting": {"ListKey": "..."}}。每隔约 2 秒轮询一次 /compound/listkey/{key}/cids/JSON,直到返回 IdentifierList。由于此模式会在多处使用,请将其封装为辅助函数。
import requests, time
from urllib.parse import quote
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
def poll_listkey(listkey, max_polls=10, interval=2.0):
"""Block until PubChem finishes async search; return CID list."""
for _ in range(max_polls):
time.sleep(interval)
j = requests.get(f"{BASE}/compound/listkey/{listkey}/cids/JSON", timeout=20).json()
if "IdentifierList" in j:
return j["IdentifierList"]["CID"]
raise TimeoutError(f"ListKey {listkey} did not complete")
# Tanimoto similarity (90% threshold, max 20 hits) — starting from aspirin SMILES
smi = quote("CC(=O)OC1=CC=CC=C1C(=O)O", safe="")
init = requests.get(
f"{BASE}/compound/similarity/smiles/{smi}/JSON?Threshold=90&MaxRecords=20").json()
cids = poll_listkey(init["Waiting"]["ListKey"]) if "Waiting" in init \
else init["IdentifierList"]["CID"]
print(f"aspirin @90% similarity: {len(cids)} hits, sample={cids[:5]}")
import requests
from urllib.parse import quote
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
# Substructure search — all compounds containing a sulfonamide group
smi = quote("S(=O)(=O)N", safe="")
init = requests.get(
f"{BASE}/compound/substructure/smiles/{smi}/JSON?MaxRecords=20").json()
cids = poll_listkey(init["Waiting"]["ListKey"]) if "Waiting" in init \
else init["IdentifierList"]["CID"]
print(f"sulfonamide-containing CIDs: {len(cids)}, sample={cids[:5]}")
模块 5:测定结果汇总(生物活性数据)
/compound/cid/{cid}/assaysummary/JSON 会返回一个 Table,列出该化合物参与的所有 PubChem BioAssay(测定 AID、靶点、结果,以及可用时的微摩尔活性)。
import requests, pandas as pd
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
r = requests.get(f"{BASE}/compound/cid/2244/assaysummary/JSON", timeout=30)
rows = r.json().get("Table", {}).get("Row", [])
cols = r.json().get("Table", {}).get("Columns", {}).get("Column", [])
print(f"aspirin appears in {len(rows)} bioassays")
# First few columns + rows as a DataFrame
df = pd.DataFrame([row["Cell"] for row in rows[:5]], columns=cols)
print(df.iloc[:, :6].to_string(index=False))
模块 6:结构文件下载(SDF/PNG)
/compound/cid/{cid}/SDF 会返回 2D MOL/SDF;/compound/cid/{cid}/PNG 会返回结构图(使用 ?image_size=large 可获取更高分辨率)。
import requests
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
cid = 2519 # caffeine
# 2D SDF for downstream RDKit / OpenBabel
sdf = requests.get(f"{BASE}/compound/cid/{cid}/SDF", timeout=15).text
with open("caffeine.sdf", "w") as f:
f.write(sdf)
print(f"caffeine.sdf: {len(sdf)} chars, ends with M END={'M END' in sdf}")
# PNG structure image
png = requests.get(f"{BASE}/compound/cid/{cid}/PNG?image_size=large", timeout=15).content
with open("caffeine.png", "wb") as f:
f.write(png)
print(f"caffeine.png: {len(png)} bytes")
核心概念
异步 ListKey 模式
相似性、子结构和分子式搜索均为异步操作——API 会启动后台任务,并返回 HTTP 202 和 {"Waiting": {"ListKey": "<id>"}}。每隔约 2 秒轮询 /compound/listkey/{id}/cids/JSON,直到响应中包含 IdentifierList。大多数搜索会在 5–15 秒内完成;对于极小规模的搜索,可缩短轮询间隔;对于超大规模的搜索,则可延长间隔。请在所有场景中使用模块 4 中的 poll_listkey 辅助函数。
少数执行较快的搜索会在首次调用时直接返回 IdentifierList(不含 Waiting 字段);请同时检查这两种情况。
属性名称参考
| API 名称 | 含义 |
|---|---|
MolecularWeight | 分子量(g/mol,字符串) |
MolecularFormula | Hill 系统分子式 |
SMILES | 异构 SMILES,包含立体化学信息(2025+ 名称;原为 IsomericSMILES) |
ConnectivitySMILES | 仅表示连接关系的 SMILES,不含立体化学信息(2025+ 名称;原为 CanonicalSMILES) |
IUPACName | 经整理的 IUPAC 名称 |
InChI / InChIKey | IUPAC InChI / InChIKey |
XLogP | 计算得出的 logP(辛醇/水) |
TPSA | 拓扑极性表面积(Ų) |
HBondDonorCount | 氢键供体数量 |
HBondAcceptorCount | 氢键受体数量 |
RotatableBondCount | 可旋转键数量 |
HeavyAtomCount | 非氢原子数量 |
Charge | 形式电荷 |
在单个 /property/<csv>/JSON URL 中,以逗号分隔并联查任意子集。请注意,MolecularWeight 返回的是字符串;执行算术运算前请转换为 float。
响应封装结构
cids/JSON→{"IdentifierList": {"CID": [int, ...]}}property/.../JSON→{"PropertyTable": {"Properties": [{...}, ...]}}(每个 CID 对应一个字典,顺序与输入一致)synonyms/JSON→{"InformationList": {"Information": [{"CID": int, "Synonym": [str, ...]}]}}description/JSON→{"InformationList": {"Information": [{"CID": int, "Description": str, "DescriptionSourceName": str, ...}, ...]}}assaysummary/JSON→{"Table": {"Columns": {"Column": [...]}, "Row": [{"Cell": [...]}, ...]}}- 异步初始化(相似性、子结构、分子式) → 202,返回
{"Waiting": {"ListKey": "..."}} - listkey 轮询 → 就绪时返回
{"IdentifierList": {"CID": [...]}}
常见工作流
工作流 1:比较一组药物的属性
目标:并排比较一组小分子的理化性质。
import requests, pandas as pd, time
from urllib.parse import quote
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
drugs = ["aspirin", "ibuprofen", "naproxen", "celecoxib"]
# Resolve names → CIDs in a loop (rate-limited)
cids = []
for d in drugs:
cid = requests.get(f"{BASE}/compound/name/{quote(d)}/cids/JSON",
timeout=15).json()["IdentifierList"]["CID"][0]
cids.append(cid)
time.sleep(0.25)
# Single batched property pull
cid_csv = ",".join(str(c) for c in cids)
r = requests.get(
f"{BASE}/compound/cid/{cid_csv}/property/"
"MolecularWeight,XLogP,TPSA,HBondDonorCount,HBondAcceptorCount/JSON")
df = pd.DataFrame(r.json()["PropertyTable"]["Properties"])
df["Name"] = drugs
df = df[["Name", "CID", "MolecularWeight", "XLogP", "TPSA",
"HBondDonorCount", "HBondAcceptorCount"]]
print(df.to_string(index=False))
工作流 2:先导化合物 → 相似类似物 → 属性
目标:以一种激酶抑制剂(吉非替尼)为起点,查找相似度为 85% 的类似物并获取其属性。
import requests, time
from urllib.parse import quote
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
def poll_listkey(listkey, max_polls=10, interval=2.0):
for _ in range(max_polls):
time.sleep(interval)
j = requests.get(f"{BASE}/compound/listkey/{listkey}/cids/JSON",
timeout=20).json()
if "IdentifierList" in j:
return j["IdentifierList"]["CID"]
raise TimeoutError("listkey timeout")
# 1. lead → CID → canonical SMILES
ref_cid = requests.get(
f"{BASE}/compound/name/gefitinib/cids/JSON").json()["IdentifierList"]["CID"][0]
ref_smi = requests.get(
f"{BASE}/compound/cid/{ref_cid}/property/SMILES/JSON"
).json()["PropertyTable"]["Properties"][0]["SMILES"]
print(f"gefitinib CID={ref_cid} SMILES={ref_smi}")
# 2. similarity search
smi_q = quote(ref_smi, safe="")
init = requests.get(
f"{BASE}/compound/similarity/smiles/{smi_q}/JSON?Threshold=85&MaxRecords=15"
).json()
sim_cids = poll_listkey(init["Waiting"]["ListKey"]) if "Waiting" in init \
else init["IdentifierList"]["CID"]
print(f" {len(sim_cids)} analogs @85% Tanimoto")
# 3. batch-pull properties for top 5 analogs
cid_csv = ",".join(str(c) for c in sim_cids[:5])
r = requests.get(
f"{BASE}/compound/cid/{cid_csv}/property/"
"MolecularWeight,XLogP,TPSA,RotatableBondCount/JSON")
for row in r.json()["PropertyTable"]["Properties"]:
print(f" CID {row['CID']}: MW={row['MolecularWeight']} XLogP={row['XLogP']}")
工作流 3:通过子结构进行药效团筛选 → 检查生物活性
目标:查找含磺酰胺基序的化合物,并检查哪些化合物有生物活性记录。
import requests, time
from urllib.parse import quote
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
def poll_listkey(listkey, max_polls=10, interval=2.0):
for _ in range(max_polls):
time.sleep(interval)
j = requests.get(f"{BASE}/compound/listkey/{listkey}/cids/JSON",
timeout=20).json()
if "IdentifierList" in j:
return j["IdentifierList"]["CID"]
raise TimeoutError("listkey timeout")
smi = quote("S(=O)(=O)N", safe="")
init = requests.get(
f"{BASE}/compound/substructure/smiles/{smi}/JSON?MaxRecords=10").json()
cids = poll_listkey(init["Waiting"]["ListKey"]) if "Waiting" in init \
else init["IdentifierList"]["CID"]
print(f"sulfonamide CIDs: {cids}")
# Bioactivity row counts for the first few hits
for cid in cids[:3]:
rows = requests.get(f"{BASE}/compound/cid/{cid}/assaysummary/JSON",
timeout=30).json().get("Table", {}).get("Row", [])
print(f" CID {cid}: {len(rows)} assay rows")
time.sleep(0.3)
关键参数
| 参数 | 端点 / 模块 | 默认值 | 范围 / 选项 | 作用 |
|---|---|---|---|---|
<namespace> | /compound/{ns}/<value>/... | — | name, cid, smiles, inchikey, inchi, formula | 输入标识符类型 |
<property csv> | /.../property/<csv>/JSON | — | 任意属性名称子集(见表格) | 要返回哪些属性(每个请求进行一次数据库调用) |
Threshold | similarity (M4) | 90 | 0–100 | Tanimoto 截止值(百分比) |
MaxRecords | similarity / substructure / formula | (服务端默认值) | 1–10000 | 限制异步结果列表的上限 |
image_size | /compound/cid/{cid}/PNG | medium | small, large, WxH(例如 500x500) | PNG 输出分辨率 |
record_type | /compound/cid/{cid}/SDF | 2d | 2d, 3d | SDF 维度(?record_type=3d) |
MaxAssayResults | /compound/cid/{cid}/assaysummary/JSON | — | int | 当化合物有数千条记录时,限制测定结果行数 |
最佳实践
-
从名称或外部标识符开始时,务必先调用
cids/JSON。名称→CID 解析和 CID→属性查询是两个独立调用;通过name → property一次完成虽可行,但会丢弃下游查询所需的规范 CID 列表。 -
批量获取属性,不要循环请求。
compound/cid/2244,3672,2157,.../property/MolecularWeight,XLogP,.../JSON最多可接受约 200 个 CID 和任意数量的属性,只需一次往返,而不是 N 次。对每个名称循环调用get_compounds是最常见的触发速率限制的陷阱。 -
对所有 SMILES 进行 URL 编码。 使用
urllib.parse.quote(smiles, safe="")。不编码的 SMILES 中含有=,#,(,),[,]时有时也能正常工作,但遇到+,/,\或看起来像查询字符串的子串时就会不可预测地出错。 -
将相似度/子结构/分子式查询视为异步操作。 根据
"Waiting" in response进行分支判断,并轮询listkey,而不是重新发起搜索。重新发起搜索会创建新的 ListKey,并浪费服务端的任务槽位。 -
将请求速率控制在每秒 ≤ 5 次、每分钟 ≤ 400 次。 在任何紧密循环中插入
time.sleep(0.25)。HTTP 503 表示触发了速率限制——等待 10 秒并降低并发量。 -
将
MolecularWeight转换为float。 它以字符串("180.16")形式返回,以保留完整小数精度。将字符串与数值阈值比较会造成不易察觉的错误。 -
对于 100 个及以上的 CID,使用 POST。 超过约 2000 个字符的 GET URL 可能会被某些 HTTP 代理截断。PubChem 也接受在表单正文中包含
cid的POST:requests.post(f"{BASE}/compound/cid/property/MolecularWeight/JSON", data={"cid": cid_csv})。 -
2025 年 SMILES 属性重命名。 PubChem 在 2025 年 PUG-REST 架构中重命名了两个 SMILES 属性:旧的
IsomericSMILES(含立体信息)→SMILES,旧的CanonicalSMILES(仅连接关系,不含立体信息)→ConnectivitySMILES。URL 路径仍接受旧名称作为输入(例如/property/CanonicalSMILES/JSON会返回 200),但响应 JSON 使用新名称作为键。因此,请求会成功,只有解析步骤会因KeyError出错。新代码请使用SMILES/ConnectivitySMILES,并读取对应键。
常用配方
配方 1 — Lipinski 五规则检查
import requests
from urllib.parse import quote
BASE = "https://pubchem.ncbi.nlm.nih.gov/rest/pug"
def check_lipinski(name):
cid = requests.get(f"{BASE}/compound/name/{quote(name)}/cids/JSON"
).json()["IdentifierList"]["CID"][0]
p = requests.get(
f"{BASE}/compound/cid/{cid}/property/"
"MolecularWeight,XLogP,HBondDonorCount,HBondAcceptorCount/JSON"
).json()["PropertyTable"]["Properties"][0]
mw, xlogp = float(p["MolecularWeight"]), p.get("XLogP", 0) or 0
hbd, hba = p["HBondDonorCount"], p["HBondAcceptorCount"]
rules = {"MW ≤ 500": mw <= 500, "XLogP ≤ 5": xlogp <= 5,
"HBD ≤ 5": hbd <= 5, "HBA ≤ 10": hba <= 10}
v = sum(1 for ok in rules.values() if not ok)
return rules, v
rules, v = check_lipinski("metformin")
print(f"violations: {v}/4 ({'PASS' if v <= 1 else 'FAIL'})")
for r, ok in rules.items(): print(f" {'✓' if ok else '✗'} {r}")
配方 2 — 获取所有别名/商品名
import requests
r = requests.get("https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/aspirin/synonyms/JSON")
syns = r.json()["InformationList"]["Information"][0]["Synonym"]
print(f"{len(syns)} synonyms")
for s in syns[:10]:
print(f" {s}")
Recipe 3 — 下载结构 PNG
import requests
cid = 2519 # caffeine
png = requests.get(
f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/{cid}/PNG?image_size=large"
).content
with open("caffeine.png", "wb") as f:
f.write(png)
print(f"wrote caffeine.png ({len(png)} bytes)")
Recipe 4 — 使用重试和 429 处理的稳健会话
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
s = requests.Session()
s.headers.update({"Accept": "application/json"})
s.mount("https://", HTTPAdapter(max_retries=Retry(
total=4, backoff_factor=1.0,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["GET", "POST"])))
r = s.get(
"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/2244/property/MolecularWeight/JSON",
timeout=15)
r.raise_for_status()
print(r.json()["PropertyTable"]["Properties"][0]["MolecularWeight"])
预期输出
- CID 查询(
/.../cids/JSON):{"IdentifierList": {"CID": [...]}}— 按相关性排序的整数 CID 列表,名称搜索时如此。 - 属性(
/.../property/.../JSON):{"PropertyTable": {"Properties": [{"CID": ..., "MolecularWeight": "180.16", ...}, ...]}}。每个输入 CID 对应一行;MolecularWeight是字符串。 - 同义词:
{"InformationList": {"Information": [{"CID": 2244, "Synonym": ["aspirin", "ACETYLSALICYLIC ACID", "50-78-2", ...]}]}}。 - 异步搜索初始化:HTTP 202,返回
{"Waiting": {"ListKey": "12345..."}}。轮询/compound/listkey/{key}/cids/JSON,直到返回IdentifierList。 - 分析摘要:
{"Table": {"Columns": {"Column": [...col names...]}, "Row": [{"Cell": [...]}, ...]}}。 - SDF:纯文本,以 CID 标头行开头;以
M END结束,后接 SDF 属性块。 - PNG:二进制
image/png;默认大小约为 2–4 KB,image_size=large时约为 10–20 KB。
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
HTTP 404 PUGREST.NotFound | 名称 / SMILES / 分子式未匹配到任何记录 | 尝试使用 CAS 号或 InChIKey;在 PubChem 网页界面检查拼写;RDKit 生成的规范 SMILES 通常可以解析输入 SMILES 无法解析的记录 |
相似性 / 子结构调用的 HTTP 202 卡在 {"Waiting":...} | 异步任务仍在运行 | 每隔 2s 轮询 /compound/listkey/{key}/cids/JSON,最长约 30s;如果任务始终未完成,请减小 MaxRecords |
HTTP 503 PUGREST.ServerBusy | 触发了每秒 5 个请求或每分钟 400 个请求的速率限制 | 在循环中插入 time.sleep(0.25);使用 Recipe 4 中的 Retry 会话;降低并发量 |
| SMILES URL 返回 HTTP 400 | SMILES 未进行 URL 编码 | 使用 urllib.parse.quote(smi, safe="") 包装 — #、+、/ 和 \ 都会导致路径解析失败 |
KeyError: 'CanonicalSMILES' / KeyError: 'IsomericSMILES' | 请求了旧名称;URL 返回 200,但 2025 JSON 使用 ConnectivitySMILES / SMILES 作为键 | 读取 p["ConnectivitySMILES"](连接关系,不含立体化学信息)或 p["SMILES"](含立体化学信息);将属性 CSV 更新为新名称 |
TypeError: '>' not supported between instances of 'str' and 'int' | MolecularWeight 是字符串 | 在进行任何算术比较前使用 float(p["MolecularWeight"]) |
批量请求 cid/2244,3672,... 只返回部分行 | URL 超出服务器限制 | 改为使用 requests.post(url, data={"cid": "2244,3672,..."});URL 保留但移除值,CSV 放在请求正文中 |
assaysummary 表为空 | CID 没有生物测定记录 | 并非所有化合物都经过测定;请在 PubChem 网页上确认 |
有效 CID 的 XLogP 为 None | 尚未计算该化合物的此属性 | 在进行算术运算前使用 p.get("XLogP", 0) or 0 进行保护 |
相关技能
chembl-database-bioactivity— IC50 / Ki / Kd 靶标结合数据,比 PubChem 的测定摘要更深入rdkit-cheminformatics— 本地 SMILES/MOL 操作、指纹、描述符、骨架提取pdb-database— 与通过 PubChem CID 找到的小分子共结晶的蛋白质结构
参考资料
- PubChem PUG-REST 文档 — 完整的 URL 语法参考
- 含示例的 PUG-REST 教程 — 逐步讲解 API
- PubChem 属性表 —
/property/<name>值及其含义的权威列表 - PubChem 主站 — 用于抽查的网页界面
- Kim 等人(2023),《Nucleic Acids Res》——PubChem 2023 年更新