mcpField
P
pubchem-compound-search

pubchem-compound-search

github.com/jaechang-hits数据与数据库38471 次安装6 天前更新
代码仓库

关于 pubchem-compound-search

PubChem Compound Search 是通过公开的 PUG-REST JSON API 查询 PubChem 的 Python 技能,面向化学和生物医学工作流。它直接使用 requests 获取标识符、性质、结构、同义词和测定摘要,无需 API 密钥。

主要功能

  1. 01解析名称和化学标识符
  2. 02批量获取化合物性质
  3. 03按相似性或子结构搜索
  4. 04获取同义词和描述
  5. 05查询测定摘要并下载结构

适用场景

  1. 01比较一组化合物的性质
  2. 02查找先导化合物的类似物
  3. 03筛选含特定结构基序的化合物
  4. 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,字符串)
MolecularFormulaHill 系统分子式
SMILES异构 SMILES,包含立体化学信息(2025+ 名称;原为 IsomericSMILES)
ConnectivitySMILES仅表示连接关系的 SMILES,不含立体化学信息(2025+ 名称;原为 CanonicalSMILES)
IUPACName经整理的 IUPAC 名称
InChI / InChIKeyIUPAC 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—任意属性名称子集(见表格)要返回哪些属性(每个请求进行一次数据库调用)
Thresholdsimilarity (M4)900–100Tanimoto 截止值(百分比)
MaxRecordssimilarity / substructure / formula(服务端默认值)1–10000限制异步结果列表的上限
image_size/compound/cid/{cid}/PNGmediumsmall, large, WxH(例如 500x500)PNG 输出分辨率
record_type/compound/cid/{cid}/SDF2d2d, 3dSDF 维度(?record_type=3d)
MaxAssayResults/compound/cid/{cid}/assaysummary/JSON—int当化合物有数千条记录时,限制测定结果行数

最佳实践

  1. 从名称或外部标识符开始时,务必先调用 cids/JSON。名称→CID 解析和 CID→属性查询是两个独立调用;通过 name → property 一次完成虽可行,但会丢弃下游查询所需的规范 CID 列表。

  2. 批量获取属性,不要循环请求。 compound/cid/2244,3672,2157,.../property/MolecularWeight,XLogP,.../JSON 最多可接受约 200 个 CID 和任意数量的属性,只需一次往返,而不是 N 次。对每个名称循环调用 get_compounds 是最常见的触发速率限制的陷阱。

  3. 对所有 SMILES 进行 URL 编码。 使用 urllib.parse.quote(smiles, safe="")。不编码的 SMILES 中含有 =, #, (, ), [, ] 时有时也能正常工作,但遇到 +, /, \ 或看起来像查询字符串的子串时就会不可预测地出错。

  4. 将相似度/子结构/分子式查询视为异步操作。 根据 "Waiting" in response 进行分支判断,并轮询 listkey,而不是重新发起搜索。重新发起搜索会创建新的 ListKey,并浪费服务端的任务槽位。

  5. 将请求速率控制在每秒 ≤ 5 次、每分钟 ≤ 400 次。 在任何紧密循环中插入 time.sleep(0.25)。HTTP 503 表示触发了速率限制——等待 10 秒并降低并发量。

  6. 将 MolecularWeight 转换为 float。 它以字符串("180.16")形式返回,以保留完整小数精度。将字符串与数值阈值比较会造成不易察觉的错误。

  7. 对于 100 个及以上的 CID,使用 POST。 超过约 2000 个字符的 GET URL 可能会被某些 HTTP 代理截断。PubChem 也接受在表单正文中包含 cid 的 POST:requests.post(f"{BASE}/compound/cid/property/MolecularWeight/JSON", data={"cid": cid_csv})。

  8. 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 400SMILES 未进行 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 找到的小分子共结晶的蛋白质结构

参考资料

评论

支持 Markdown