Разбор XML с запросами и ElementTree - PullRequest
0 голосов
/ 24 апреля 2020

Я пытаюсь получить данные из научной базы данных c. У меня был рабочий скрипт с использованием urllib и ElementTree, но я хотел использовать более актуальный модуль, поэтому я попытался переписать его с запросами.

К сожалению, ElementTree не хочет анализировать XML anylonger из-за Ошибка типа с Unicode. Вместо этого я попробовал BeautifulSoup, который работает в некоторой степени, но у него были проблемы с доступом к вложенным тегам. Итак, вернемся к ElementTree - который тоже встроен.

Для следующего кода я получаю «TypeError: приведение в Unicode: нужна строка или буфер, ответ найден». Если я добавлю «.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()

Редактировать:

Вывод должен выглядеть следующим образом:

присоединение, имя, рекомендуемый белокName, имя гена первичное, таксономия NCBI, научные данные организма c, последовательность, длина

Для примера это будет:

P0AES4, GYRA_ECOLI, субъединица ДНК-гиразы A, gyrA, 83333, Escherichia coli (штамм K12), MSDLAREITP ..., 875

1 Ответ

1 голос
/ 24 апреля 2020

Ваша проблема начинается с правильного именования вещей :

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

requests.get() не возвращает XML. Он возвращает ответ .

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

И этот ответ может содержать текст (т.е. строку):

print(resp.text)

И эту строку может быть XML, которое ElementTree может преобразовать в дерево:

tree = ET.fromstring(resp.text)

, которое мы затем можем использовать для получения информации:

tree.find('entry')

, которая возвращает 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'}
...