Обнаружение разрывов абзаца в XML -конвертированном PDF (Python) - PullRequest
0 голосов
/ 25 апреля 2020

У меня есть этот файл PDF, который имеет эти "длинные" пробелы (выделены желтым цветом на изображении ниже). Моя цель - обнаружить их, чтобы я мог разделить сегменты текста вокруг этих пробелов.

n XML

Пока что мои испытания не были полностью безуспешными. так как XML возвращает атрибут «ограничивающий прямоугольник» (пример: bbox="68.031,553.639,76.375,566.366"), который имеет четыре значения (x1, y1, x2, y2), я мог узнать более или менее расстояние, которое я искал, делая x1 - х1 предыдущего элемента. Но вывод невелик, и я уверен, что есть более простой ответ на мою проблему, чем тот, который у меня есть.

Вывод, который я получаю, не сохраняет пробелов и не учитывает разрывы строк. Но даже не учитывает разрывы абзацев (изображение ниже):

enter image description here

Которые должны учитывать не x1 атрибута bbox , но, вероятно, позиция у, но я не знаю, как с этим справиться.

Это мой код:

import lxml.etree as etree

parser = etree.XMLParser(remove_blank_text=True)
tree = etree.parse('fe3.xml', parser)
root = tree.getroot()

# Get the first BBox value as float
# Return null if not found
def getBBoxFirstValue(line):
    if line is not None:
        bb = line.attrib.get('bbox')
        if bb is not None:
            try:
                return float(bb.split(",")[0])
            except ValueError:
                pass
    return None


new_line        = None
previous_bb     = None

for x in tree.xpath('//text'):
    # Get current bb value
    bb = getBBoxFirstValue(x)
    # Check current and past values aren't empty
    if bb is not None and previous_bb is not None:
        #print(bb, previous_bb, (bb-previous_bb))
        #print(abs(bb-previous_bb))
        # If distance with preview bb > 10
        if (bb - previous_bb) > 20 or (bb - previous_bb) < -1000:
            # If new_line isn't empty: it's inserted into parent tag at position of current tag

            if new_line is not None:
                x.getparent().insert(x.getparent().index(x), new_line)
            # A new "new_line" element is created
            new_line = etree.Element("new_line")

        # If the new line isn't not (e.g. one distance > 10 has been already found)
        if new_line is not None:
            new_line.append(x)

    # Keep latest non empty BBox 1st value
    if bb is not None:
        previous_bb = bb

# Add last new_line element if not null
if new_line is not None:
    tree.xpath('//text')[-1].getparent().append(new_line)


newtree = etree.tostring(root, encoding='utf-8', pretty_print=True)
#newtree = newtree.decode("UTF-8")
print(newtree)
with open("output.xml", "wb") as f:
    f.write(newtree)

Мой входной файл находится здесь: ссылка

Вывод, который я получаю здесь: ссылка

РЕДАКТИРОВАТЬ:

Для пояснения, ввод XML выглядит так:

Рассмотрим текстовые теги, имеющие атрибуты "bbox"

<pages>
 <page>
  <textbox>
   <textline>
    <text> a </text>
    <text> b </text>
    <text> c </text>
   </textline>
   <textline>
    <text> d </text>
  </textbox>
  <textbox>
   <textline>
    <text> e </text>
    <text> f </text>
   </textline>
  </textbox>
 </page>
</pages>

Вывод, который я хотел бы получить:

<pages>
 <page>
  <textbox>
   <textline>
   <new_line>
    <text> a </text>
    <text> b </text>
   </new_line>
   <new_line>
    <text> c </text>
   </new_line>
   </textline>
   <textline>
   <new_line>
    <text> d </text>
   </new_line>
  </textbox>
  <textbox>
   <textline>
   <new_line>
    <text> e </text>
    <text> f </text>
    </new_line>
   </textline>
  </textbox>
 </page>
</pages>

Но вывод, который я получаю:

<pages>
 <page>
  <textbox>
   <textline>
   <new_line>
    <text> a </text>
    <text> b </text>
   </new_line>
   </textline>
   <textline>
   <new_line>
    <text> c </text>
    <text> d </text>
   </new_line>
  </textbox>
  <textbox>
   <textline>
   <new_line>
    <text> e </text>
    <text> f </text>
    </new_line>
   </textline>
  </textbox>
 </page>
</pages>

Итак, что происходит с моим кодом, так это то, что «текстовое поле» не сохраняется должным образом.

1 Ответ

0 голосов
/ 26 апреля 2020

Функция модификации этой библиотеки немного слабая. Попробуйте проверить, работает ли он.

from simplified_scrapy import SimplifiedDoc,req,utils
html = '''
<pages>
 <page>
  <textbox>
   <textline>
    <text> a </text>
    <text> b </text>
    <text> c </text>
   </textline>
   <textline>
    <text> d </text>
  </textbox>
  <textbox>
   <textline>
    <text> e </text>
    <text> f </text>
   </textline>
  </textbox>
 </page>
</pages>'''
doc = SimplifiedDoc(html)
first = doc.getElement('textline').getElement('text') # Get the first
first.repleaceSelf('<new_line>\n'+first.outerHtml)
next = first.getNext(tag='text') # Get next 
while next:
  tmp = next.next
  if next.text == 'c': # Your condition
    next.repleaceSelf('</new_line>\n<new_line>\n' + next.outerHtml)

  if not tmp or tmp.tag != "text": # The last one
    next.repleaceSelf(next.outerHtml + '\n</new_line>')
    tmp = doc.getElement('text', start=next._end)
    if tmp:
      tmp.repleaceSelf('<new_line>\n'+tmp.outerHtml)
  else:
    tmp = doc.getElement('text', start=next._end)
  next = tmp
print (doc.html)

Результат:

<pages>
 <page>
  <textbox>
   <textline>
    <new_line>
<text> a </text>
    <text> b </text>
    </new_line>
<new_line>
<text> c </text>
</new_line>
   </textline>
   <textline>
    <new_line>
<text> d </text>
</new_line>
  </textbox>
  <textbox>
   <textline>
    <new_line>
<text> e </text>
    <text> f </text>
</new_line>
   </textline>
  </textbox>
 </page>
</pages>
...