使用Pandas解析BindingDB XML时遇XPath无节点返回错误求助
解决BindingDB XML解析的XPath错误
错误原因
报错提示xpath does not return any nodes,核心问题是你指定的XPath路径.//bdb没有匹配到XML中的任何节点——BindingDB的getTargetByCompound接口返回的XML里,单个靶标数据的行节点并非<bdb>,而是带有命名空间的特定节点(比如<bdb:targetWithDrug>),且你需要准确匹配这个层级。
解决方案步骤
1. 先确认XML结构(关键)
先打印接口返回的XML内容,明确节点层级:
import requests smile = 'C[C@H]1[C@H](C)CC[C@]2(C)CC[C@]3(C)C(=CC(=O)[C@@H]4[C@@]5(C)CC[C@@H](O)[C@](C)(C(=O)O)[C@@H]5CC[C@]43C)[C@H]12' api_binding = requests.get(f'https://bindingdb.org/axis2/services/BDBService/getTargetByCompound?smiles={smile}&cutoff=1') print(api_binding.text)
观察输出会发现,每个靶标的数据都包裹在<bdb:targetWithDrug>节点下,这才是你需要指定的行级节点。
2. 修正Pandas解析代码
调整XPath路径到正确的节点,同时保留命名空间配置:
import pandas as pd import requests smile = 'C[C@H]1[C@H](C)CC[C@]2(C)CC[C@]3(C)C(=CC(=O)[C@@H]4[C@@]5(C)CC[C@@H](O)[C@](C)(C(=O)O)[C@@H]5CC[C@]43C)[C@H]12' api_binding = requests.get(f'https://bindingdb.org/axis2/services/BDBService/getTargetByCompound?smiles={smile}&cutoff=1') # 命名空间保持正确配置,XPath指向实际行节点 namespaces = {"bdb": "https://ws.bindingdb.org/xsd"} df = pd.read_xml(api_binding.text, xpath=".//bdb:targetWithDrug", namespaces=namespaces) # 提取人类靶标信息 result = df.loc[df["species"] == "Homo sapiens (Human)", "target"] print(result)
3. 备用方案:用lxml手动解析(应对复杂XML)
如果Pandas的read_xml对命名空间处理仍有问题,改用lxml直接解析节点:
import requests import pandas as pd from lxml import etree smile = 'C[C@H]1[C@H](C)CC[C@]2(C)CC[C@]3(C)C(=CC(=O)[C@@H]4[C@@]5(C)CC[C@@H](O)[C@](C)(C(=O)O)[C@@H]5CC[C@]43C)[C@H]12' api_binding = requests.get(f'https://bindingdb.org/axis2/services/BDBService/getTargetByCompound?smiles={smile}&cutoff=1') # 解析XML根节点 root = etree.fromstring(api_binding.content) ns = {"bdb": "https://ws.bindingdb.org/xsd"} # 遍历所有靶标节点,提取字段 data = [] for node in root.xpath("//bdb:targetWithDrug", namespaces=ns): row = { "species": node.xpath("./bdb:species/text()", namespaces=ns)[0] if node.xpath("./bdb:species/text()", namespaces=ns) else None, "target": node.xpath("./bdb:target/text()", namespaces=ns)[0] if node.xpath("./bdb:target/text()", namespaces=ns) else None # 可添加其他需要的字段,比如affinity、inchi等 } data.append(row) # 转为DataFrame并筛选 df = pd.DataFrame(data) result = df.loc[df["species"] == "Homo sapiens (Human)", "target"] print(result)
关键说明
- 必须确保XPath指向XML中实际存在的行级节点,不能凭猜测写路径;
- 命名空间的前缀和URL必须和XML中的
xmlns声明完全一致; - 手动解析方式更灵活,适合结构复杂的XML数据。
内容的提问来源于stack exchange,提问作者pulkit leuva
相关产品推荐
相关产品推荐

