当前位置:首页>python>[python] 基于python-docx库的Word文档自动处理全解

[python] 基于python-docx库的Word文档自动处理全解

  • 2026-02-03 15:17:32
[python] 基于python-docx库的Word文档自动处理全解

python-docx是一款纯Python实现的第三方库,专门用于创建和修改Microsoft Word的.docx格式文档。该库无需依赖 Microsoft Word软件即可运行,具备优秀的跨平台特性,可在Windows、Mac、Linux等系统上使用。需要注意的是,python-docx仅兼容.docx 格式(对应 Word 2007 及以上版本),不支持旧版的.doc 格式文件。.docx是基于XML的开放压缩格式,而.doc是二进制私有格式,前者体积更小、兼容性更优。

python-docx官方代码仓库见:python-docx[1],详细文档见:python-docx docs[2]。截至本文撰写时,python-docx的稳定版本为1.2.0,python-docx安装命令如下:

pip install python-docx

1 使用说明

unsetunset1.1 快速入门unsetunset

Python-docx中的Word文档内存对象模型采用树状结构分层映射文档元素,使得程序能够精准控制文档的内容、格式与布局。该树状结构示意如下:

Document(文档)├── Sections(节)├── Paragraphs(段落)│   ├── Runs(文本片段)│   └── InlineShapes(内联形状,如图片)├── Tables(表格)│   ├── Rows(行)│   │   └── Cells(单元格)│   │       └── Paragraphs(单元格内的段落)└── Core Properties(文档属性)

各个对象简介如下:

核心对象
代表含义
在文档树中的位置
主要功能与说明
Document
整个Word文档对象
根对象
用于打开或创建一个.docx文件
Sections
文档的节
Document.sections
管理页面设置(如页边距、纸张方向)
Paragraph
段落
Document.paragraphs
Table.cell.paragraphs
文档的基本单元由一个或多个Run组成,并拥有统一的段落格式
Run
具有相同格式的连续文本
Paragraph.runs
格式控制的最小单位,可以对Run单独设置字体、大小等字符级格式
Table
表格
Document.tables
代表文档中的一个表格,由行(Table.rows)、列(Table.columns)和单元格(Table.cell)组成
Cell
表格单元格
Table.cell(row,col)
每个Cell本身可以包含多个Paragraph,就像一个微缩文档
InlineShape
内嵌形状(如图片)
Paragraph.add_picture()
创建
代表文档中与文本在同一层的图形对象,最常用的是图片
Styles
样式集合
Document.styles
管理文档中定义的所有样式(如“标题1”、“正文”等)

以下代码示例描述了如何通过python-docx库快速实现文档的创建,完成段落、标题、表格、图片等内容添加及字符段落样式设置,并保存为docx文件:

# 1. 初始化文档from docx import Documentfrom docx.shared import Inches, Cm# 新建空白文档,不添加参数,默认新建doc = Document()  # 2. 添加段落# 默认都会把内容追加到文档的末尾doc.add_paragraph("这是文档正文段落")  # 直接添加段落para = doc.add_paragraph("主段落"# 该方法返回新段落的引用对象para.insert_paragraph_before("插入在主段落上方的段落")  # 主段落的引用之前插入段落para = doc.add_paragraph("插入在主段落下方的段落"# 主段落的引用之后插入段落# 3. 添加标题(级别1-9,0为文档标题)doc.add_heading("文档总标题", level=0# 一份报告的封面标题doc.add_heading("第一章 概述", level=1# 一级标题doc.add_heading("1.1 核心功能", level=2# 二级标题# 4. 分页符doc.add_page_break()  # 强制后续内容另起一页# 5. 添加表格(固定行+动态行+样式)# 5.1 固定表格(2行2列)table1 = doc.add_table(rows=2, cols=2)table1.cell(00).text = "姓名"table1.cell(01).text = "年龄"table1.cell(10).text = "张三"table1.cell(11).text = "25"# 5.2 动态表格(表头+数据行)table2 = doc.add_table(rows=1, cols=3)# 将鼠标悬停在Word表格样式库中的表格样式缩略图上,即可找到表格样式名称table2.style = "Light Shading Accent 1"# 应用预设样式headers = ["数量""产品编号""描述"]for i, header in enumerate(headers):    table2.rows[0].cells[i].text = header# 批量添加数据items = [(7"1024""毛绒小猫"), (3"2042""菲比精灵"), (1"1288""豪华项圈")]for item in items:    row = table2.add_row().cells    row[0].text = str(item[0])    row[1].text = item[1]    row[2].text = item[2]# 6. 添加图片(本地文件+尺寸调整)doc.add_picture("test.png", width=Inches(1.5))  # 1.5英寸宽(自动等比缩放)doc.add_picture("test2.jpg", width=Cm(5),height=Cm(1))  # 同时指定宽高# 7. 段落样式(项目符号/编号)doc.add_paragraph("项目符号列表项1", style="ListBullet")doc.add_paragraph("项目符号列表项2", style="ListBullet")doc.add_paragraph("编号列表项1", style="ListNumber")# 8. 字符格式(粗体/斜体)para = doc.add_paragraph()para.add_run("普通文本 ").bold = Falsepara.add_run("粗体文本").bold = Truepara.add_run(" 普通文本 ").italic = Falsepara.add_run("斜体文本").italic = True# 9. 字符样式(预设样式)para2 = doc.add_paragraph("普通文本,")para2.add_run("带强调的文本", style="Emphasis")  # 应用"强调"样式# 10. 保存文档doc.save("test_output.docx")

后续内容将对python-docx的各个核心对象进行具体介绍。

unsetunset1.2 Python-docx的核心对象unsetunset

1.2.1 Document对象

Python-docx本质上是一个文档修改工具。即使创建新文档,其原理也是基于一个预设的空白模板进行修改。因此,文档的格式(如样式、页眉、页脚)与正文内容是分离存储的,即使清空模板文字也不会删除格式设定。以下示例展示了如何创建文档或打开已有文档:

from docx import Documentfrom io import BytesIO, StringIO  # 用于类文件对象操作"""演示python-docx操作文档的核心功能"""# ===================== 1. 创建新文档并保存 =====================print("1. 创建新文档并保存...")# 基于默认模板创建空文档new_doc = Document()new_doc.add_heading('python-docx 文档操作示例', level=1)new_doc.add_paragraph('这是通过python-docx创建的新文档')# 保存新文档到本地new_doc.save('新建文档.docx')print("✅ 新文档已保存为:新建文档.docx")# ===================== 2. 打开现有文档并修改保存 =====================print("\n2. 打开现有文档并修改...")# 打开刚才创建的文档existing_doc = Document('新建文档.docx')# 向文档追加内容existing_doc.add_paragraph('这是打开现有文档后追加的内容')# 另存为新文件(避免覆盖原文件)existing_doc.save('修改后的文档.docx')print("✅ 修改后的文档已保存为:修改后的文档.docx")# ===================== 3. 通过类文件对象(BytesIO)读写文档 =====================print("\n3. 通过类文件对象操作文档...")# 3.1 读取:将本地文档读取到BytesIO流中with open('修改后的文档.docx''rb'as f:  # 必须用rb(二进制读),跨平台兼容    doc_stream = BytesIO(f.read())  # 用BytesIO而非StringIO# 从流中打开文档stream_doc = Document(doc_stream)# 追加内容stream_doc.add_paragraph('这是通过类文件对象添加的内容')# 3.2 保存:将文档保存到BytesIO流中(不落地到本地文件)output_stream = BytesIO()stream_doc.save(output_stream)# 可选:将流中的内容写入本地文件,验证结果with open('类文件对象生成的文档.docx''wb'as f:    f.write(output_stream.getvalue())print("✅ 类文件对象操作的文档已保存为:类文件对象生成的文档.docx")# 关闭流doc_stream.close()output_stream.close()

1.2.2 Table对象

Word软件中的表格功能相当复杂,这导致在使用python-docx操作表格时,往往难以提前明确表格的具体内容和结构,增加了处理的难度。本节将从简单表格到复杂表格来介绍如何使用python-docx操作表格。

规整表格

规整表格也就是一个行列数固定、无合并或省略单元格的标准表格,这是最基础的表格形式。关系型数据库表和pandas数据表都是规整表格的典型示例:

+---+---+---+| a | b | c |+---+---+---+| d | e | f |+---+---+---+| g | h | i |+---+---+---+

通过控制表格行列数即可创建规整表格:

from docx import Documentfrom docx.shared import Inches# 创建新文档doc = Document()# 添加3行2列的规整表格table = doc.add_table(rows=3, cols=2)table.style = 'Table Grid'# 显示表格边框,便于查看# 填充单元格内容(a-i 对应示例中的规整表格)cell_texts = ['a''b''c''d''e''f']idx = 0for row in table.rows:for cell in row.cells:        cell.text = cell_texts[idx]        idx += 1# 保存文档doc.save('规整表格示例.docx')# 读取并验证规整表格的行列数(每行单元格数相同)print("规整表格每行的单元格数:")for i, row in enumerate(table.rows):    print(f"第{i+1}行:{len(row.cells)}个单元格")

合并单元格

将多个连续的横向或纵向单元格合并为一个单元格,是实际使用中非常常见的方式:

+---+---+---+   +---+---+---+|   a   | b |   |   | b | c |+---+---+---+   + a +---+---+| c | d | e |   |   | d | e |+---+---+---+   +---+---+---+| f | g | h |   | f | g | h |+---+---+---+   +---+---+---+

实现方式为先创建规整表格,再通过cell.merge()实现单元格的横向或纵向合并:

from docx import Documentdoc = Document()table = doc.add_table(rows=2, cols=3)table.style = 'Table Grid'# 示例1:横向合并(第一行第一个单元格合并右侧单元格)cell_1_1 = table.cell(00)  # 第1行第1列(索引从0开始)cell_1_2 = table.cell(01)cell_1_1.merge(cell_1_2)cell_1_1.text = '合并单元格(横向)'# 示例2:纵向合并(第三列前两个单元格合并)cell_1_3 = table.cell(02)cell_2_3 = table.cell(12)cell_1_3.merge(cell_2_3)cell_1_3.text = '合并单元格(纵向)'# 填充其他单元格table.cell(10).text = 'd'table.cell(11).text = 'e'# 查看合并后每行的单元格数# 注意以下内容返回的是原始表格结构print("合并单元格后每行的单元格数:")for i, row in enumerate(table.rows):    print(f"第{i+1}行:{len(row.cells)}个单元格")doc.save('合并单元格示例.docx')

递归表格

表格处理的另一个复杂点是其递归特性,Word中的表格单元格本身可以包含一个或多个表格。可以通过_Cell.tables_Cell.iter_inner_content()检测嵌套表格:

  • _Cell.tables:直接返回单元格内包含的所有表格。
  • _Cell.iter_inner_content():按文档顺序返回单元格内的所有内容(包括段落和表格),保持表格与段落的相对位置不变。

示例代码如下:

from docx import Documentfrom docx.shared import Inchesfrom docx.table import Tablefrom docx.text.paragraph import Paragraphdefgenerate_nested_table_doc():"""生成带嵌套表格的示例Word文档(示例数据)"""# 1. 创建新文档    doc = Document()# 2. 创建外层表格(2行2列)    outer_table = doc.add_table(rows=2, cols=2)    outer_table.style = 'Table Grid'# 显示表格边框# 3. 填充外层表格的普通单元格    cell_1_1 = outer_table.cell(00)    cell_1_1.text = "下方单元格包含嵌套表格"    cell_1_2 = outer_table.cell(01)    cell_1_2.text = "普通单元格(无嵌套)"# 4. 关键:在 (1,0) 单元格中嵌套一个子表格    cell_2_1 = outer_table.cell(10)# 先给嵌套表格前加一个段落(模拟真实文档的混合内容)    para = cell_2_1.add_paragraph("嵌套表格前的段落内容:")# 在单元格内创建嵌套表格(3行1列)    inner_table = cell_2_1.add_table(rows=3, cols=1)    inner_table.style = 'Table Grid'# 填充嵌套表格    inner_table.cell(00).text = "嵌套表格-行1"    inner_table.cell(10).text = "嵌套表格-行2"    inner_table.cell(20).text = "嵌套表格-行3"# 嵌套表格后再加一个段落    cell_2_1.add_paragraph("嵌套表格后的段落内容")# 5. 填充外层表格最后一个单元格    cell_2_2 = outer_table.cell(11)    cell_2_2.text = "普通单元格(无嵌套)"# 6. 保存文档(生成示例数据)    doc.save("嵌套表格.docx")    print("=" * 50)    print("✅ 嵌套表格.docx")    print("=" * 50)deftraverse_table(table, level=0):"""    递归遍历表格,处理嵌套表格    :param table: 要遍历的表格对象    :param level: 表格嵌套层级(外层为0,内层+1)    """    indent = "  " * level  # 缩进,方便区分层级    print(f"\n{indent}=== 遍历【层级{level}】表格 ===")# 遍历表格的每一行for row_idx, row in enumerate(table.rows):# 遍历行中的每一个单元格for col_idx, cell in enumerate(row.cells):            print(f"\n{indent}单元格 ({row_idx+1}{col_idx+1}):")# --------------------------# 方法1:_Cell.tables - 直接获取单元格内的所有表格# --------------------------            inner_tables = cell.tablesif inner_tables:                print(f"{indent}  📌 检测到 {len(inner_tables)} 个嵌套表格:")# 递归遍历每个嵌套表格for inner_table in inner_tables:                    traverse_table(inner_table, level + 1)else:                print(f"{indent}  📌 无嵌套表格")# --------------------------# 方法2:_Cell.iter_inner_content() - 按顺序获取单元格内所有内容(段落+表格)# --------------------------            print(f"{indent}  📌 单元格内完整内容(按顺序):")for content in cell.iter_inner_content():if isinstance(content, Paragraph):# 处理段落内容(过滤空段落)                    text = content.text.strip()if text:                        print(f"{indent} [段落]:{text}")elif isinstance(content, Table):# 遇到表格时的提示(避免重复遍历,仅演示位置)                    print(f"{indent} [表格]:嵌套表格(层级{level+1})")defparse_nested_tables():"""解析生成的嵌套表格文档,演示核心方法"""# 1. 打开示例文档    doc = Document("嵌套表格.docx")# 2. 遍历文档中的所有外层表格    print("\n开始解析嵌套表格:")    print("-" * 50)for table in doc.tables:        traverse_table(table)# 主程序入口if __name__ == "__main__":# 生成带嵌套表格的示例文档    generate_nested_table_doc()# 第二步:解析嵌套表格,演示_Cell.tables和iter_inner_content的使用    parse_nested_tables()    print("\n" + "=" * 50)    print("✅ 嵌套表格解析完成!")    print("=" * 50)

1.2.3 文本处理

在Word文档中,内容的组织逻辑分为两个主要层级:块级对象和行内对象。

  • 块级对象(如段落、表格)是占据整行的大模块,其宽度由页面边距、分栏或单元格边界决定,文本会在其左右边界内自动换行。
  • 行内对象则存在于这些大模块内部,如加粗的词语或句子,最常见的表现形式是文本片段(runs)。一个段落就是由一个或多个文本片段组成的。

相应地,格式控制也分为两类:

  • 块级属性(如缩进、间距、对齐方式)控制模块在页面上的布局位置;
  • 行内属性(如字体、加粗、颜色)则控制模块内部文字的具体外观。

下面通过Python-docx的代码示例,展示这两类格式的实际应用:

from docx import Documentfrom docx.shared import Inches, Pt, RGBColorfrom docx.enum.text import (    WD_ALIGN_PARAGRAPH,    WD_TAB_ALIGNMENT,    WD_TAB_LEADER,    WD_UNDERLINE)from docx.enum.dml import MSO_THEME_COLOR# 创建一个新的 Word 文档doc = Document()# ==================== 1. 块级格式设置:段落布局控制 ====================# 1.1 标题段落(居中对齐、段后间距)title_para = doc.add_paragraph("Python-docx 文本格式示例")title_format = title_para.paragraph_format  # 块级格式对象title_format.alignment = WD_ALIGN_PARAGRAPH.CENTER  # 居中对齐(块级属性)title_format.space_after = Pt(18)  # 段后间距(块级属性)# 1.2 正文段落(缩进与行间距)content_para = doc.add_paragraph("这是一个带缩进和自定义行间距的正文段落。")content_format = content_para.paragraph_formatcontent_format.left_indent = Inches(0.5)          # 左缩进content_format.first_line_indent = Inches(-0.25)  # 悬挂缩进content_format.line_spacing = 1.5# 1.5倍行间距content_format.space_before = Pt(12)             # 段前间距# 1.3 带制表位的段落(块级定位)tab_para = doc.add_paragraph("姓名:\t张三\t年龄:\t25")tab_format = tab_para.paragraph_formattab_stops = tab_format.tab_stops# 添加三个制表位(位置、对齐方式、前导符)tab_stops.add_tab_stop(Inches(1.5), WD_TAB_ALIGNMENT.RIGHT, WD_TAB_LEADER.DOTS)tab_stops.add_tab_stop(Inches(2.5), WD_TAB_ALIGNMENT.LEFT, WD_TAB_LEADER.SPACES)tab_stops.add_tab_stop(Inches(3.5), WD_TAB_ALIGNMENT.RIGHT, WD_TAB_LEADER.DOTS)# 1.4 分页控制(块级保持与孤行控制)page_para1 = doc.add_paragraph("这是章节标题(确保与下一段同页)")page_para1.paragraph_format.keep_with_next = True# 与下段同页page_para2 = doc.add_paragraph("这是章节内容,启用了孤行控制,避免段落首行/末行单独显示在一页。" * 20)page_para2.paragraph_format.widow_control = True# 避免孤行# ==================== 2. 行内格式设置:文字外观控制 ====================char_para = doc.add_paragraph("字符格式示例:")# 粗体bold_run = char_para.add_run("粗体文本")bold_run.font.bold = Truechar_para.add_run(" | ")# 斜体italic_run = char_para.add_run("斜体文本")italic_run.font.italic = Truechar_para.add_run(" | ")# 下划线(双下划线)underline_run = char_para.add_run("双下划线文本")underline_run.font.underline = WD_UNDERLINE.DOUBLEchar_para.add_run(" | ")# 不同字号和颜色color_run = char_para.add_run("16号红色文本")color_run.font.size = Pt(16)               # 字号color_run.font.color.rgb = RGBColor(25500)  # 颜色char_para.add_run(" | ")# 上标sup_run = char_para.add_run("上标")sup_run.font.superscript = True# ==================== 3. 保存文档 ====================doc.save("文本格式示例.docx")print("文档已保存为:文本格式示例.docx")

1.2.4 Sections对象

Word引入了节(section)的概念,它指文档中具有相同页面布局(如页边距、纸张方向)的连续部分。通过分节,用户可以在同一份文档中混合使用不同版式,例如同时包含纵向页面和横向页面。此外,每个节还可以独立设置其页眉与页脚的样式。绝大多数Word文档默认仅包含一个节,通常也无需更改页面布局。然而,当确实需要对页面布局进行调整时,理解节的功能与设置方法就变得至关重要。以下示例展示了如何使用python-docx库创建包含多个节、各节拥有不同页面设置的Word文档:

from docx import Documentfrom docx.enum.section import WD_SECTION_STARTfrom docx.enum.section import WD_ORIENTfrom docx.shared import Inches# 1. 创建新文档并查看默认节document = Document()print("初始文档的节数量:", len(document.sections))  # 默认1个节# 获取默认节并修改其基础布局(纵向,常规边距)default_section = document.sections[0]# 设置默认节的边距:左1.5英寸、右1英寸、上下各1英寸default_section.left_margin = Inches(1.5)default_section.right_margin = Inches(1)default_section.top_margin = Inches(1)default_section.bottom_margin = Inches(1)# 2. 给默认节添加内容(纵向页面内容)document.add_heading('第一节:纵向页面内容', level=1)document.add_paragraph('这是默认节的内容,页面为纵向,边距:左1.5英寸、右1英寸。')# 3. 添加新节(奇数页开始,横向布局)# 创建新节,指定分节符类型为奇数页开始new_section = document.add_section(WD_SECTION_START.ODD_PAGE)# 修改新节的页面方向为横向(需同时交换宽高)new_section.orientation = WD_ORIENT.LANDSCAPE# 先交换宽高值,避免页面尺寸异常new_width, new_height = new_section.page_height, new_section.page_widthnew_section.page_width = new_widthnew_section.page_height = new_height# 设置新节的边距:左右各1.25英寸,上下各0.8英寸new_section.left_margin = Inches(1.25)new_section.right_margin = Inches(1.25)new_section.top_margin = Inches(0.8)new_section.bottom_margin = Inches(0.8)# 4. 给新节添加内容(横向页面内容)document.add_heading('第二节:横向页面内容', level=1)document.add_paragraph('这是新节的内容,页面为横向,边距:左右1.25英寸、上下0.8英寸。')# 5. 再添加一个新节(偶数页开始,纵向布局)third_section = document.add_section(WD_SECTION_START.EVEN_PAGE)# 恢复纵向布局third_section.orientation = WD_ORIENT.PORTRAITthird_section.page_width = Inches(8.5)third_section.page_height = Inches(11)# 设置特殊边距(添加装订线)third_section.gutter = Inches(0.2)  # 装订线0.2英寸third_section.header_distance = Inches(0.6)  # 页眉距离0.6英寸# 6. 给第三个节添加内容document.add_heading('第三节:带装订线的纵向页面', level=1)document.add_paragraph('这一节包含0.2英寸的装订线,页眉距离页面顶部0.6英寸。')# 7. 遍历所有节,打印关键属性print("\n=== 所有节的关键属性 ===")for idx, section in enumerate(document.sections):    print(f"\n第{idx+1}节:")    print(f"  起始类型:{section.start_type}")    print(f"  页面方向:{section.orientation}")    print(f"  左右边距:{section.left_margin/914400:.2f}英寸 / {section.right_margin/914400:.2f}英寸")    print(f"  装订线:{section.gutter/914400:.2f}英寸")# 保存文档document.save("多节文档示例.docx")print("\n文档已保存为:多节文档示例.docx")

1.2.5 页眉页脚对象

页眉是指显示在每一页上页边距区域的文本,与正文内容相互独立,通常用于展示文档标题、作者、创建日期或页码等上下文信息。同一文档中的页眉在各页面间基本保持一致,仅在部分内容上可能存在细微差异,例如章节标题或页码的变化。页脚在功能和特性上与页眉完全类似,唯一的区别是页脚位于页面底部。页脚与脚注不同,脚注在各页面间并不统一。以下是操作文档页眉页脚的示例代码:

from docx import Document# -------------------------- 1. 初始化文档并创建基础页眉 --------------------------# 创建新文档doc = Document()# 获取文档的第一个节(新建文档默认只有1个节)section1 = doc.sections[0]header1 = section1.header# 检查初始状态:新建文档的页眉默认关联到前一节页眉设置(此处无前置节,故无实际页眉)print(f"初始页眉关联状态: {header1.is_linked_to_previous}")  # 输出: True# 为第一节添加简单页眉(仅左侧文本)# 直接编辑页眉的第一个段落(新建页眉默认包含1个空段落)para1 = header1.paragraphs[0]para1.text = "文档主标题 - 第一节页眉"# 自动创建独立页眉定义,关联状态变为Falseprint(f"添加页眉后关联状态: {header1.is_linked_to_previous}")  # 输出: False# -------------------------- 2. 添加带分区(左/中/右)的页眉 --------------------------# 先清空第一节原有页眉内容,重新设置分区页眉para1.clear()# 使用制表符\t分隔左、中、右三部分内容para1.text = "左侧:文档名称\t居中:2026年1月\t右侧:页码"# 应用Word默认的"Header"样式(确保制表位生效)para1.style = doc.styles["Header"]# -------------------------- 3. 添加新节并设置独立页眉 --------------------------# 向文档末尾添加新节(section2)section2 = doc.add_section()header2 = section2.header# 初始状态:新节的页眉默认关联到前一节(section1)print(f"第二节初始关联状态: {header2.is_linked_to_previous}")  # 输出: True# 验证:此时编辑header2的内容会直接修改section1的页眉(继承特性)# 先取消关联,创建第二节的独立页眉header2.is_linked_to_previous = False# 为第二节添加专属页眉para2 = header2.paragraphs[0]para2.text = "第二节独立页眉 - 仅本节显示"# -------------------------- 4. 添加页脚(与页眉用法完全一致) --------------------------# 为第一节添加页脚(包含页码)footer1 = doc.sections[0].footerfooter1.is_linked_to_previous = False# 取消关联,创建独立页脚footer_para1 = footer1.paragraphs[0]footer_para1.text = "\t第 {PAGE} 页 / 共 {NUMPAGES} 页\t"# 居中显示页码footer_para1.style = doc.styles["Footer"]# 为第二节添加不同的页脚footer2 = doc.sections[1].footerfooter2.is_linked_to_previous = Falsefooter_para2 = footer2.paragraphs[0]footer_para2.text = "第二节页脚 - 联系人:测试账号"# -------------------------- 5. 删除页眉(恢复关联状态) --------------------------# 若需删除第二节的独立页眉,只需将其关联状态设为True(会永久删除内容)# 此处仅演示,注释掉避免影响最终效果# header2.is_linked_to_previous = True# -------------------------- 6. 保存文档 --------------------------doc.save("页眉页脚示例.docx")print("文档已保存为:页眉页脚示例.docx")

unsetunset1.3 非文本内容管理unsetunset

1.3.1 样式管理

在Word中,内置样式会出现在Word界面的样式面板中,但不会自动加入文档中,直到你第一次使用它。这样避免了文件因所有样式定义而臃肿。一旦某样式被使用,其定义就会永久加入文档,即使后来删除应用内容也不会消失。因此,若要用python-docx使样式生效,必须在初始文档中包含其定义,否则样式会静默失效。 以下是一个综合性的示例,它整合了文档中所有核心的样式操作功能,包括样式的访问、应用、创建、删除,以及字符段落格式的定义等:

from docx import Documentfrom docx.enum.style import WD_STYLE_TYPEfrom docx.shared import Pt, Inchesfrom docx.enum.text import WD_UNDERLINE# 1. 创建新文档并访问样式集合doc = Document()styles = doc.stylesprint(f"初始样式数量: {len(styles)}")# 2. 访问并筛选特定类型的样式# 筛选所有段落样式并打印名称print("\n=== 所有段落样式 ===")paragraph_styles = [s for s in styles if s.type == WD_STYLE_TYPE.PARAGRAPH]for style in paragraph_styles[:5]:  # 只打印前5个避免输出过长    print(f"- {style.name}")# 3. 应用现有样式到新段落# 方式1: 创建时指定样式名称doc.add_heading("样式操作示例", level=0)heading1_para = doc.add_paragraph("这是应用 Heading 1 样式的段落", style="Heading 1")# 方式2: 先创建段落再赋值样式对象normal_para = doc.add_paragraph()normal_para.text = "这是先创建再应用 Normal 样式的段落"normal_para.style = styles["Normal"]# 4. 创建自定义样式# 4.1 创建段落样式并设置基础样式、字符格式、段落格式citation_style = styles.add_style("Citation", WD_STYLE_TYPE.PARAGRAPH)# 设置基础样式(继承 Normal 样式的格式)citation_style.base_style = styles["Normal"]# 设置字符格式citation_style.font.name = "宋体"citation_style.font.size = Pt(10)citation_style.font.italic = True# 斜体citation_style.font.underline = WD_UNDERLINE.DOT_DASH  # 点划线下划线# 设置段落格式(悬挂缩进、段前间距)citation_style.paragraph_format.left_indent = Inches(0.25)citation_style.paragraph_format.first_line_indent = Inches(-0.25)citation_style.paragraph_format.space_before = Pt(6)# 设置后续段落样式citation_style.next_paragraph_style = styles["Normal"]# 应用自定义样式citation_para = doc.add_paragraph("这是自定义 Citation 样式的引用文本", style="Citation")print(f"\n自定义样式应用后名称: {citation_para.style.name}")# 5. 控制样式在 Word 中的显示(快速样式、优先级)body_text_style = styles["Body Text"]body_text_style.hidden = Falsebody_text_style.quick_style = Truebody_text_style.priority = 1# 6. 处理潜在样式(Latent Styles)latent_styles = styles.latent_stylesprint(f"\n潜在样式总数: {len(latent_styles)}")# 为 List Bullet 添加潜在样式定义if"List Bullet"notin latent_styles:    latent_list_bullet = latent_styles.add_latent_style("List Bullet")    latent_list_bullet.hidden = False    latent_list_bullet.priority = 2    latent_list_bullet.quick_style = Trueprint(f"List Bullet 潜在样式优先级: {latent_styles['List Bullet'].priority}")# 7. 删除样式print(f"\n删除前样式数量: {len(styles)}")if"Citation"in styles:    styles["Citation"].delete()    print(f"删除后样式数量: {len(styles)}")# 8. 保存文档doc.save("样式操作示例.docx")print("\n文档已保存为: 样式操作示例.docx")

1.3.2 批注管理

Word支持在文档中添加批注,这是审阅功能的一部分,通常用于他人在不修改原文的情况下提供反馈。Word文档里操作步骤如下:

  1. 选取文本范围;
  2. 点击审阅工具栏中的新建批注;
  3. 输入或粘贴批注内容。

批注仅能添加至文档主体,不可插入页眉、页脚或其他批注内。Word文档里脚注和尾注中理论上允许添加批注,但当前python-docx暂不支持该操作。此外高版本Word支持解决批注和回复批注功能,但python-docx暂未实现。以下是包含批注创建、富文本批注、元数据修改及批注遍历的完整示例:

# 导入必要的库from docx import Documentfrom datetime import datetime, timezone"""创建文档并演示批注的完整操作流程:1. 创建基础批注2. 创建富文本格式批注3. 修改批注元数据4. 访问和遍历所有批注"""# 1. 初始化文档对象doc = Document()doc.add_heading("Python-docx 批注演示文档", level=1)# 2. 示例1:创建基础文本批注para1 = doc.add_paragraph("这是第一段测试文本,用于添加基础批注。")# 为整段文本添加基础批注basic_comment = doc.add_comment(    runs=para1.runs,  # 关联的文本块    text="基础批注:这段文本表述清晰,建议保留。",  # 批注纯文本内容    author="张三",  # 批注作者    initials="ZS"# 作者缩写)print(f"✅ 基础批注创建完成")# 3. 示例2:创建富文本格式批注(包含粗体、斜体等样式)para2 = doc.add_paragraph("这是第二段测试文本,用于添加富文本批注。")# 创建空内容批注(后续手动添加富文本)rich_comment = doc.add_comment(    runs=para2.runs,    text="",  # 初始为空,后续添加富文本    author="李四",    initials="LS")# 向批注中添加富文本内容cmt_para = rich_comment.paragraphs[0]  # 获取批注的默认段落cmt_para.add_run("富文本批注:")  # 普通文本cmt_para.add_run("重点建议:").bold = True# 粗体文本cmt_para.add_run("这段文本需要补充案例,").italic = True# 斜体文本cmt_para.add_run("建议参考行业标准。")  # 普通文本# 4. 示例3:修改批注元数据(作者、缩写)basic_comment.author = "张小三"# 修改作者名basic_comment.initials = "ZXS"# 修改作者缩写print(f"✅ 基础批注元数据已更新:作者={basic_comment.author},缩写={basic_comment.initials}")# 5. 示例4:访问和遍历所有批注print("\n📋 文档中所有批注信息:")for idx, comment in enumerate(doc.comments):    print(f"\n批注 {idx+1}:")    print(f"  作者:{comment.author}")    print(f"  缩写:{comment.initials}")# 提取批注的完整文本(兼容富文本)    comment_text = "\n  ".join([para.text for para in comment.paragraphs])    print(f"  内容:{comment_text}")# 6. 保存文档doc.save("批注演示文档.docx")print("\n📄 文档已保存为:批注演示文档.docx")

1.3.3 图片对象

Word文档中的内容分为两个图层:文本层和绘图层。文本层按从左到右、自上而下的顺序排列,页满则自动换页。绘图层中的对象称为形状,可自由放置。图片是一种特殊形状,可置于文本层或绘图层。位于文本层的图片称为嵌入式图片,它在排版中被视为一个大型文本字符:行高会自动调整以容纳图片,并支持类似文本的换行效果。若在其前方插入文本,图片会随之向后移动。嵌入式图片通常独占一个段落,但也可与前后文本共存于同一段落中。

当前python-docx库仅支持嵌入式图片。通过Document.add_picture()方法可将图片默认添加至文档末尾的独立段落中,但经过适当设置,也能实现灵活的图文混排效果,示例如下:

from docx import Documentfrom docx.shared import Inches, Ptfrom docx.enum.text import WD_ALIGN_PARAGRAPH# 1. 创建一个新的Word文档doc = Document()# 2. 基础用法:在文档末尾插入图片(单独占一个段落)doc.add_heading('1. 基础插入图片', level=2)# 添加图片,设置宽度为2英寸(高度会按比例自动调整)doc.add_picture('test.png', width=Inches(2))# 3. 进阶用法:图文混排(图片和文本在同一个段落)doc.add_heading('2. 图文混排示例', level=2)# 创建一个新段落mixed_paragraph = doc.add_paragraph()# 添加文本到段落开头mixed_paragraph.add_run('这是图片左侧的文本,')# 在段落中插入图片(非单独段落)img_run = mixed_paragraph.add_run()img_run.add_picture('test.png', width=Inches(1))# 在图片右侧添加文本mixed_paragraph.add_run('这是图片右侧的文本。')# 4. 自定义图片尺寸+段落对齐doc.add_heading('3. 自定义尺寸与对齐', level=2)align_para = doc.add_paragraph()align_para.alignment = WD_ALIGN_PARAGRAPH.CENTER  # 段落居中对齐align_run = align_para.add_run()# 同时设置宽度和高度(注意:可能导致图片变形)align_run.add_picture('test.png', width=Inches(1.5), height=Inches(1))align_para.add_run('\n这是居中显示的图片')# 5. 保存文档doc.save('形状图片示例.docx')print("文档已保存为形状图片示例.docx")

unsetunset1.4 综合示例unsetunset

在实际应用中,python-docx主要被用于文档修改和自动化生成,而非从头创建文档。本节将通过一个综合示例,展示如何对一个包含标题、段落、多种表格、多张图片和分页符的多页文档进行针对性修改,并提供相应的文档生成代码。

文档生成

以下代码生成一个示例多页文档,涵盖了日常办公中常见的文档结构:

from docx import Documentfrom docx.shared import Inches, Ptfrom docx.enum.text import WD_ALIGN_PARAGRAPHfrom docx.enum.table import WD_TABLE_ALIGNMENTfrom docx.oxml.ns import qnimport osdefensure_test_images():# 简单生成测试图片(如果没有的话)try:from PIL import Imagefor i in range(13):            img_path = f"image{i}.jpg"ifnot os.path.exists(img_path):                img = Image.new('RGB', (800600), color='lightblue')                img.save(img_path)        print("测试图片已准备完成")except ImportError:        print("请安装pillow库:pip install pillow")        exit(1)# 生成Word文档defgenerate_complex_doc():# 创建新文档    doc = Document()# 设置文档默认字体(解决中文显示问题)    doc.styles['Normal'].font.name = '微软雅黑'    doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')# ========== 第一页内容 ==========# 标题    title = doc.add_heading('XX项目调研报告'0)    title.alignment = WD_ALIGN_PARAGRAPH.CENTER  # 居中对齐    title_run = title.runs[0]    title_run.font.size = Pt(24)    title_run.font.bold = True# 副标题/说明    sub_para = doc.add_paragraph('报告生成时间:2026年1月  报告编制人:测试用户')    sub_para.alignment = WD_ALIGN_PARAGRAPH.RIGHT    sub_para_run = sub_para.runs[0]    sub_para_run.font.size = Pt(10)# 正文段落    doc.add_heading('一、项目概述', level=1)    overview_para = doc.add_paragraph()    overview_para.add_run('本项目针对企业数字化转型需求,重点解决现有业务系统数据孤岛、流程不规范、决策效率低等核心问题。').font.size = Pt(12)    overview_para.add_run('\n项目覆盖范围包括:').font.bold = True    overview_para.add_run('\n1) 生产管理模块:实现生产流程自动化监控')    overview_para.add_run('\n2) 销售管理模块:打通客户数据与订单系统')    overview_para.add_run('\n3) 财务管理模块:实现财务数据实时汇总分析')# 第一个表格:项目基础信息表(2行4列)    doc.add_heading('1.1 项目基础信息', level=2)    table1 = doc.add_table(rows=2, cols=4)    table1.alignment = WD_TABLE_ALIGNMENT.CENTER  # 表格居中    table1.style = 'Table Grid'# 带边框样式# 填充表格1表头    hdr_cells = table1.rows[0].cells    hdr_cells[0].text = '项目编号'    hdr_cells[1].text = '项目名称'    hdr_cells[2].text = '启动时间'    hdr_cells[3].text = '预计工期'# 填充表格1内容    row_cells = table1.rows[1].cells    row_cells[0].text = 'XM2026001'    row_cells[1].text = '企业数字化转型项目'    row_cells[2].text = '2026-01-01'    row_cells[3].text = '12个月'# 调整表格1单元格字体for row in table1.rows:for cell in row.cells:for paragraph in cell.paragraphs:for run in paragraph.runs:                    run.font.size = Pt(10)                    run.font.name = '微软雅黑'                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')# 插入第一张图片    doc.add_heading('1.2 项目架构图', level=2)    img1_para = doc.add_paragraph()    img1_para.alignment = WD_ALIGN_PARAGRAPH.CENTER    img1_run = img1_para.add_run()    img1_run.add_picture('image1.jpg', width=Inches(5))  # 图片宽度5英寸    img1_para.add_run('\n图1:项目整体架构图').font.size = Pt(10)# 插入分页符(第一页结束)    doc.add_page_break()# ========== 第二页内容 ==========    doc.add_heading('二、项目资源配置', level=1)    resource_para = doc.add_paragraph('本项目所需资源包括人力资源、硬件资源、软件资源三大类,具体配置如下表所示:')# 第二个表格:资源配置表(5行3列)    table2 = doc.add_table(rows=5, cols=3)    table2.style = 'Table Grid'    table2.alignment = WD_TABLE_ALIGNMENT.CENTER# 填充表格2    table2_data = [        ['资源类型''规格/数量''备注'],        ['人力资源''项目经理1人,开发工程师5人,测试工程师2人''均为全职'],        ['服务器''8核16G云服务器3台''阿里云ECS'],        ['数据库''MySQL 8.0 主从架构''数据实时备份'],        ['软件授权''Python、Office、开发工具''企业版授权']    ]for i, row_data in enumerate(table2_data):        row_cells = table2.rows[i].cellsfor j, cell_text in enumerate(row_data):            row_cells[j].text = cell_text# 设置单元格字体for paragraph in row_cells[j].paragraphs:for run in paragraph.runs:                    run.font.size = Pt(10)                    run.font.name = '微软雅黑'                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')# 表头加粗if i == 0:for cell in table2.rows[i].cells:for paragraph in cell.paragraphs:for run in paragraph.runs:                        run.font.bold = True# 插入第二张图片    doc.add_heading('2.1 资源部署示意图', level=2)    img2_para = doc.add_paragraph()    img2_para.alignment = WD_ALIGN_PARAGRAPH.CENTER    img2_run = img2_para.add_run()    img2_run.add_picture('image2.jpg', width=Inches(5))    img2_para.add_run('\n图2:资源部署拓扑图').font.size = Pt(10)# 补充段落内容    doc.add_paragraph('资源配置遵循「够用且预留扩展」原则,硬件资源可根据项目进度弹性扩容,人力资源采用「核心+外协」模式保障交付进度。')# 插入分页符(第二页结束)    doc.add_page_break()# ========== 第三页内容 ==========    doc.add_heading('三、项目风险评估', level=1)    risk_para = doc.add_paragraph('通过对技术、人员、成本、进度四个维度的评估,识别出以下核心风险点及应对措施:')# 第三个表格:风险评估表(4行4列)    table3 = doc.add_table(rows=4, cols=4)    table3.style = 'Table Grid'    table3.alignment = WD_TABLE_ALIGNMENT.CENTER    table3_data = [        ['风险类型''风险等级''影响范围''应对措施'],        ['技术风险''中''核心功能模块''提前进行技术预研,制定备选方案'],        ['进度风险''低''整体交付''设置里程碑节点,每周进度复盘'],        ['成本风险''低''预算管控''建立成本台账,超支提前预警']    ]for i, row_data in enumerate(table3_data):        row_cells = table3.rows[i].cellsfor j, cell_text in enumerate(row_data):            row_cells[j].text = cell_textfor paragraph in row_cells[j].paragraphs:for run in paragraph.runs:                    run.font.size = Pt(10)                    run.font.name = '微软雅黑'                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')if i == 0:for cell in table3.rows[i].cells:for paragraph in cell.paragraphs:for run in paragraph.runs:                        run.font.bold = True# 结尾段落    doc.add_paragraph('\n综上所述,本项目整体可控,通过科学的资源配置和风险管控措施,能够保障项目按计划交付并达到预期目标。')# 保存文档    doc.save('项目报告.docx')    print("项目报告文档已生成")if __name__ == '__main__':    ensure_test_images()  # 准备测试图片    generate_complex_doc()

文档修改

文档修改代码针对上述生成的文档,实现以下常见修改需求:

  • 修改标题和段落文本
  • 修改表格中的内容
  • 替换图片
  • 添加新的段落和表格
  • 修改字体样式

示例代码如下:

from docx import Documentfrom docx.shared import Inches, Ptfrom docx.shared import RGBColorfrom docx.enum.table import WD_TABLE_ALIGNMENTfrom docx.enum.text import WD_ALIGN_PARAGRAPHfrom docx.oxml.ns import qnimport os# 修改已生成的Word文档defmodify_complex_doc(file_path):# 打开已生成的文档    doc = Document(file_path)    print("已打开待修改的文档")# ========== 1. 修改标题 ==========# 第一个标题是级别0的标题(主标题)    main_title = doc.paragraphs[0]    main_title.runs[0].text = 'XX企业数字化转型项目终版报告'# 修改主标题文本    main_title.runs[0].font.color.rgb = RGBColor(00255)  # 标题改为蓝色    main_title.runs[0].font.size = Pt(20)    main_title.runs[0].font.name = '微软雅黑'    main_title.runs[0]._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')    main_title.alignment = WD_ALIGN_PARAGRAPH.CENTER# ========== 2. 修改段落文本 ==========# 找到"项目概述"下的段落(可通过文本特征定位)for para in doc.paragraphs:if'本项目针对企业数字化转型需求'in para.text:# 清空原有内容,重新写入            para.clear()            new_run = para.add_run('本项目针对大型制造企业数字化转型需求,重点解决现有业务系统数据孤岛、流程不规范、决策效率低等核心问题。')            new_run.font.size = Pt(12)            new_run.font.name = '微软雅黑'            new_run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')# 追加内容            para.add_run('\n项目升级后新增:')            para.add_run('\n4) 供应链管理模块:打通上下游供应商数据')break# ========== 3. 修改表格内容并添加表格名 ==========# 表格1:项目基础信息表(第一个表格)    table1 = doc.tables[0]# 修改项目编号    table1.rows[1].cells[0].text = 'XM2026001-FINAL'# 修改预计工期    table1.rows[1].cells[3].text = '10个月'# 给修改后的单元格文字标红for cell in [table1.rows[1].cells[0], table1.rows[1].cells[3]]:for para in cell.paragraphs:for run in para.runs:                run.font.color.rgb = RGBColor(25500)                run.font.size = Pt(11)                run.font.name = '微软雅黑'                run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')# 为表格1添加表格名(表题)# 找到表格1的位置,在表格上方插入表名    table1_elem = table1._element    table_caption1 = doc.add_paragraph('表1 项目基础信息表')    table_caption1.alignment = WD_ALIGN_PARAGRAPH.CENTER  # 居中对齐    table_caption1.paragraph_format.space_before = Pt(0)    table_caption1.paragraph_format.space_after = Pt(0)# 设置表名字体格式for run in table_caption1.runs:        run.font.size = Pt(11)        run.font.name = '微软雅黑'        run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')        run.font.bold = True# 加粗# 将表名插入到表格上方    table1_elem.addprevious(table_caption1._element)# 表格2:资源配置表(第二个表格)    table2 = doc.tables[1]# 修改服务器配置    table2.rows[3].cells[1].text = '16核32G云服务器3台(升级配置)'# 设置表格2单元格字体for row in table2.rows:for cell in row.cells:for para in cell.paragraphs:for run in para.runs:                    run.font.size = Pt(11)                    run.font.name = '微软雅黑'                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')# 为表格2添加表格名(表题)    table2_elem = table2._element    table_caption2 = doc.add_paragraph('表2 项目资源配置表')    table_caption2.alignment = WD_ALIGN_PARAGRAPH.CENTERfor run in table_caption2.runs:        run.font.size = Pt(11)        run.font.name = '微软雅黑'        run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')        run.font.bold = True    table2_elem.addprevious(table_caption2._element)# ========== 4. 替换图片并规范图名 ==========# 先准备一张新的测试图片from PIL import Image    new_img_path = 'test.png'ifnot os.path.exists(new_img_path):        img = Image.new('RGB', (800600), color='lightgreen')        img.save(new_img_path)# 找到第一张图片所在的段落(通过图片相关特征)    img_para_index = -1for i, para in enumerate(doc.paragraphs):if'图1:项目整体架构图'in para.text or'graphicData'in str(para._element.xml):            img_para_index = ibreakif img_para_index != -1:# 清空段落中的图片和文字,重新添加        img_para = doc.paragraphs[img_para_index]        img_para.clear()# 重新添加新图片        img_run = img_para.add_run()        img_run.add_picture(new_img_path, width=Inches(5))# 添加规范的图名(图题)        img_caption = img_para.add_run('\n图1 项目整体架构图(终版)')        img_caption.font.size = Pt(10)        img_caption.font.name = '微软雅黑'        img_caption._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')        img_para.alignment = WD_ALIGN_PARAGRAPH.CENTER# ========== 5. 添加新内容并为新表格加表名 ==========# 在第三页风险评估后添加新的段落和表格# 先找到风险评估标题的位置,在其后添加内容for i, para in enumerate(doc.paragraphs):if'三、项目风险评估'in para.text:# 添加新的子标题            new_sub_heading = doc.add_heading('3.1 风险应对预案', level=2)# 插入到指定位置            doc.paragraphs.insert(i+1, new_sub_heading)# 添加新段落            new_para = doc.add_paragraph('针对高优先级风险,制定专项应对预案,包括应急响应流程、备用资源调配方案等,确保风险发生时可快速处置。')            new_para.alignment = WD_ALIGN_PARAGRAPH.JUSTIFYfor run in new_para.runs:                run.font.size = Pt(12)                run.font.name = '微软雅黑'                run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')            doc.paragraphs.insert(i+2, new_para)# 添加新表格(应急预案表)            new_table = doc.add_table(rows=2, cols=2)            new_table.style = 'Table Grid'            new_table.alignment = WD_TABLE_ALIGNMENT.CENTER# 填充新表格            new_table.rows[0].cells[0].text = '风险类型'            new_table.rows[0].cells[1].text = '应急联系人'            new_table.rows[1].cells[0].text = '技术风险'            new_table.rows[1].cells[1].text = '张工 13800138000'# 设置新表格字体for row in new_table.rows:for cell in row.cells:for para_cell in cell.paragraphs:for run in para_cell.runs:                            run.font.size = Pt(10)                            run.font.name = '微软雅黑'                            run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')# 为新表格添加表名            new_table_caption = doc.add_paragraph('表3 风险应急联系人表')            new_table_caption.alignment = WD_ALIGN_PARAGRAPH.CENTERfor run in new_table_caption.runs:                run.font.size = Pt(11)                run.font.name = '微软雅黑'                run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')                run.font.bold = True# 插入新表格名和新表格            doc.element.body.insert(i+3, new_table_caption._element)            doc.element.body.insert(i+4, new_table._element)break# ========== 保存修改后的文档 ==========    doc.save('项目报告_修改版.docx')    print("修改后的文档已保存:项目报告_修改版.docx")if __name__ == '__main__':# 确保原文档存在    file_path = '项目报告.docx'ifnot os.path.exists(file_path):        print("请先运行生成代码创建原始文档!")else:        modify_complex_doc(file_path)

欢迎关注我的公众号“彭彭加油鸭”,原创技术文章第一时间推送。

参考资料

[1] 

python-docx: https://github.com/python-openxml/python-docx

[2] 

python-docx docs: https://python-docx.readthedocs.io/en/latest/

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-02-08 18:03:28 HTTP/2.0 GET : https://f.mffb.com.cn/a/462891.html
  2. 运行时间 : 0.083728s [ 吞吐率:11.94req/s ] 内存消耗:4,647.93kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=9ab912d635e3fc3933cbe3496d5fb4a4
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000463s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000692s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000361s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000293s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000504s ]
  6. SELECT * FROM `set` [ RunTime:0.000191s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000633s ]
  8. SELECT * FROM `article` WHERE `id` = 462891 LIMIT 1 [ RunTime:0.000577s ]
  9. UPDATE `article` SET `lasttime` = 1770545008 WHERE `id` = 462891 [ RunTime:0.008043s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000291s ]
  11. SELECT * FROM `article` WHERE `id` < 462891 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000404s ]
  12. SELECT * FROM `article` WHERE `id` > 462891 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000370s ]
  13. SELECT * FROM `article` WHERE `id` < 462891 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.000712s ]
  14. SELECT * FROM `article` WHERE `id` < 462891 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.000785s ]
  15. SELECT * FROM `article` WHERE `id` < 462891 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.000810s ]
0.085314s