代码之家  ›  专栏  ›  技术社区  ›  Jaswinder

有没有办法读取.docx文件,包括使用python docx自动编号

  •  14
  • Jaswinder  · 技术社区  · 7 年前

    问题陈述:从.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
    
    1 回复  |  直到 7 年前
        1
  •  7
  •   Laurent LAPORTE    7 年前

    现在看来 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中),如果存在的话。

    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

        2
  •  3
  •   Elliott    6 年前

    有一个包docx2python,它以一种简单得多的方式来实现这一点:pypi.org/project/docx2python/

    以下代码:

    from docx2python import docx2python
    document = docx2python("C:/input/MyDoc.docx")
    print(document.body)