Python 根据化合物的英文名称或者 CASNO 批量获取其对应 SMILES
·
参考链接:https://www.aropha.com/resources/blog/get-chemical-smiles-by-cas-or-name/
Python 3.11.4
第一种方式:首先需要pip安装相对于的模块matchms、cirpy,然后根据上面的连接进行改写,里面input_msp = "test.msp"修改为自己想对应的路径,运行该Python代码就会自动根据msp格式里面的casno或者compound_name批量加入对应的smiles
from matchms.importing import load_from_msp
from matchms.exporting import save_as_msp
import cirpy
import re
import time
input_msp = "test.msp"
output_msp = "output_with_smiles.msp"
not_found_file = "not_found.txt"
not_found = []
# 将 CASNO 转换为标准格式
def format_cas(cas):
if not cas:
return None
cas_digits = re.sub(r'\D', '', str(cas)) # 去掉非数字
if len(cas_digits) < 5:
return None
first = cas_digits[:-3]
second = cas_digits[-3:-1]
check = cas_digits[-1]
return f"{first}-{second}-{check}"
# 加载 MSP 文件
spectra = list(load_from_msp(input_msp))
for spectrum in spectra:
metadata = spectrum.metadata
casno = metadata.get("casno") or ""
name = metadata.get("compound_name") or ""
smiles = None
# 优先查 CASNO
if casno:
std_cas = format_cas(casno)
if std_cas:
try:
smiles = cirpy.resolve(std_cas, 'smiles')
except Exception:
smiles = None
# 如果 CAS 查不到,则用 Name
if not smiles and name:
try:
smiles = cirpy.resolve(name, 'smiles')
except Exception:
smiles = None
# 如果都查不到,记录 Name 或 CASNO
if not smiles:
not_found.append(str(name or casno or "Unknown"))
print(f"❌ 未找到: {name or casno or 'Unknown'}")
else:
metadata["smiles"] = smiles
spectrum.metadata = metadata
time.sleep(0.3) # 避免请求过快
# 保存新的 MSP 文件
save_as_msp(spectra, output_msp)
# 保存未找到的记录
if not_found:
with open(not_found_file, "w", encoding="utf-8") as f:
f.write("\n".join(not_found))
print(f"完成!输出文件:{output_msp}")
print(f"未找到的记录已保存:{not_found_file}")
第二种方式:使用 pubchem 进行搜索,通过msp里面的名字或者casno号进行搜索,这种可能国内的网络不行,需要国外的网络,同样里面input_msp = "test.msp"修改为自己想对应的路径
from matchms.importing import load_from_msp
from matchms.exporting import save_as_msp
import requests
import re
import time
# ====== 路径配置 ======
input_msp = "test.msp"
output_msp = "out.msp"
record_file = "smiles_record.txt"
# ====== 工具函数 ======
def format_cas(cas):
"""格式化 CAS 号为标准形如 xxxx-yy-z"""
if not cas:
return None
cas_digits = re.sub(r'\D', '', str(cas))
if len(cas_digits) < 5:
return None
first = cas_digits[:-3]
second = cas_digits[-3:-1]
check = cas_digits[-1]
return f"{first}-{second}-{check}"
def query_smiles_from_pubchem(identifier):
"""通过 PubChem 查询 SMILES,可输入 CAS 或化合物名"""
url = f"https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/name/{identifier}/property/CanonicalSMILES,ConnectivitySMILES/JSON"
try:
res = requests.get(url, timeout=10)
res.raise_for_status()
data = res.json()
props = data.get("PropertyTable", {}).get("Properties", [])
if props:
# 优先 ConnectivitySMILES
if "ConnectivitySMILES" in props[0]:
return props[0]["ConnectivitySMILES"]
elif "CanonicalSMILES" in props[0]:
return props[0]["CanonicalSMILES"]
except Exception as e:
print(f"⚠️ 查询失败: {identifier} ({e})")
return None
# ====== 主逻辑 ======
spectra = list(load_from_msp(input_msp))
found_records = []
not_found_records = []
for spectrum in spectra:
metadata = spectrum.metadata
casno = metadata.get("casno") or ""
name = metadata.get("compound_name") or metadata.get("name") or ""
smiles = metadata.get("smiles")
# 跳过已有 SMILES
if smiles:
continue
found_smiles = None
# ① 优先用 CAS 号查询
if casno:
std_cas = format_cas(casno)
if std_cas:
found_smiles = query_smiles_from_pubchem(std_cas)
if found_smiles:
print(f"✅ CAS匹配成功: {std_cas} -> {found_smiles}")
# ② 若 CAS 查询失败,再用名称
if not found_smiles and name:
found_smiles = query_smiles_from_pubchem(name)
if found_smiles:
print(f"✅ 名称匹配成功: {name} -> {found_smiles}")
# ③ 保存结果
if found_smiles:
metadata["smiles"] = found_smiles
spectrum.metadata = metadata
found_records.append((name, casno, found_smiles))
else:
# ✨ 这里修改:打印化合物名 + CAS号
print(f"❌ 未找到: 名称={name or 'Unknown'} | CAS={casno or 'Unknown'}")
not_found_records.append((name, casno))
time.sleep(0.3) # 防止请求过快
# ====== 保存结果 ======
save_as_msp(spectra, output_msp)
with open(record_file, "w", encoding="utf-8") as rf:
rf.write("Compound_Name\tCAS\tSMILES\n")
rf.write("\n# ✅ 找到的记录\n")
for name, cas, smiles in found_records:
rf.write(f"{name}\t{cas}\t{smiles}\n")
rf.write("\n# ❌ 未找到的记录\n")
for name, cas in not_found_records:
rf.write(f"{name}\t{cas}\t\n")
print(f"\n✅ 完成!输出 MSP 文件:{output_msp}")
print(f"📄 查询记录保存于:{record_file}")
更多推荐


所有评论(0)