HOOOS

Python实战:自动提取PDF表格数据并导出CSV(含代码示例)

0 5 数据挖掘者小李 PythonPDF表格提取CSV导出
Apple

在日常工作中,我们经常需要从PDF文档中提取表格数据。手动复制粘贴效率低下,且容易出错。本文将介绍如何使用Python编写程序,自动识别并提取PDF文档中的表格数据,并将其保存为CSV格式,方便后续分析和处理。我们将重点解决表格跨页、合并单元格等复杂情况,并提供详细的代码示例。

1. 准备工作

在开始之前,需要安装以下Python库:

  • pdfplumber: 用于解析PDF文档,提取文本和表格。
  • pandas: 用于处理表格数据,并导出为CSV格式。

可以使用pip命令安装:

pip install pdfplumber pandas

2. 代码实现

以下是一个示例代码,可以提取PDF文档中的所有表格,并将每个表格保存为一个CSV文件。

import pdfplumber
import pandas as pd
import os


def extract_tables_from_pdf(pdf_path, output_dir='tables'):
    """从PDF文档中提取表格数据,并保存为CSV文件。"

    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    with pdfplumber.open(pdf_path) as pdf:
        table_index = 1
        for i, page in enumerate(pdf.pages):
            tables = page.extract_tables()
            if tables:
                for table in tables:
                    # 将表格数据转换为DataFrame
                    df = pd.DataFrame(table[1:], columns=table[0]) if table[0] else pd.DataFrame(table)

                    # 清理DataFrame:移除空行、空列和特殊字符
                    df = df.dropna(axis=0, how='all')  # 移除所有值均为 NaN 的行
                    df = df.dropna(axis=1, how='all')  # 移除所有值均为 NaN 的列

                    # 移除DataFrame中的换行符(\n)、制表符(\t)和回车符(\r)
                    df = df.replace({r'[\n\t\r]': ''}, regex=True)

                    # 将DataFrame中的None值替换为空字符串
                    df = df.fillna('')

                    # 保存为CSV文件
                    output_path = os.path.join(output_dir, f'table_{table_index}_page_{i+1}.csv')
                    df.to_csv(output_path, index=False, encoding='utf-8-sig')
                    print(f'表格 {table_index} 从第 {i+1} 页提取成功,保存到:{output_path}')
                    table_index += 1


if __name__ == '__main__':
    pdf_file = 'example.pdf'  # 替换为你的PDF文件路径
    extract_tables_from_pdf(pdf_file)

代码解释:

  1. 导入库: 导入pdfplumberpandas库。
  2. extract_tables_from_pdf 函数:
    • 接收PDF文件路径和输出目录作为参数。
    • 使用pdfplumber.open()打开PDF文档。
    • 循环遍历每一页,使用page.extract_tables()提取表格。
    • 将提取的表格数据转换为pandas.DataFrame
    • 将DataFrame保存为CSV文件,文件名包含表格索引和页码。
  3. 主程序:
    • 指定PDF文件路径。
    • 调用extract_tables_from_pdf函数,提取表格数据。

3. 处理复杂表格

3.1 表格跨页

pdfplumber可以自动处理表格跨页的情况。当表格跨页时,page.extract_tables()会将跨页的表格合并为一个表格。

3.2 合并单元格

pdfplumber对合并单元格的支持有限。提取的表格数据中,合并的单元格可能会被拆分为多个单元格。为了解决这个问题,可以尝试以下方法:

  • 手动调整: 提取表格后,手动编辑CSV文件,合并被拆分的单元格。这适用于表格数量较少的情况。
  • 自定义解析: 如果PDF文档的格式比较规范,可以尝试自定义解析方法。例如,根据单元格的坐标和文本内容,判断是否为合并单元格,并进行合并。

以下是一个自定义解析合并单元格的示例代码:

import pdfplumber
import pandas as pd
import os

def extract_tables_with_merged_cells(pdf_path, output_dir='tables_merged'):
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    with pdfplumber.open(pdf_path) as pdf:
        table_index = 1
        for i, page in enumerate(pdf.pages):
            # 使用`extract_table`方法,并自定义参数
            table = page.extract_table({
                'vertical_strategy': 'lines',
                'horizontal_strategy': 'lines',
                'explicit_vertical_lines': page.vertical_lines,
                'explicit_horizontal_lines': page.horizontal_lines
            })

            if table:
                # 将表格数据转换为DataFrame
                df = pd.DataFrame(table[1:], columns=table[0]) if table[0] else pd.DataFrame(table)

                # 清理DataFrame:移除空行、空列和特殊字符
                df = df.dropna(axis=0, how='all')  # 移除所有值均为 NaN 的行
                df = df.dropna(axis=1, how='all')  # 移除所有值均为 NaN 的列

                # 移除DataFrame中的换行符(\n)、制表符(\t)和回车符(\r)
                df = df.replace({r'[\n\t\r]': ''}, regex=True)

                # 将DataFrame中的None值替换为空字符串
                df = df.fillna('')

                # 保存为CSV文件
                output_path = os.path.join(output_dir, f'table_{table_index}_page_{i+1}.csv')
                df.to_csv(output_path, index=False, encoding='utf-8-sig')
                print(f'表格 {table_index} 从第 {i+1} 页提取成功,保存到:{output_path}')
                table_index += 1


if __name__ == '__main__':
    pdf_file = 'example.pdf'  # 替换为你的PDF文件路径
    extract_tables_with_merged_cells(pdf_file)

代码解释:

  1. 使用extract_table方法: 使用page.extract_table()方法,而不是page.extract_tables()方法。extract_table方法允许自定义参数,更灵活地控制表格提取过程。
  2. 自定义参数: 通过vertical_strategyhorizontal_strategyexplicit_vertical_linesexplicit_horizontal_lines等参数,指定表格的提取策略。这些参数可以帮助pdfplumber更准确地识别表格的边界,从而更好地处理合并单元格。

注意: 自定义解析方法需要根据具体的PDF文档进行调整。不同的PDF文档可能需要不同的参数设置才能达到最佳效果。

4. 优化和改进

  • 错误处理: 在代码中添加错误处理机制,例如,捕获文件不存在、PDF格式错误等异常,提高程序的健壮性。
  • 进度显示: 当处理大型PDF文档时,可以添加进度显示,让用户了解程序的运行状态。
  • 多线程处理: 对于包含大量表格的PDF文档,可以使用多线程技术,并行提取表格数据,提高程序的运行效率。
  • 更强大的库: 尝试使用camelottabula-py等更专业的PDF表格提取库,它们可能在处理复杂表格方面表现更好。 但这些库通常依赖于外部Java环境,配置可能相对复杂。
  • OCR: 如果PDF是扫描件,需要先进行OCR识别,将图片转换为文本,才能提取表格数据。可以使用pytesseract库进行OCR识别。

5. 总结

本文介绍了如何使用Python自动提取PDF表格数据,并保存为CSV格式。我们提供了详细的代码示例,并讨论了如何处理表格跨页、合并单元格等复杂情况。通过学习本文,您可以快速构建自己的PDF表格提取工具,提高工作效率。

希望本文对您有所帮助!快去试试吧! 记住,实践是检验真理的唯一标准,多尝试不同的PDF文档,你就能掌握更多技巧!

点评评价

captcha
健康