第3章:分子数据库构建——ChEMBL、PubChem、ZINC、PDB等公共资源

做虚拟筛选,说白了第一步就是找数据。没有好数据,后面算法再牛也白搭。我个人习惯把这一步叫做“数据地基”——地基打不牢,上面的pipeline再花哨,结果也经不起推敲。

市面上公开的分子数据库不少,但真正能在生产环境里直接用的,其实就那几个。我这些年折腾下来,最常用的就是ChEMBL、PubChem、ZINC和PDB。每个库的脾气秉性都不一样,得摸透了才能用好。

嗯,咱们一个一个来看。

核心观点:分子数据库不是简单的“下载-解压-完事”。你需要理解每个库的schema、数据更新频率、以及API的限流策略。

3.1 ChEMBL——生物活性数据的首选

ChEMBL是欧洲生物信息学研究所(EBI)维护的。它最厉害的地方在于,数据是人工从文献里抠出来的,质量非常高。我记得有一次做靶点验证,从ChEMBL拉出来的IC50数据跟后续实验的吻合度超过90%。

ChEMBL提供两种获取方式:一是直接下载MySQL dump,二是通过REST API查询。我个人更推荐API,省去建库的折腾。

举个例子,你想查某个靶点对应的活性分子,可以这样调API:

# 获取与靶点CHEMBL ID关联的化合物列表
curl -X GET "https://www.ebi.ac.uk/chembl/api/data/activity.json?target_chembl_id=CHEMBL203&limit=10"

返回的是JSON格式,解析起来很方便。但是要注意,API有访问频率限制——好像是每秒最多3次请求。我曾经有个同事没注意这个,一把梭子发了上千个并发请求,直接被封了IP。

避坑指南:我曾经爬ChEMBL时没做请求间隔,结果被EBI封了24小时。建议每次API调用之间至少sleep 0.5秒,或者用他们提供的批量下载文件。

3.2 PubChem——数据量最大,但最“脏”

PubChem由美国NIH维护。它是目前最大的免费化学数据库,化合物数量超过1亿。但说实话,数据质量参差不齐。

为什么?因为PubChem的数据来源太杂了——有科研机构提交的,有专利里挖的,还有供应商的库存。同一分子在不同来源里结构表示可能都不一样。

所以用PubChem的时候,我强烈建议你先做个去重和标准化。比如用RDKit对分子进行规范:

from rdkit import Chem
from rdkit.Chem import SaltRemover

# 读取PubChem的SDF文件
mol = Chem.MolFromMolFile("pubchem_example.sdf")

# 去除盐和溶剂
remover = SaltRemover.SaltRemover()
mol_clean = remover.StripMol(mol, dontRemoveEverything=True)

# 标准化为规范SMILES
canonical_smiles = Chem.MolToSmiles(mol_clean)
print(canonical_smiles)

你想想看,如果这一步不做,后面跑的对接结果很可能因为分子表示不一致而出现偏差。我在项目里就吃过这个亏,花了三天时间排查,最后发现是PubChem里同一个分子有两种SMILES表示。

3.3 ZINC——虚拟筛选的“主力军”

ZINC是专门为虚拟筛选设计的数据库。它最大的卖点是——所有分子都经过了“类药性”过滤。这意味着你不用再重复做Lipinski五规则检查了。

ZINC把分子分成了几个档次:

分子集 数量(约) 特点 典型用途
ZINC-20 2.3亿 商品化/可采购分子 虚拟筛选后直接购买
ZINC-22 16亿 包含虚拟分子 大规模虚拟筛选
ZINC-FDA ~3000 已批准药物 药物重定位

下载ZINC数据时,我通常用他们的官方工具zinc-downloader。你指定想要的分组和格式,它会自动切分:

# 下载ZINC-20中的“Lead-like”分子集,格式为mol2
zinc-downloader --subset lead-like --format mol2 --output ./zinc_data/

说实话,ZINC的目录结构一开始看着有点晕——它按tranche(分片)来组织。每个分片包含约10万个分子,方便并行处理。这一点在设计pipeline时特别重要。

我的习惯:下载ZINC数据时,不要一口气全下完。先下2-3个tranche做测试,等pipeline调通了再用后台任务批量下载。

3.4 PDB——蛋白质结构的“仓库”

PDB(Protein Data Bank)是结构数据的老祖宗。做分子对接时,你是拿它存的小分子配体,还是拿它存的蛋白受体?答案通常是后者。

PDB里一个关键概念是分辨率。分辨率小于2.0 Å的结构才算靠谱。我个人的筛选标准是:

  • 分辨率 ≤ 2.0 Å —— 可用
  • 分辨率 ≤ 1.5 Å —— 优质
  • 分辨率 > 2.5 Å —— 慎用

通过PDB的API获取结构信息很简单:

# 获取4AGN(一个激酶结构)的元数据
curl -X GET "https://data.rcsb.org/rest/v1/core/entry/4AGN"

但要注意,PDB里很多结构是有缺陷的——比如缺失的侧链、不合理的键长、或者水分子没处理好。所以下载后一定要做结构准备,像加氢、修复侧链、分配电荷这些步骤,一个都不能省。

3.5 构建本地数据库的最佳实践

说到这里,你可能会问:那这四类数据到底怎么整合到pipeline里?

我个人建议的做法是:建立一个本地分子数据库。把所有数据拉下来,存到你熟悉的关系型或非关系型数据库里。

比如,我用PostgreSQL建过这样一个schema:

CREATE TABLE molecules (
    id SERIAL PRIMARY KEY,
    source_db TEXT NOT NULL,       -- 来源: chembl/pubchem/zinc/pdb
    source_id TEXT NOT NULL,       -- 原始ID
    smiles TEXT,                   -- 规范SMILES
    inchi TEXT,                    -- InChI字符串
    molecular_weight DOUBLE PRECISION,
    logp DOUBLE PRECISION,
    num_h_donors INTEGER,
    num_h_acceptors INTEGER,
    num_rotatable_bonds INTEGER,
    data JSONB,                   -- 扩展属性,灵活存储
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_molecules_smiles ON molecules USING hash (smiles);
CREATE INDEX idx_molecules_source ON molecules (source_db);

为什么要用JSONB存扩展属性?因为不同数据库的元数据差异太大了。ChEMBL有pChEMBL值,PubChem有XlogP,ZINC有采购价格——统一放在JSONB里最灵活。

下面这张图,总结了我构建分子数据库时的核心流程和思考路径:

分子数据库构建核心逻辑 ChEMBL PubChem ZINC PDB 数据获取:REST API / 批量下载 / MySQL dump 限流处理、断点续传、格式转换(SDF, SMILES, MOL2) 数据标准化:去重、盐去除、规范SMILES、结构校正 RDKit / Open Babel 化学信息学工具 数据集成:统一入库、字段映射、索引构建 PostgreSQL / MongoDB / 自定义schema 输出:标准化分子库,可直接用于虚拟筛选 关键:每个步骤都要做质量监控——记录数据量、丢弃比例、异常分布

3.6 数据更新的节奏

数据库不是一次建完就完事了。ChEMBL每两个月更新一次,PubChem不定期更新,ZINC三个月左右出一次快照。这设计pipeline时需要考虑进去。

我的做法是:写一个cron job,每月初自动检查各数据源的版本号。如果有更新,就增量下载差异部分,然后触发pipeline重新跑一遍筛选。

# 0 0 1 * * /opt/scripts/update_db.sh --check-version --download-diff

当然,如果你的筛选目标是做一个静态数据集的分析,那不用这么频繁。但如果是长期运行的筛选服务,数据同步就是必修课了。

小技巧:每次更新后,对比新旧版本的分子库,重点关注“新增分子”和“删除分子”的分布。有时候某次更新会把一批活性数据删掉,必须人工审查。

好了,关于分子数据库构建这块,核心就是这些。记住:数据库本身不产生价值,真正值钱的是你从中筛选出那些有活性的分子。而这一步能不能做好,很大程度上取决于你数据的质量和组织方式。