当前位置:首页 > Python > 正文

Python提取PDF文本数字 - 详细教程与代码示例

Python提取PDF文本数字的详细教程

在数据分析、财务报告处理和信息提取工作中,经常需要从PDF文档中提取数字数据。本教程将详细介绍如何使用Python高效地从PDF文件中提取文本和数字。

为什么需要从PDF提取数字?

PDF是存储报告、发票和财务文档的常用格式,但提取其中的结构化数据却很困难。常见应用场景包括:

  • 财务报告中的金额数据提取
  • 科学研究论文中的数值结果收集
  • 发票处理系统中的自动化数据录入
  • 市场分析报告中的统计数字抓取

Python库选择与安装

Python有几个优秀的PDF处理库:

库名称 特点 安装命令
pdfplumber 提取文本准确,支持表格提取,简单易用 pip install pdfplumber
PyPDF2 基础PDF操作,文本提取功能有限 pip install PyPDF2
pdfminer.six 强大的文本提取,但API较复杂 pip install pdfminer.six

本教程将使用pdfplumber,因为它提供了直观的API和出色的文本提取能力。

PDF文本提取基础

使用pdfplumber提取PDF文本的基本方法:

示例代码:提取整个PDF文本

import pdfplumber

def extract_text_from_pdf(pdf_path):
    all_text = ""
    with pdfplumber.open(pdf_path) as pdf:
        for page in pdf.pages:
            text = page.extract_text()
            if text:
                all_text += text + "\n"
    return all_text

# 使用示例
pdf_text = extract_text_from_pdf("财务报告.pdf")
print(pdf_text)

这段代码会遍历PDF的每一页,提取所有文本内容并合并为一个字符串。

使用正则表达式提取数字

从提取的文本中识别数字需要正则表达式:

数字提取函数

import re

def extract_numbers(text):
    # 匹配整数、小数、科学计数法、带逗号的数字
    pattern = r"[-+]?\d{1,3}(?:,\d{3})*(?:\.\d+)?(?:[eE][-+]?\d+)?"
    numbers = re.findall(pattern, text)
    
    # 清理数字格式(移除逗号)
    cleaned_numbers = [num.replace(",", "") for num in numbers]
    
    # 转换为合适的数值类型
    final_numbers = []
    for num in cleaned_numbers:
        try:
            # 尝试转换为浮点数
            n = float(num)
            # 如果是整数,转换为int
            if n.is_integer():
                final_numbers.append(int(n))
            else:
                final_numbers.append(n)
        except ValueError:
            continue
    
    return final_numbers

# 使用示例
numbers = extract_numbers(pdf_text)
print("提取到的数字:", numbers)

这个函数可以识别各种格式的数字:

  • 整数:42, -15, 1,000
  • 小数:3.14, -0.5
  • 科学计数法:1.23e-4
  • 带千位分隔符:12,345.67

表格数据处理技巧

PDF中的表格数据需要特殊处理:

提取表格数据

def extract_tables_from_pdf(pdf_path):
    all_tables = []
    with pdfplumber.open(pdf_path) as pdf:
        for page in pdf.pages:
            tables = page.extract_tables()
            for table in tables:
                # 处理表格数据
                processed_table = []
                for row in table:
                    processed_row = [cell.replace("\n", " ") if cell else "" for cell in row]
                    processed_table.append(processed_row)
                all_tables.append(processed_table)
    return all_tables

# 使用示例
tables = extract_tables_from_pdf("财务报告.pdf")
for i, table in enumerate(tables):
    print(f"表格 {i+1}:")
    for row in table:
        print(row)

提取表格后,可以进一步处理其中的数字:

# 从表格中提取数字
for table in tables:
    for row in table:
        for cell in row:
            # 检查单元格是否包含数字
            if any(char.isdigit() for char in cell):
                # 提取并处理数字
                cell_numbers = extract_numbers(cell)
                if cell_numbers:
                    print(f"在单元格 '{cell}' 中找到数字: {cell_numbers}")

完整代码示例

完整的PDF数字提取脚本:

import pdfplumber
import re

def extract_pdf_numbers(pdf_path):
    """从PDF文件中提取所有数字"""
    all_numbers = []
    
    with pdfplumber.open(pdf_path) as pdf:
        for page in pdf.pages:
            # 提取文本
            text = page.extract_text()
            if text:
                all_numbers.extend(extract_numbers(text))
            
            # 提取表格中的数字
            tables = page.extract_tables()
            for table in tables:
                for row in table:
                    for cell in row:
                        if cell:
                            all_numbers.extend(extract_numbers(cell))
    
    return all_numbers

def extract_numbers(text):
    """从文本中提取数字"""
    pattern = r"[-+]?\d{1,3}(?:,\d{3})*(?:\.\d+)?(?:[eE][-+]?\d+)?"
    numbers = re.findall(pattern, text)
    cleaned_numbers = [num.replace(",", "") for num in numbers]
    
    final_numbers = []
    for num in cleaned_numbers:
        try:
            n = float(num)
            if n.is_integer():
                final_numbers.append(int(n))
            else:
                final_numbers.append(n)
        except ValueError:
            continue
    
    return final_numbers

if __name__ == "__main__":
    pdf_file = "财务报告.pdf"
    numbers = extract_pdf_numbers(pdf_file)
    
    print(f"从 {pdf_file} 中提取到 {len(numbers)} 个数字:")
    print(numbers)
    
    # 保存到CSV文件
    with open("extracted_numbers.csv", "w") as f:
        f.write("Extracted Numbers\n")
        for num in numbers:
            f.write(f"{num}\n")
    
    print("结果已保存到 extracted_numbers.csv")

常见问题与解决方案

Q: 提取的数字不准确或遗漏

解决方案:

  • 调整正则表达式模式以匹配特定格式
  • 检查PDF是否是扫描件(图片)而非可搜索文本
  • 尝试不同的PDF库(如pdfminer.six)

Q: 表格提取混乱

解决方案:

  • 使用pdfplumber的table_settings参数调整表格检测
  • 尝试extract_table()替代extract_tables()
  • 处理前使用page.debug_tablefinder()可视化表格检测

Q: 性能问题(大文件处理慢)

解决方案:

  • 使用多线程/多进程处理页面
  • 仅处理特定页面范围
  • 对于纯数据PDF,考虑转换为其他格式(如Excel)

总结

本教程详细介绍了使用Python从PDF文件中提取数字的完整流程:

  1. 使用pdfplumber提取PDF文本和表格内容
  2. 应用正则表达式识别各种格式的数字
  3. 清理和转换数字格式
  4. 处理表格中的特殊数据
  5. 保存提取结果

通过这个方法,你可以自动化处理财务报告、研究论文、商业分析等各种PDF文档中的数据提取任务,大大提高工作效率。

发表评论