参考链接:https://www.aropha.com/resources/blog/get-chemical-smiles-by-cas-or-name/

Python 3.11.4

第一种方式:首先需要pip安装相对于的模块matchmscirpy,然后根据上面的连接进行改写,里面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}")

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐