使用 Python 提取 Word 文档中的表格数据

Word 文档中的表格经常用于保存统计数据、项目清单、检测记录和业务报表。如果只是偶尔处理一两个文件,可以直接复制表格内容;但当文档包含多个表格,或者需要批量提取大量 Word 文件中的数据时,手动操作就比较低效。

通过 Python,可以按照文档、节、表格、行和单元格的层级读取 Word 表格,并将提取的数据继续用于统计分析、数据库导入,或者保存为 CSV 等结构化文件。

本文介绍如何使用 Python 读取 Word 表格数据、提取文档中的所有表格,以及批量处理多个 Word 文件。

环境设置

要运行下面的代码示例,需要先安装 Word 处理所需的 Python 模块:

bash 复制代码
pip install Spire.Doc

使用 Python 读取 Word 表格数据

如果只需要读取文档中的某一个表格,可以先获取表格对象,再依次遍历其中的行和单元格。

下面的示例读取 Word 文档第一个节中的第一个表格,并将表格内容保存到二维列表中:

python 复制代码
from spire.doc import *
from spire.doc.common import *

input_file = "input.docx"

# 加载 Word 文档
document = Document()
document.LoadFromFile(input_file)

# 获取第一个节
section = document.Sections.get_Item(0)

# 获取第一个表格
table = section.Tables.get_Item(0)

table_data = []

# 遍历表格中的行
for r in range(table.Rows.Count):
    row = table.Rows.get_Item(r)
    row_data = []

    # 遍历当前行中的单元格
    for c in range(row.Cells.Count):
        cell = row.Cells.get_Item(c)

        # 一个单元格中可能包含多个段落
        paragraphs = []

        for p in range(cell.Paragraphs.Count):
            text = cell.Paragraphs.get_Item(p).Text.strip()

            if text:
                paragraphs.append(text)

        # 合并单元格中的段落文本
        row_data.append(" ".join(paragraphs))

    table_data.append(row_data)

# 输出表格数据
for row in table_data:
    print(row)

document.Close()

Word 单元格中并不一定只有一段文字,因此代码没有直接读取某一个段落,而是遍历 cell.Paragraphs,再将同一单元格中的多个段落合并。

提取完成后,table_data 的结构类似于:

python 复制代码
[
    ["姓名", "部门", "职位"],
    ["张三", "研发部", "开发工程师"],
    ["李四", "测试部", "测试工程师"]
]

得到二维数据后,可以继续进行筛选、统计、数据库写入或文件导出。

将 Word 中的所有表格提取为 CSV

一个 Word 文档可能包含多个节,每个节中又可能包含多个表格。

如果需要完整提取文档中的表格,应该依次遍历所有节中的 Tables 集合,而不是只读取第一个表格。

下面的示例将每个 Word 表格分别保存为一个 CSV 文件:

python 复制代码
import csv
import os
from spire.doc import *
from spire.doc.common import *

input_file = "input.docx"
output_folder = "ExtractedTables"

# 创建输出目录
os.makedirs(output_folder, exist_ok=True)

# 加载 Word 文档
document = Document()
document.LoadFromFile(input_file)

table_number = 0

# 遍历文档中的所有节
for s in range(document.Sections.Count):
    section = document.Sections.get_Item(s)

    # 遍历当前节中的所有表格
    for t in range(section.Tables.Count):
        table = section.Tables.get_Item(t)
        table_number += 1

        output_file = os.path.join(
            output_folder,
            f"table_{table_number}.csv"
        )

        with open(
            output_file,
            "w",
            newline="",
            encoding="utf-8-sig"
        ) as csv_file:

            writer = csv.writer(csv_file)

            # 遍历表格中的行
            for r in range(table.Rows.Count):
                row = table.Rows.get_Item(r)
                row_data = []

                # 遍历行中的单元格
                for c in range(row.Cells.Count):
                    cell = row.Cells.get_Item(c)
                    paragraphs = []

                    for p in range(cell.Paragraphs.Count):
                        text = cell.Paragraphs.get_Item(p).Text.strip()

                        if text:
                            paragraphs.append(text)

                    row_data.append(" ".join(paragraphs))

                writer.writerow(row_data)

document.Close()

print(f"共提取 {table_number} 个表格。")

例如,一个 Word 文档包含三个表格,运行后会得到:

text 复制代码
ExtractedTables/
├── table_1.csv
├── table_2.csv
└── table_3.csv

这里使用 utf-8-sig 编码保存 CSV,主要是为了减少包含中文内容的文件在常用表格软件中直接打开时出现乱码的情况。

保留单元格中的换行

前面的示例使用空格连接单元格中的多个段落:

python 复制代码
" ".join(paragraphs)

例如,Word 单元格原本包含:

text 复制代码
产品名称
产品型号

提取后会得到:

text 复制代码
产品名称 产品型号

如果需要保留原有的分行关系,可以改为:

python 复制代码
"\n".join(paragraphs)

这样导出到 CSV 后,多个段落仍然会保留在同一个单元格中,只是以换行符分隔。

具体采用哪种方式,取决于后续如何使用这些数据。如果只是用于数据库导入或数据分析,合并为空格通常更方便;如果希望尽量保留原有内容结构,可以使用换行符。

批量提取多个 Word 文件中的表格

如果一个目录中包含大量 Word 文档,可以将提取过程封装成函数,然后批量处理 .doc.docx 文件。

下面的示例为每个 Word 文档创建一个独立目录,并将其中的所有表格分别保存为 CSV:

python 复制代码
import csv
import os
from spire.doc import *
from spire.doc.common import *


def extract_tables(word_file, output_folder):

    os.makedirs(output_folder, exist_ok=True)

    document = Document()
    document.LoadFromFile(word_file)

    table_number = 0

    for s in range(document.Sections.Count):
        section = document.Sections.get_Item(s)

        for t in range(section.Tables.Count):
            table = section.Tables.get_Item(t)
            table_number += 1

            output_file = os.path.join(
                output_folder,
                f"table_{table_number}.csv"
            )

            with open(
                output_file,
                "w",
                newline="",
                encoding="utf-8-sig"
            ) as csv_file:

                writer = csv.writer(csv_file)

                for r in range(table.Rows.Count):
                    row = table.Rows.get_Item(r)
                    row_data = []

                    for c in range(row.Cells.Count):
                        cell = row.Cells.get_Item(c)
                        paragraphs = []

                        for p in range(cell.Paragraphs.Count):
                            text = (
                                cell.Paragraphs
                                .get_Item(p)
                                .Text
                                .strip()
                            )

                            if text:
                                paragraphs.append(text)

                        row_data.append(
                            " ".join(paragraphs)
                        )

                    writer.writerow(row_data)

    document.Close()

    return table_number


input_folder = "WordFiles"
output_folder = "ExtractedTables"

for file_name in os.listdir(input_folder):

    if not file_name.lower().endswith((".doc", ".docx")):
        continue

    input_file = os.path.join(
        input_folder,
        file_name
    )

    document_name = os.path.splitext(file_name)[0]

    document_output = os.path.join(
        output_folder,
        document_name
    )

    count = extract_tables(
        input_file,
        document_output
    )

    print(
        f"{file_name}:提取 {count} 个表格"
    )

假设输入目录中包含:

text 复制代码
WordFiles/
├── report.docx
├── inventory.docx
└── records.doc

处理后会按照文档名称分别保存:

text 复制代码
ExtractedTables/
├── report/
│   ├── table_1.csv
│   └── table_2.csv
├── inventory/
│   └── table_1.csv
└── records/
    ├── table_1.csv
    └── table_2.csv

这种方式可以避免不同 Word 文档中的表格文件相互覆盖,也更方便后续按照原文档进行分类处理。

提取 Word 表格时需要注意什么

Word 表格与 CSV 这样的二维数据并不是完全对应的,因此提取时有几个问题需要注意。

情况 处理方式
一个单元格包含多个段落 使用空格或换行符连接
单元格为空 保留空字符串,避免影响列的位置
文档包含多个节 遍历所有 Sections
每个节包含多个表格 遍历每个节的 Tables
文档包含合并单元格 导出后检查数据对应关系
需要处理多个 Word 文件 为每个文档建立独立输出目录

其中,合并单元格尤其值得注意。

Word 可以在横向或纵向合并多个单元格,而 CSV 本身没有"合并单元格"的概念。因此,将 Word 表格转换为纯二维数据之后,原有的合并关系无法直接保留。

如果后续需要将数据导入数据库或用于统计分析,通常还需要根据具体表格结构决定如何填充这些空缺位置。

总结

使用 Python 提取 Word 表格,本质上是按照文档结构依次访问节、表格、行和单元格,再读取每个单元格中的段落文本。

如果只需要一个表格,可以直接获取指定的 Table 对象;如果文档中包含多个表格,则可以遍历所有节中的 Tables 集合,并将每个表格分别保存为 CSV。

对于批量文档,可以进一步将提取逻辑封装成函数,实现多个 Word 文件的自动读取和分类保存。需要注意的是,Word 中的合并单元格、段落换行等结构在转换为二维数据时可能需要额外处理,应根据数据的最终用途决定具体的转换方式。

相关推荐
for_ever_love__42 分钟前
python基础语法学习: 动态类型
开发语言·python·学习
troy1281 小时前
分布式系统框架选型指南:主流框架优缺点深度对比
python·django·pygame
129Lab1 小时前
BMS算法快速原型开发:AI辅助实现扩展卡尔曼滤波(EKF)SOC估算从理论到代码落地
python·嵌入式开发·bms·卡尔曼滤波·电池管理系统·soc估算
萧鼎1 小时前
safetensors 库的安装、核心语法与实战用法,安全保存模型权重
python·开源·教程·python库·safetensors
千里码aicood2 小时前
基于Python语言的测量程序设计
开发语言·python
2601_962300812 小时前
用PyTorch Lightning简化空间分析:Python和机器学习的力量
python·深度学习·机器学习·空间分析·pytorchlightning
jayson.h2 小时前
python-可视化提取表格-通用
开发语言·python
悟天特斯3 小时前
AI驱动的楼宇节能:从粗放管控到精准降碳的实践路径
开发语言·人工智能·python·物联网
名字还没想好☜3 小时前
Python 用 tempfile 安全创建临时文件:NamedTemporaryFile、TemporaryDirectory 与别自己拼 /tmp 的坑
开发语言·后端·python·安全·编程语言