Разбор и сортировка тегов HTML с красивым супом - PullRequest
0 голосов
/ 04 октября 2019

У меня есть ниже HTML-файл, который содержит bbox информацию из PDF-файла:

<flow>
  <block xMin="53.879997" yMin="369.965298" xMax="63.939976" yMax="380.991433">
    <line xMin="53.879997" yMin="369.965298" xMax="63.939976" yMax="380.991433">
      <word xMin="53.879997" yMin="369.965298" xMax="63.939976" yMax="380.991433">10</word>
    </line>
  </block>
</flow>
<flow>
  <block xMin="53.879997" yMin="417.965298" xMax="63.939976" yMax="428.991433">
    <line xMin="53.879997" yMin="417.965298" xMax="63.939976" yMax="428.991433">
      <word xMin="53.879997" yMin="417.965298" xMax="63.939976" yMax="428.991433">20</word>
    </line>
  </block>
</flow>
<flow>
  <block xMin="111.351361" yMin="369.965298" xMax="134.220382" yMax="380.991433">
    <line xMin="111.351361" yMin="369.965298" xMax="134.220382" yMax="380.991433">
      <word xMin="111.351361" yMin="369.965298" xMax="116.331548" yMax="380.991433">1</word>
      <word xMin="121.909358" yMin="369.965298" xMax="134.220382" yMax="380.991433">PC</word>
    </line>
  </block>
</flow>

Выше ограничивающие области для слов: 10 20 1 PC

Висходный документ, он написан так:

10 1 PC
20

Следовательно, я хотел бы проанализировать выше HTML-файл и извлечь все <line> теги, а затем отсортировать их все по yMin значение. Конечный результат выше был бы: 10 1 PC 20 вместо.

То, что я пробовал до сих пор

Я не очень далеко, так как я все еще изучаю Python. Я использую BeautifulSoup4:

with open("test.html", "r") as f:
    contents = f.read()
    soup = BeautifulSoup(contents, 'lxml')

    for line in soup.find_all("line", attrs={"ymin":True}):
        print(line.get('ymin'))

Выше просто распечатывает каждый тег и его содержимое.

Хотя я не уверен, как сортировать теги строк.

Любая помощьбудет высоко ценится.

Ответы [ 2 ]

1 голос
/ 04 октября 2019

Вы можете использовать BeautifulSoup с soup.find_all:

from bs4 import BeautifulSoup as soup
r = [i.find_all('word') for i in sorted(soup(html, 'html.parser').find_all('line'), key=lambda x:float(x['ymin']))]
result = [i.text for b in r for i in b]

Выход:

['10', '1', 'PC', '20']
0 голосов
/ 04 октября 2019

Попробуйте следующий код. Можно определить среднее значение, а затем проверить его с помощью среднего значения.

from bs4 import BeautifulSoup
html='''<flow>
  <block xMin="53.879997" yMin="369.965298" xMax="63.939976" yMax="380.991433">
    <line xMin="53.879997" yMin="369.965298" xMax="63.939976" yMax="380.991433">
      <word xMin="53.879997" yMin="369.965298" xMax="63.939976" yMax="380.991433">10</word>
    </line>
  </block>
</flow>
<flow>
  <block xMin="53.879997" yMin="417.965298" xMax="63.939976" yMax="428.991433">
    <line xMin="53.879997" yMin="417.965298" xMax="63.939976" yMax="428.991433">
      <word xMin="53.879997" yMin="417.965298" xMax="63.939976" yMax="428.991433">20</word>
    </line>
  </block>
</flow>
<flow>
  <block xMin="111.351361" yMin="369.965298" xMax="134.220382" yMax="380.991433">
    <line xMin="111.351361" yMin="369.965298" xMax="134.220382" yMax="380.991433">
      <word xMin="111.351361" yMin="369.965298" xMax="116.331548" yMax="380.991433">1</word>
      <word xMin="121.909358" yMin="369.965298" xMax="134.220382" yMax="380.991433">PC</word>
    </line>
  </block>
</flow>'''

soup=BeautifulSoup(html,'lxml')
pricemin=soup.select_one('line[yMin]')['ymin']
list1=[]
list_last=[]
for item in soup.select('line[yMin]'):
    if float(pricemin) < float(item['ymin']):

         for w in item.select('word'):
             list_last.append(w.text)
    else:
        for w in item.select('word'):
            list1.append(w.text)

print(list1+list_last)

Выход :

['10', '1', 'PC', '20']

Чтобы напечатать это

print(' '.join(list1+list_last))

Вывод :

10 1 PC 20
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...