XML синтаксический анализ с использованием BeautifulSoup: получение нескольких текстовых данных с одинаковым идентификатором внутри одного документа - PullRequest
1 голос
/ 07 августа 2020

Я пытаюсь получить несколько текстовых данных с одним и тем же номером do c внутри одного документа (тега)

Мой XML файл выглядит так:

<doc>
<docnum>1234</docnum>
<p>text1</p>
<p>text2</p>
<p>text3</p>
<p>text4</p>
<p>text5</p>
<docdesc>only text</docdesc>
</doc>

<doc>
<docnum>789</docnum>
<p>text1</p>
<p>text2</p>
<p>text3</p>
<p>text4</p>
<p>text5</p>
<docdesc>only and only texts</docdesc>
</doc>

Но методы find_all () и find () BeautifulSoup не могут извлекать их по отдельности. Мой фрагмент кода выглядит следующим образом:

from bs4 import BeautifulSoup
with open('file.xml', 'r') as openfile:
    content = "".join(openfile.readlines())
    soupcontent = BeautifulSoup(content, "lxml")
    docnums = [str(t.text) for t in (soupcontent.findAll('docnum'))]
    doctexts = [str(t.text) for t in (soupcontent.find_all('p'))]
    for a, b in zip(docnums, doctexts):
        print(a + '\n' + b)

Но вместо сопоставления docnum doc1 со всеми p документа doc1 он сопоставляет все. Вложенные циклы for внутри каждого find_all () также не помогают. Он не может остановиться, когда достигнут конец тега do c

1 Ответ

1 голос
/ 07 августа 2020

Этот скрипт распечатает все <docnum>, <p> и <docdesc> для каждого индивидуума <doc>:

from bs4 import BeautifulSoup

txt = '''<doc>
<docnum>1234</docnum>
<p>text1</p>
<p>text2</p>
<p>text3</p>
<p>text4</p>
<p>text5</p>
<docdesc>only text</docdesc>
</doc>

<doc>
<docnum>789</docnum>
<p>text1</p>
<p>text2</p>
<p>text3</p>
<p>text4</p>
<p>text5</p>
<docdesc>only and only texts</docdesc>
</doc>'''

soup = BeautifulSoup(txt, 'html.parser')

for doc in soup.select('doc'):
    print('docnum :', doc.docnum.text)
    print('text   :', [p.text for p in doc.select('p')])
    print('docdesc:', doc.docdesc.text)
    print('-' * 80)

Печать:

docnum : 1234
text   : ['text1', 'text2', 'text3', 'text4', 'text5']
docdesc: only text
--------------------------------------------------------------------------------
docnum : 789
text   : ['text1', 'text2', 'text3', 'text4', 'text5']
docdesc: only and only texts
--------------------------------------------------------------------------------

РЕДАКТИРОВАТЬ: Чтобы хранить данные в списках, вы можете:

docnums   = []
doctexts  = []

for doc in soup.select('doc'):
    docnums.append(doc.docnum.text)
    doctexts.append([p.text for p in doc.select('p')])

for n, t in zip(docnums, doctexts):
    print(n)
    print(' '.join(t))
...