Есть ли способ прочитать файл.docx, включая автоматическую нумерацию с помощью python-docx - программирование
Подтвердить что ты не робот

Есть ли способ прочитать файл.docx, включая автоматическую нумерацию с помощью python-docx

Заявление о проблемах. Извлеките разделы из файла.docx, включая автозапуск.

Я попробовал python-docx извлечь текст из файла.docx, но это исключает автозапуск.

from docx import Document

document = Document("wadali.docx")


def iter_items(paragraphs):
    for paragraph in document.paragraphs:
        if paragraph.style.name.startswith('Agt'):
            yield paragraph
        if paragraph.style.name.startswith('TOC'):
            yield paragraph
        if paragraph.style.name.startswith('Heading'):
            yield paragraph
        if paragraph.style.name.startswith('Title'):
            yield paragraph
        if paragraph.style.name.startswith('Heading'):
            yield paragraph
        if paragraph.style.name.startswith('Table Normal'):
            yield paragraph
        if paragraph.style.name.startswith('List'):
            yield paragraph


for item in iter_items(document.paragraphs):
    print item.text
4b9b3361

Ответ 1

Похоже, что в настоящее время python-docx v0.8 не полностью поддерживает нумерацию. Вам нужно немного взломать.

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

import docx.document
import docx.oxml.table
import docx.oxml.text.paragraph
import docx.table
import docx.text.paragraph


def iter_paragraphs(parent, recursive=True):
    """
    Yield each paragraph and table child within *parent*, in document order.
    Each returned value is an instance of Paragraph. *parent*
    would most commonly be a reference to a main Document object, but
    also works for a _Cell object, which itself can contain paragraphs and tables.
    """
    if isinstance(parent, docx.document.Document):
        parent_elm = parent.element.body
    elif isinstance(parent, docx.table._Cell):
        parent_elm = parent._tc
    else:
        raise TypeError(repr(type(parent)))

    for child in parent_elm.iterchildren():
        if isinstance(child, docx.oxml.text.paragraph.CT_P):
            yield docx.text.paragraph.Paragraph(child, parent)
        elif isinstance(child, docx.oxml.table.CT_Tbl):
            if recursive:
                table = docx.table.Table(child, parent)
                for row in table.rows:
                    for cell in row.cells:
                        for child_paragraph in iter_paragraphs(cell):
                            yield child_paragraph

Вы можете использовать его для поиска всех абзацев документа, включая абзацы в ячейках таблицы.

Например:

import docx

document = docx.Document("sample.docx")
for paragraph in iter_paragraphs(document):
    print(paragraph.text)

Чтобы получить доступ к свойству нумерации, вам нужно выполнить поиск в "защищенных" элементах paragraph._p.pPr.numPr, который является объектом docx.oxml.numbering.CT_NumPr:

for paragraph in iter_paragraphs(document):
    num_pr = paragraph._p.pPr.numPr
    if num_pr is not None:
        print(num_pr)  # type: docx.oxml.numbering.CT_NumPr

Обратите внимание, что этот объект извлекается из файла numbering.xml (внутри docx), если он существует.

Чтобы получить доступ к нему, вам необходимо прочитать свой файл docx как пакет. Например:

import docx.package
import docx.parts.document
import docx.parts.numbering

package = docx.package.Package.open("sample.docx")

main_document_part = package.main_document_part
assert isinstance(main_document_part, docx.parts.document.DocumentPart)

numbering_part = main_document_part.numbering_part
assert isinstance(numbering_part, docx.parts.numbering.NumberingPart)

ct_numbering = numbering_part._element
print(ct_numbering)  # CT_Numbering
for num in ct_numbering.num_lst:
    print(num)  # CT_Num
    print(num.abstractNumId)  # CT_DecimalNumber

Информация Mor доступна в документации Office Open XMl.