使用 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 中的合并单元格、段落换行等结构在转换为二维数据时可能需要额外处理,应根据数据的最终用途决定具体的转换方式。

相关推荐
weixin_440730501 小时前
函数return、参数、参数组、递归函数、高阶函数等小结
开发语言·python
天赐范式1 小时前
天赐范式第181天:让视图开始切换——PBFT视图切换与从safety到liveness的跨越
python·pbft·数字生命·天赐范式·动态运行时·拜占庭容错
sugarzhangnotes1 小时前
【无标题】
开发语言·人工智能·python
weixin_447195292 小时前
【无标题】
pytorch·python
迅猛龙办公室2 小时前
Python实现简单的人名对话
python
阿坨2 小时前
firestart:一行命令启动你的日常应用和网页
python·pypi·cli·click
老歌老听老掉牙3 小时前
麻花钻切屑形态演变的力学机制与临界条件分析
python·算法·钻头
happylifetree3 小时前
Python18(补充):练习
python
weixin_416667964 小时前
银河麒麟V10看门狗试验-1
网络·chrome·python
古城小栈4 小时前
Pydantic 从入门到实践全讲解
python