使用请求和 ElementTree 解析 XML

Parsing XML with requests and ElementTree

我正在尝试从科学数据库中检索数据。我有一个使用 urllib 和 ElementTree 的工作脚本,但我想使用更新的模块,所以我尝试用请求重写它。

不幸的是,由于 unicode 的 TypeError,ElementTree 不想再解析 XML。所以我尝试了 BeautifulSoup ,这在某种程度上有效,但在访问嵌套标签时遇到了问题。回到 ElementTree——它也是内置的。

对于以下代码,我得到 "TypeError: coercing to Unicode: need string or buffer, Response found"。如果我将“.text”或“.content”添加到带有 et.parsing 的行,则不会发生错误,而是打印而不是解析整个站点内容。

for entry in input_list:
xml = requests.Session().get(url.xml)
if xml.status_code == 200:
    try:
        tree = et.parse(xml)
        root = getroot.tree()

        for record in root.iter(base + 'placeholder').text:
            var1 = record
            break

        print(var1)

    except TypeError:
        print('error on parsing')

else:
    xml.raise_for_status()

编辑:

输出应如下所示:

登录号、名称、蛋白质推荐名称、主要基因名称、NCBI 分类学、生物科学、序列、长度

例如:

P0AES4,GYRA_ECOLI,DNA 促旋酶亚基 A,gyrA,83333,大肠杆菌(菌株 K12),MSDLAREITP...,875

您的问题始于 正确命名事物:

xml = requests.Session().get(url.xml)

requests.get() 不 return XML。它 return 是一个 响应

resp = requests.Session().get(url.xml)

并且此响应可能包含 文本(即字符串):

print(resp.text)

而这个字符串可能是 XML,ElementTree 可以将其转换为树:

tree = ET.fromstring(resp.text)

然后我们可以使用它来获取信息:

tree.find('entry')

which returns None,因为在这种情况下 XML 在命名空间中 (xmlns="..."),而该命名空间是 http://uniprot.org/uniprot.必须提到的是,当我们搜索元素时:

tree.find('{http://uniprot.org/uniprot}entry')

写起来很笨拙。所以我们做一个缩写:

xml_ns = {
    'up': 'http://uniprot.org/uniprot'
}

并改用它:

tree.find('up:entry', xml_ns)

现在打印

<Element '{http://uniprot.org/uniprot}entry' at 0x03C0AD80>

利用所有这些,我们得到:

import requests
import xml.etree.ElementTree as ET

xml_url = 'https://www.uniprot.org/uniprot/P0AES4.xml'
xml_ns = {
    'up': 'http://uniprot.org/uniprot'
}

resp = requests.get(xml_url)
tree = ET.fromstring(resp.text)

def get_text(node):
    return node.text if node is not None else None

for entry in tree.findall('./up:entry', xml_ns):
    data = {
        'accession': get_text( entry.find('./up:accession', xml_ns) )
        # find and add more items
    }

    print(data)

打印

{'accession': 'P0AES4'}