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

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

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

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

环境设置

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

复制代码
pip install Spire.Doc

使用 Python 读取 Word 表格数据

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

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

ini 复制代码
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​​ 的结构类似于:

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

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

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

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

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

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

ini 复制代码
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 文档包含三个表格,运行后会得到:

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

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

保留单元格中的换行

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

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

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

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

提取后会得到:

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

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

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

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

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

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

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

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

ini 复制代码
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} 个表格"
    )

假设输入目录中包含:

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

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

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

相关推荐
有味道的男人1 小时前
得物详情 API|支持实时价格、成色、鉴别服务数据
windows·python·api
小溪学编程1 小时前
Java BufferedReader 详解:从基础用法到性能优化
java·python·性能优化
2601_962300471 小时前
基于Python与Tkinter的ADB Monkey自动化测试脚本开发
python·adb·tkinter·android测试·gui自动化
SamChan901 小时前
PDF翻译后的格式完整性校验:用Python自动比对译文与原文档的表格与段落结构
开发语言·python·ai·pdf·机器翻译
2601_962077982 小时前
Python是一门什么样的语言?
python·编程语言·解释器·编译型·解释型
用户019027581612 小时前
不用 SDK 也能取 A 股数据:AlphaFeed REST API 用 cURL/HTTP 直连教程
python
旋生万物2 小时前
素数都排在等角螺线上?用螺旋数论给黎曼猜想画一张“几何画像“(附Python)
python·ai编程·数论·黎曼猜想·素数分布
用户3721574261352 小时前
使用 Python 压缩 PDF 文件:减小图片、字体和文档内容体积
python
java1234_小锋2 小时前
Tornado 6.5,全面支持 Python 3.14
数据库·python·tornado