按顺序处理docx中的对象

Chr*_*ris 3 python ms-word python-docx

我想按照Word文档中写入的顺序处理对象。我遇到的对象是段落、段落中的文本、段落中的运行、运行中的文本、表格以及表格单元格中的段落。到目前为止我有两个有用的程序。遍历文档的段落并获取该段落的文本;存储在由[第#段]索引的列表中。这个程序能够从运行中收集文本;存储在由[段落#][运行#]索引的二维列表中,但我没有发现运行比段落的整个文本更有用。我的第二个程序遍历整个文档并查找表格。当它有一个表格时,它会按行、单元格和单元格中的段落浏览表格。

现在,这些似乎是实现我的目标的重要基石。我想按顺序收集文本。抽象地说,就好像一个人按住键盘上的右箭头命令闪烁的文本光标移动。当文本光标在对象上移动时,它通过多个索引来存储它们,这些索引标记了对象的# 和对象的类型。

假设我有子函数paragraph_read 和table_read。假设文档具有以下对象顺序: 。我想仔细检查这些并按以下顺序执行我的子功能:paragraph_read、paragraph_read、table_read、paragraph_read

我想知道我的程序是否可以像向右滑动光标一样逐个对象地移动文档。

非常感谢您的帮助。谢谢。

-克里斯

sca*_*nny 7

更新

有一些新方法python-docx可以处理这里的大部分细节:

Document.iter_inner_content()- 提供对文档中的Paragraph和对象的访问,按文档顺序:Table

for block_item in document:
    if isinstance(block_item, Paragraph):
        ... process paragraph ...
    elif isinstance(block_item, Table):
        ... process table ...
Run Code Online (Sandbox Code Playgroud)

表格单元格也是块项容器并且具有相同的方法。如果需要的话,这允许递归到表中。

页眉和页脚对象也是块项容器并具有此方法。

节本身不是块项目容器,但当您想要逐节迭代文档时,确实有此方法。


您需要将此函数添加到代码中方便的地方:

from docx.document import Document
from docx.oxml.table import CT_Tbl
from docx.oxml.text.paragraph import CT_P
from docx.table import _Cell, Table
from docx.text.paragraph import Paragraph


def iter_block_items(parent):
    """
    Yield each paragraph and table child within *parent*, in document
    order. Each returned value is an instance of either Table or
    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, Document):
        parent_elm = parent.element.body
    elif isinstance(parent, _Cell):
        parent_elm = parent._tc
    else:
        raise ValueError("something's not right")

    for child in parent_elm.iterchildren():
        if isinstance(child, CT_P):
            yield Paragraph(child, parent)
        elif isinstance(child, CT_Tbl):
            yield Table(child, parent)
Run Code Online (Sandbox Code Playgroud)

然后你像这样使用它:

document = Document('my_document.docx')

for block_item in iter_block_items(document):
    if isinstance(block_item, Paragraph):
        do_paragraph_thing(paragraph=block_item)
    elif isinstance(block_item, Table):
        do_table_thing(table=block_item)
    else:
        # raise an exception or do nothing or whatever. This branch would
        # only be reached on an unforeseen error.
Run Code Online (Sandbox Code Playgroud)