Python-docx: определить разрыв страницы в абзаце

Я перебираю документ по абзацам, затем разбиваю текст каждого абзаца на предложения по . (точка с пробелом). Я разбиваю текст абзаца на предложения,чтобы сделать текстовый поиск более эффективным по сравнению с поиском в целом тексте абзаца.

Затем код ищет ошибку в каждом слове предложения, ошибка берется из базы данных исправления ошибок. Я показываю ниже упрощенный код:

from docx.enum.text import WD_BREAK

for paragraph in document.paragraphs:
    sentences = paragraph.text.split('. ') 
    for sentence in sentences:
        words=sentence.split(' ')
        for word in words:
            for error in error_dictionary:
                 if error in word:
                     # (A) make simple replacement
                     word = word.replace(error, correction, 1)
                     # (B) alternative replacement based on runs 
                     for run in paragraph.runs:
                         if error in run.text:
                               run.text = run.text.replace(error, correction, 1)
                         # here we may fetch page break attribute and knowing current number 
                         # find out at what page the replacement has taken place 
                         if run.page_break== WD_BREAK:
                              current_page_number +=1
                     replace_counter += 1
                     # write to a report what paragraph and what page
                     write_report(error, correction, sentence, current_page_number )  
                     # for that I need to know a page break    

Проблема заключается в том, как определить, содержит ли прогон (или другой элемент абзаца) разрыв страницы? run.page_break == WD_BREAK работает? @scanny показал как добавить разрыв страницы, но как его идентифицировать?

Лучше всего, если можно определить также разрыв строки в абзаце.

Я мог бы сделать:

for run in paragraph.runs:
    if run._element.br_lst:             
        for br in run._element.br_lst:
            br_couter+=1
            print br.type                

Однако этот код показывает только жесткие разрывы, то есть разрывы, вставленные с помощью Ctrl+Enter. Мягкие разрывы страниц не обнаруживаются... (Мягкие разрывы страниц формируются, когда пользователь продолжает печатать до тех пор, пока страница, на которой он находится, не закончится, а затем он переходит на следующую страницу)

Любые подсказки?


person Igor Savinkin    schedule 31.10.2018    source источник


Ответы (2)


Для мягких и жестких разрывов страниц я теперь использую следующее:

for run in paragraph.runs:
    if 'lastRenderedPageBreak' in run._element.xml:  
        print 'soft page break found at run:', run.text[:20] 
    if 'w:br' in run._element.xml and 'type="page"' in run._element.xml:
        print 'hard page break found at run:', run.text[:20]
person Igor Savinkin    schedule 16.11.2018

Невозможно обнаружить программные разрывы страниц в файле .docx. Их положение известно только механизму рендеринга и не отражается в самом файле .docx. Если вы ищете здесь «[python-docx] разрыв страницы» или «[python-docx] TOC», вы найдете более подробное объяснение этого.

Что касается первой части вашего вопроса, эта страница из раздела технического анализа документации python-docx показывает, как выглядят разрывы в базовом XML:
https://python-docx.readthedocs.io/en/latest/dev/analysis/features/text/breaks.html#specimen-xml

Пока нет поддержки API для явного поиска разрывов, хотя свойство run.text указывает на них с помощью символа перевода строки \n. Однако \n не отличает разрывы строк от разрывов страниц.

Если вам нужно получить более конкретную информацию, вам нужно будет копаться в XML при каждом запуске и искать конкретные элементы разрыва (w:br), которые вас интересуют, и их атрибуты:

>>> run._element.xml
<w:r>
  <w:t>Text before</w:t>
  <w:br/>
  <w:t>and after line break</w:t>
</w:r>

Упомянутый вами подход run._element.br_lst является хорошим, тогда вам просто нужно изучить атрибуты каждого w:br, чтобы увидеть, есть ли у него атрибут w:type=.

person scanny    schedule 31.10.2018
comment
в итоге я просто разделил текст абзаца на строки (и подсчитал индекс строк) следующим образом: for line in paragraph.text.splitlines() - person Igor Savinkin; 01.11.2018
comment
Я создаю файл docx с помощью python-docx и имею разные интервалы между строками абзаца (DOUBLE и SINGLE) в разных точках, поэтому подсчет строк на самом деле не работает, если только я не определял тип интервала при расчете. Это много работы. - person j_allen_morris; 25.06.2019