🎯 课程主题
使用 LangChain 的 PyPDFLoader 和 MinerU 工具加载并解析 PDF 文件。
📝 核心知识点
PDF 文件的特点与挑战
- PDF 在实际数据中占比很高,类型多样:
- 扫描版:需 OCR 识别
- 电子文本版:可直接提取文字
- 混合版:同时包含文本和图片
- PDF 内部可能包含:数学公式、表格、图片(含需要 OCR 提取的文字)
方案一:PyPDFLoader
- 继承自
BaseLoader,API 风格与其他 Loader 一致 - 核心参数:
file_path:本地文件路径(也支持线上 URL)extraction_mode:提取模式"plain"(默认):纯文本提取"layout":布局感知提取,保留空格和换行符,适用于特殊格式文档
from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader(
file_path="./sample.pdf",
extraction_mode="plain"
)
docs = loader.load() # 返回 List[Document]
print(len(docs)) # 例如:36 个 Document 分块
方案二:MinerU(推荐)
- 提供 PDF、Word、PPT、图片等文件的解析能力
- 支持 OCR 识别图片中的文字
- 使用前需在官网注册并获取 API Token,写入
.env文件:
MINERU_API_TOKEN=你的token值
- 使用流程:
- 上传文件到 MinerU 服务器
- 等待处理(约 20 秒)
- 下载结果(返回压缩包,解压后为多个 JSON 文件)
# 核心函数示例
def upload_file(file_path):
"""上传文件到 MinerU 服务器"""
...
def download_result():
"""下载处理结果(压缩包),解压后得到 JSON 文件"""
...
- 处理结果:JSON 格式,同时完成了自动切分(split),每个 JSON 文件对应文档的一个分块。
开发建议
实际项目开发中,推荐优先使用 MinerU,尤其当 PDF 包含图片、表格等复杂内容时。
🏗️ 架构与工作流
💻 代码实战
PyPDFLoader 加载本地 PDF
from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader(
file_path="./sample.pdf",
extraction_mode="plain"
)
documents = loader.load()
print(f"共 {len(documents)} 个 Document")
# 输出示例:共 36 个 Document
PyPDFLoader 加载线上 PDF
loader = PyPDFLoader(
file_path="https://example.com/paper.pdf",
extraction_mode="plain"
)
documents = loader.load()
# 同样可以正常加载
MinerU 加载 PDF(配置与环境变量)
- 在
.env中添加:
MINERU_API_TOKEN=your_actual_token_here
- 核心加载代码(上传 + 下载):
import os
import requests
from dotenv import load_dotenv
load_dotenv()
API_TOKEN = os.getenv("MINERU_API_TOKEN")
def upload_and_parse_pdf(file_path):
# 1. 上传文件
upload_url = "https://api.mineru.com/v1/upload"
with open(file_path, "rb") as f:
response = requests.post(upload_url, files={"file": f}, headers={"Authorization": f"Bearer {API_TOKEN}"})
# 2. 轮询获取结果
task_id = response.json()["task_id"]
result_url = f"https://api.mineru.com/v1/result/{task_id}"
result = requests.get(result_url, headers={"Authorization": f"Bearer {API_TOKEN}"})
# 3. 下载并解压
download_url = result.json()["download_url"]
zip_response = requests.get(download_url)
with open("result.zip", "wb") as f:
f.write(zip_response.content)
# 解压后得到多个 JSON 文件
import zipfile
with zipfile.ZipFile("result.zip", "r") as zf:
zf.extractall("./output")
⚠️ 常见问题与避坑指南
- 网络代理问题:使用 MinerU 时如果开启了代理/梯子,可能导致连接中断。关闭代理后重试即可。
- API Token 配置:
.env中的 key 名称必须与代码中os.getenv()的参数一致,否则读取不到。 - PyPDFLoader 分块数量:
load()返回的是多个 Document,并非一个 Document 存整个 PDF。默认按页或文本段落切分为多个 Document。 - MinerU 处理时间:需要等待服务器处理(约 20 秒),不是即时返回。
- layout 模式:使用
extraction_mode="layout"时,结果中会包含大量空格和换行符,更适合保留原文档的排版结构。
💡 个人总结与延伸
- 选型建议:
- 纯文本 PDF → 用
PyPDFLoader即可,简单高效 - 含图片/表格/公式的复杂 PDF → 用
MinerU,OCR 能力更强
- 纯文本 PDF → 用
- MinerU 返回的 JSON 格式天然完成了 document 的分块切分,可直接接入下游的向量化与检索流程
- PyPDFLoader 遵循 BaseLoader 统一接口,
load()返回List[Document],与后续的 TextSplitter 无缝衔接 - 对于批量处理场景,MinerU 需要逐文件上传+下载,注意 API 调用频率限制