如何在 Python 中从 PDF 提取文本 (2026)

发布: (2026年3月16日 GMT+8 17:21)
10 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的具体文本内容,我将为您翻译成简体中文并保留原有的格式、Markdown 语法以及技术术语。

从 PDF 中提取文本

从 PDF 中提取文本仍然是数据工程、AI 流水线和自动化工作流中最常见的任务之一。无论你是在构建搜索系统、检索增强生成(RAG)流水线,还是仅仅处理报告,第一步都是将 PDF 转换为干净、可用的文本。

乍一看这似乎很简单,但 PDF 从未像现代格式那样被设计为机器可读。PDF 本质上是一组描述页面外观的指令,而不是段落、标题或表格的结构化表示。这意味着文本可能以碎片形式存储,位置任意,甚至以图像形式嵌入。

正因为如此,原生提取往往会产生断句、阅读顺序错误或内容缺失。现代工具尝试重建结构,而不仅仅是读取原始文本流,这也是提取方法选择重要的原因。

PDF 文本提取的工作原理

大多数 PDF 提取流水线遵循相同的高层流程:

  1. 解析 文档的每一页。
  2. 检测 文本块并将其组装成可读顺序。
  3. 如果文档包含扫描页,应用 OCR
  4. 规范化 输出,以便进行索引、搜索或传递给下游系统。

虽然这个工作流听起来直截了当,但每一步都蕴含了大量的复杂性。阅读顺序检测在多列布局或技术文档中变得困难。表格则增加了另一层难度,因为视觉结构并不总能干净地映射到文本。

这也是许多团队最终会超越简单的 PDF 库,转向更完整的文档处理框架的原因。

在 Python 中从 PDF 提取文本

在 Python 中,提取文本的基本工作流无论使用哪个库都大致相同:

  1. 加载文档。
  2. 解析文档。
  3. 将其转换为可以打印、存储或进一步处理的文本。

不同的库提供不同的 API,但总体模式保持一致。真正的差异体现在它们处理布局、性能以及 OCR 能力的好坏上。

Source:

使用 Kreuzberg 进行 PDF 提取

现代文档流水线往往需要的不仅是读取文本流。它们需要一致的元数据、可靠的多格式处理能力,以及在处理大量文件时的良好性能。

Kreuzberg 正是为此类工作负载而设计。它使用基于 Rust 的提取引擎并提供 Python 绑定(截至 2026 年3月已支持另外 11 种编程语言),实现高效的文档处理,同时能够平滑地集成到 Python 流程中。

安装

pip install kreuzberg

同步提取

from kreuzberg import extract_file_sync

result = extract_file_sync("document.pdf")
print(result.content)                         # 提取的文本
print(f"Pages: {result.metadata['page_count']}")  # 页数

异步提取

import asyncio
from kreuzberg import extract_file

async def main():
    result = await extract_file("document.pdf")
    print(result.content)                         # 提取的文本
    print(f"Tables found: {len(result.tables)}")  # 表格数量

asyncio.run(main())

两个函数均返回一个 ExtractionResult 对象,包含:

  • result.content – 提取的文本。
  • result.tables – 检测到的表格列表。
  • result.metadata – 文档属性(例如页数、格式)。

批量提取(同步)

from pathlib import Path
from kreuzberg import batch_extract_files_sync

paths = list(Path("documents").glob("*.pdf"))
results = batch_extract_files_sync(paths)

for path, result in zip(paths, results):
    print(f"{path.name}: {len(result.content)} characters")

批量助手会自动处理并发,使一次性处理大量 PDF 变得轻松。

扫描 PDF 的 OCR

通过传入带有 OcrConfigExtractionConfig 来启用 OCR。

Tesseract(英文)

from kreuzberg import extract_file_sync, ExtractionConfig, OcrConfig

config = ExtractionConfig(
    ocr=OcrConfig(backend="tesseract", language="eng")
)

result = extract_file_sync("scanned.pdf", config=config)
print(result.content)

PaddleOCR(中文)

from kreuzberg import extract_file_sync, ExtractionConfig, OcrConfig

config = ExtractionConfig(
    ocr=OcrConfig(backend="paddleocr", language="zh")
)

result = extract_file_sync("scanned.pdf", config=config)
print(f"Extracted content (preview): {result.content[:100]}")
print(f"Total characters: {len(result.content)}")

常见运行时问题

如果遇到 libonnxruntime.so 加载错误,首先升级/安装 onnxruntime

python -m pip install --upgrade onnxruntime

如果在 Linux 上错误仍然存在,需将 onnxruntime/capi 目录加入 LD_LIBRARY_PATH(将 <venv_path> 替换为实际的虚拟环境路径):

export LD_LIBRARY_PATH="/<venv_path>/lib/pythonX.Y/site-packages/onnxruntime/capi:$LD_LIBRARY_PATH"

Kreuzberg 支持 TesseractEasyOCRPaddleOCR 作为后端,这在多语言文档中非常有用,因为不同语言的后端质量可能有所差异。

Extracting Tables and Structured Content

表格是另一个简单提取方法难以应对的领域。即使文本被正确捕获,行与列之间的关系也可能丢失。

更高级的提取流水线尝试检测表格区域并保留结构,以确保数据可用。这在财务报告、研究论文和运营文档中尤为重要,因为这些文档中的表格往往包含最关键的信息。

性能与扩展性考虑

只要开始处理超过几份文件,性能就变得日益重要。批量导入、RAG 管道以及搜索索引工作流可能涉及成千上万甚至数百万个文档,而解析阶段的低效会迅速导致成本飙升。

影响性能的因素包括:

  • Implementation – 解析引擎的实现方式(编译型 vs. 解释型)。
  • Memory management – 对 RAM 的高效使用以及对大文件的流式处理。
  • Concurrency support – 能否并行运行多个解析任务。

大量依赖解释执行或外部子进程的工具在大规模使用时常常会出现瓶颈,而原生解析引擎在持续负载下通常表现更佳。这也是许多现代文档处理工具采用编译核心并在其上提供语言绑定的原因之一。

PDF提取在现代流水线中的位置

在大多数实际系统中,文本提取仅是第一步。文本可用后,通常会:

  1. 将文本拆分为块。
  2. 转换为嵌入向量。
  3. 存储在向量数据库中以供检索。

这种架构已成为文档搜索和检索增强生成(RAG)系统的标准做法,因为它能够高效地查询大型文档集合。可靠的提取是实现其他所有功能的基础。

常见陷阱

新手开发者在进行 PDF 提取时常常假设所有 PDF 的行为都相同。实际上,文档在结构和质量上差异巨大,一个在某个数据集上表现良好的流水线在另一个数据集上可能会失效。

避免陷阱的技巧

  • 使用多样化的文档进行测试 – 包括扫描文件、多列布局以及大型报告。问题通常会在接近真实使用场景时迅速显现。
  • 不要忽视元数据 – 页码、标题和文档层次结构在后期往往变得至关重要,尤其是在构建需要引用来源的检索系统时。

最后思考

在 Python 中从 PDF 提取文本比几年前更容易了,但文档结构和布局的根本挑战仍然存在。选择能够很好处理这些复杂性的工具可以显著提升下游系统的质量——从搜索到 RAG 再到分析。一旦摄取层可靠,整个管道的设计和维护就会变得更加轻松。

0 浏览
Back to Blog

相关文章

阅读更多 »