PyPDFLoader(底层使用 pypdf)主要是通过提取 PDF 的矢量文本流来工作的。对于扫描版 PDF、纯图片 PDF 或包含复杂排版/渲染表格的 PDF,PyPDFLoader 往往提取不到任何有效文本或只能提取出大量空白,从而触发空文档报错。

要彻底解决包含表格、扫描件或复杂图文 PDF的解析问题,通常有以下 3 种主流解决方案


方案 1:使用 unstructured 模块解析(推荐,支持表格结构提取)

LangChain 官方推荐使用 UnstructuredPDFLoader,它能够识别复杂的文档结构(包括表格、列表、标题等),并将其转化为清晰的文本描述。

1. 安装依赖
pip install "unstructured[pdf]"

2. 替换加载器代码

from langchain_community.document_loaders import PyPDFLoader 替换为 UnstructuredPDFLoader

from langchain_community.document_loaders import UnstructuredPDFLoader

# 替换原来的 PyPDFLoader
# mode="single" 表示将整份文档合并解析,也可设为 "elements" 按表格/段落拆分
loader = UnstructuredPDFLoader(tmp_file_path, mode="single")
pages = loader.load()


方案 2:使用 pdfplumber 解析(针对带表格的电子版 PDF)

如果 PDF 是电子生成的(非扫描件),但因为里面有表格导致 PyPDFLoader 抓取失败或乱码,pdfplumber 是提取表格和文本最精准的工具。

1. 安装依赖
pip install pdfplumber

2. 使用 pdfplumber 编写增强版 PDF 加载函数

可以直接替换原代码中的 PyPDFLoader 部分:

import pdfplumber
from langchain_core.documents import Document

def load_pdf_with_tables(pdf_path):
    docs = []
    with pdfplumber.open(pdf_path) as pdf:
        for page_num, page in enumerate(pdf.pages):
            # 1. 提取普通文本
            text = page.extract_text() or ""
            
            # 2. 提取表格并转化为 Markdown 格式的文本
            tables = page.extract_tables()
            table_texts = []
            for table in tables:
                # 过滤全空行
                clean_table = [[cell if cell else "" for cell in row] for row in table if any(row)]
                if clean_table:
                    # 将二维数组表格转换为简单的 Markdown 文本形式
                    for row in clean_table:
                        table_texts.append(" | ".join(row))
            
            full_content = text + "\n\n" + "\n".join(table_texts)
            if full_content.strip():
                docs.append(Document(page_content=full_content, metadata={"page": page_num + 1}))
    return docs

在主流程中调用:
# 3. 加载与解析 PDF 文本(支持表格提取)
pages = load_pdf_with_tables(tmp_file_path)
os.remove(tmp_file_path)  # 清理临时文件


方案 3:开启 OCR 支持(针对纯图片/扫描版 PDF)

如果上传的 PDF 是图片扫描件(即没有任何文本层),则必须依赖 OCR(光学字符识别)

1. 安装依赖

需要安装 pdf2imagepytesseract(同时需在操作系统安装 tesseract 引擎):

pip install pdf2image pytesseract

2. 结合 pdf2image + pytesseract 的备用提取逻辑

可以在文本提取为空时自动降级到 OCR 模式:

import pytesseract
from pdf2image import convert_from_path
from langchain_core.documents import Document

def load_pdf_with_ocr_fallback(pdf_path):
    # 先尝试用 pdfplumber 提取
    docs = load_pdf_with_tables(pdf_path)
    
    # 如果提取出的内容为空,说明可能是扫描件/纯图片 PDF,启用 OCR 提取
    if not docs:
        images = convert_from_path(pdf_path)
        docs = []
        for i, image in enumerate(images):
            # 使用 OCR 识别图片内容(chi_sim 识别中文,eng 识别英文)
            text = pytesseract.image_to_string(image, lang='chi_sim+eng')
            if text.strip():
                docs.append(Document(page_content=text, metadata={"page": i + 1}))
                
    return docs


总结

  • 如果主要是带有数据表格的电子版 PDF:优先选择 方案 2 (pdfplumber),无需额外安装复杂的系统 C 库,能精准提取表格内容。
  • 如果是复杂的排版文档:优先选择 方案 1 (unstructured)
  • 如果包含图片扫描件 PDF:选择 方案 3 (OCR 降级处理)
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐