RAG 文档解析实战:PyMuPDF 与 Unstructured 的使用
2026/6/16 21:16:06 网站建设 项目流程

📖 目录

  • 一、RAG 为什么需要文档解析?
  • 二、PyMuPDF 和 Unstructured 的定位区别
  • 三、PyMuPDF 简介
  • 四、PyMuPDF 基础用法
    • 1. 提取 PDF 文本
    • 2. 提取文本块
    • 3. 提取字典结构
    • 4. 把 PDF 页面渲染成图片
    • 5. 提取 PDF 中的图片
    • 6. 表格提取
  • 五、PyMuPDF 在 RAG 中的推荐用法
    • 1. 普通 PDF 文本知识库
    • 2. 扫描件 PDF
    • 3. 图片较多的 PDF
    • 4. 表格较多的 PDF
  • 六、Unstructured 简介
  • 七、Unstructured 基础用法
    • 1. 自动解析文档
    • 2. 解析 PDF
    • 3. 解析图片
  • 八、Unstructured 的 Title 是怎么来的?
  • 九、Unstructured Chunking 用法
    • 1. 按标题切 Chunk
    • 2. 为什么 Unstructured 的 chunking 和普通文本切分不同?
  • 十、QA 格式文档怎么处理?
    • QA 数据向量化问题还是答案?
  • 十一、QA 里有图片怎么办?
  • 十二、QA 里有表格怎么办?
  • 十三、PyMuPDF 与 Unstructured 的组合方案
    • 方案 1:Unstructured 主导
    • 方案 2:PyMuPDF 主导
    • 方案 3:混合方案
  • 十四、RAG 入库数据结构推荐
  • 十五、总结

一、RAG 为什么需要文档解析?

RAG 的完整流程通常是:

原始文档 -> 文档解析 -> 文本清洗 -> Chunk 切分 -> 向量化 -> 写入向量库 -> 检索 -> LLM 生成回答

在这个流程里,文档解析非常关键。如果 PDF、Word、图片、表格在解析阶段就被处理坏了,后面的向量检索和问答效果都会下降。

常见问题包括:

  • PDF 提取出来文字顺序错乱;
  • 扫描件 PDF 没有可复制文本;
  • 表格被拆成一堆无意义的行;
  • 图片里的文字没有 OCR;
  • 标题和正文没有结构;
  • Chunk 切得太碎或太长;
  • 检索结果没有页码、来源、章节信息。

PyMuPDF 和 Unstructured 都是 RAG 文档处理里常见的工具,但它们定位不同。

二、PyMuPDF 和 Unstructured 的定位区别

工具核心定位更适合做什么
PyMuPDFPDF 底层解析与页面处理库提取文本、图片、坐标、页面渲染、表格检测
Unstructured多格式文档解析与结构化预处理框架把 PDF、Word、HTML、图片等解析成结构化 Element,并支持 chunk

可以简单理解:

PyMuPDF 更像 PDF 手术刀。 Unstructured 更像 RAG 文档预处理流水线。

如果你只处理 PDF,并且想要更细粒度控制页面、坐标、图片、表格,PyMuPDF 很合适。

如果你要处理多种格式,例如 PDF、DOCX、HTML、PPTX、图片,并希望直接拿到TitleNarrativeTextTable等结构化元素,Unstructured 更方便。

三、PyMuPDF 简介

PyMuPDF 是一个高性能 Python 文档处理库,底层基于 MuPDF。它可以处理 PDF、XPS、EPUB 等格式。RAG 中最常用的是 PDF 解析。

安装:

pipinstallpymupdf

导入方式:

importfitz

注意:PyMuPDF 的导入名是fitz

四、PyMuPDF 基础用法

1. 提取 PDF 文本

importfitz doc=fitz.open("demo.pdf")forpage_index,pageinenumerate(doc):text=page.get_text()print(f"第{page_index+1}页")print(text)

page.get_text()默认提取纯文本,适合普通可复制文本 PDF。

如果是扫描件 PDF,可能提取不到文字,需要先 OCR。

2. 提取文本块

importfitz doc=fitz.open("demo.pdf")page=doc[0]blocks=page.get_text("blocks")forblockinblocks:print(block)

blocks会返回带坐标的文本块,常用于:

  • 分析页面布局;
  • 判断标题和正文;
  • 按区域抽取内容;
  • 保留页码和坐标 metadata。

3. 提取字典结构

importfitz doc=fitz.open("demo.pdf")page=doc[0]data=page.get_text("dict")forblockindata["blocks"]:ifblock["type"]==0:forlineinblock["lines"]:line_text="".join(span["text"]forspaninline["spans"])print(line_text)

dict结构里有更详细的字体、字号、坐标信息。你可以根据字号、加粗、位置来粗略判断标题。

4. 把 PDF 页面渲染成图片

importfitz doc=fitz.open("demo.pdf")fori,pageinenumerate(doc):pix=page.get_pixmap()pix.save(f"page_{i+1}.png")

如果想提高图片分辨率:

importfitz doc=fitz.open("demo.pdf")page=doc[0]matrix=fitz.Matrix(2,2)pix=page.get_pixmap(matrix=matrix)pix.save("page_1_2x.png")

这在 OCR、视觉模型理解、图片问答中很常用。

5. 提取 PDF 中的图片

importfitz doc=fitz.open("demo.pdf")forpage_index,pageinenumerate(doc):images=page.get_images(full=True)forimage_index,imginenumerate(images):xref=img[0]base_image=doc.extract_image(xref)image_bytes=base_image["image"]image_ext=base_image["ext"]image_path=f"page_{page_index+1}_image_{image_index+1}.{image_ext}"withopen(image_path,"wb")asf:f.write(image_bytes)

RAG 中图片一般不要直接向量化原图,而是:

图片 -> OCR / caption -> 文本描述参与向量化 原图路径 -> metadata 保存,用于回答时引用或展示

6. 表格提取

PyMuPDF 新版本支持页面表格检测。典型用法类似:

importfitz doc=fitz.open("demo.pdf")page=doc[0]tables=page.find_tables()fortableintables:df=table.to_pandas()print(df)

注意:

  • 表格检测依赖 PDF 版面质量;
  • 复杂跨页表格、无线框表格可能识别不稳定;
  • 如果表格很重要,建议结合pdfplumber、Camelot、Tabula 或 Unstructured 的表格能力做对比。

五、PyMuPDF 在 RAG 中的推荐用法

1. 普通 PDF 文本知识库

PyMuPDF 提取文本 -> 按页保存 page metadata -> 清洗页眉页脚 -> 按标题或段落切 chunk -> 向量化

示例数据结构:

{"content":"这里是第 3 页中的一段正文...","metadata":{"source":"manual.pdf","page":3,"type":"text"}}

2. 扫描件 PDF

PyMuPDF 渲染页面图片 -> OCR -> 得到文本 -> 切 chunk -> 向量化

3. 图片较多的 PDF

PyMuPDF 提取图片 -> OCR / caption -> 图片说明进入 embedding_text -> 原图路径进入 metadata

示例:

{"embedding_text":"登录页面截图,包含用户名、密码、验证码、登录按钮。","metadata":{"source":"manual.pdf","page":5,"image_path":"/assets/page_5_image_1.png","type":"image"}}

4. 表格较多的 PDF

表格不要只当普通文本处理,建议保存三份:

Markdown 表格:给 LLM 阅读 CSV / JSON:用于精确查询和计算 表格摘要:参与向量检索

六、Unstructured 简介

Unstructured 是一个面向 LLM / RAG 的文档预处理库。它可以把 PDF、HTML、Word、PPT、图片等文件解析成结构化元素。

安装:

pipinstallunstructured

如果处理 PDF、图片和 OCR,通常需要额外依赖。实际项目中可以按官方文档安装对应 extras,例如 PDF、OCR、local inference 相关依赖。

Unstructured 的核心思想是:

先 partition 成 Elements 再基于 Elements 做 chunking

常见 Element 类型:

Element 类型含义
Title标题
NarrativeText正文段落
ListItem列表项
Table表格
Image图片
Header页眉
Footer页脚

七、Unstructured 基础用法

1. 自动解析文档

fromunstructured.partition.autoimportpartition elements=partition(filename="demo.pdf")foreinelements:print(type(e).__name__,e.text[:80]ifhasattr(e,"text")else"")

这会自动根据文件类型选择解析方式。

2. 解析 PDF

fromunstructured.partition.pdfimportpartition_pdf elements=partition_pdf(filename="demo.pdf",strategy="hi_res",infer_table_structure=True,)foreinelements:print(type(e).__name__,e.text[:100])

常见参数:

参数说明
strategy="fast"速度快,适合可复制文本 PDF
strategy="hi_res"使用版面分析,适合复杂 PDF、扫描件、表格、标题识别
infer_table_structure=True尝试识别表格结构

3. 解析图片

fromunstructured.partition.imageimportpartition_image elements=partition_image(filename="page.png",strategy="hi_res",)foreinelements:print(type(e).__name__,e.text)

图片解析一般依赖 OCR 和布局识别。

八、Unstructured 的 Title 是怎么来的?

Unstructured 不是在 chunk 阶段凭空判断标题,而是在 partition 阶段把文档解析成 Elements。

如果某段内容被识别为:

Title

那么chunk_by_title才能把它当作章节边界。

流程如下:

原始文档 -> partition -> Title / NarrativeText / ListItem / Table 等 Elements -> chunk_by_title -> 按 Title 边界切 chunk

九、Unstructured Chunking 用法

1. 按标题切 Chunk

fromunstructured.partition.pdfimportpartition_pdffromunstructured.chunking.titleimportchunk_by_title elements=partition_pdf(filename="demo.pdf",strategy="hi_res",infer_table_structure=True,)chunks=chunk_by_title(elements,max_characters=1200,new_after_n_chars=1000,combine_text_under_n_chars=200,)forchunkinchunks:print(type(chunk).__name__)print(chunk.text[:300])

参数说明:

参数作用
max_characters单个 chunk 最大字符数
new_after_n_chars超过这个长度后倾向开启新 chunk
combine_text_under_n_chars太短的 section 尽量合并

2. 为什么 Unstructured 的 chunking 和普通文本切分不同?

普通 splitter 往往是:

纯文本 -> 按字符数 / token 数硬切

Unstructured 更像:

文档 -> Element 结构 -> 根据标题、段落、表格等结构切

优势是能保留文档结构,尤其适合说明书、政策文档、FAQ、操作手册。

十、QA 格式文档怎么处理?

推荐结构:

{"question":"访问中心站需要哪些条件?","answer":"中心站部署...","embedding_text":"问题:访问中心号。","metadata":{"source":"中心站说明文档.pdf","page":1,"section":"1"}}

QA 数据向量化问题还是答案?

推荐:

用于检索:问题 + 同义问题 + 答案摘要 + 关键词 用于回答:完整答案

不要只向量化答案,也不要只保存问题。

更稳的embedding_text

问题:如何登录中心站? 同义问题:中心站怎么登录?登录中心站需要什么? 答案摘要:通过浏览器访问中心站网址,输入用户名、密码和手机验证码登录。 关键词:登录、网址、用户名、密码、手机验证码、验证码。

十一、QA 里有图片怎么办?

图片不要直接塞进向量库。推荐流程:

图片 -> OCR -> caption -> OCR 文本和 caption 参与向量化 -> 原图路径保存到 metadata

示例:

{"type":"image","path":"/assets/page_2_image_1.png","caption":"登录页面截图,包含用户名输入框、密码输入框、发送手机验证码按钮和登录按钮。","ocr_text":"用户名 密码 发送手机验证码 验证码 登录"}

然后把这些信息加入embedding_text

图片说明:登录页面截图,包含用户名、密码、验证码和登录按钮。 图片 OCR:用户名、密码、发送手机验证码、验证码、登录。

这样用户问:

登录页面验证码按钮在哪里?

也有机会检索到正确 QA。

十二、QA 里有表格怎么办?

表格建议不要只做 caption,也不要只把表格原文混进一大段文本。

推荐保存三种形态:

Markdown 表格:给 LLM 看。 CSV / JSON:用于精确查询和计算。 表格摘要:参与向量检索。

例如:

| 项目 | 最低配置 | 推荐配置 | | --- | --- | --- | | CPU | i5 | i7 / Ryzen 7 | | 内存 | 8GB | 16GB | | 显卡 | 集成显卡 | GTX 1660 |

表格摘要:

表格说明访问中心站的硬件配置要求。最低配置为 i5、8GB 内存、集成显卡;推荐配置为 i7 或 Ryzen 7、16GB 内存、GTX 1660。

向量化文本可以写成:

问题:访问中心? 答案摘要:需要电脑,最低配置 i5、8GB 内存、集成显卡;推荐 i7/Ryzen 7、16GB 内存、GTX 1660。 表格关键词:CPU、内存、显卡、最低配置、推荐配置。

如果用户问计算类问题:

推荐内存比最低内存多多少?

更好的做法是:

检索到表格 -> 读取 CSV / JSON -> 用程序计算 -> LLM 解释结果

不要完全依赖模型从自然语言表格里猜。

十三、PyMuPDF 与 Unstructured 的组合方案

实际项目中,两者可以组合使用。

方案 1:Unstructured 主导

适合多格式文档:

Unstructured partition -> Elements -> chunk_by_title -> 表格摘要 / 图片 OCR -> 向量化

优点:

  • 多格式统一;
  • Title、Table、ListItem 等结构清晰;
  • chunking 更贴近文档结构。

缺点:

  • 依赖较多;
  • 复杂 PDF 的效果和环境配置有关;
  • 需要检查 Title、Table 是否识别正确。

方案 2:PyMuPDF 主导

适合 PDF 控制更细的场景:

PyMuPDF 按页解析 -> 提取文本 / 图片 / 坐标 / 表格 -> 自定义规则切 chunk -> 向量化

优点:

  • 速度快;
  • PDF 级控制强;
  • 方便保留页码、坐标、图片路径。

缺点:

  • 标题、段落、表格结构需要自己处理;
  • 多格式支持不如 Unstructured 统一。

方案 3:混合方案

推荐给生产项目:

先用 Unstructured 获取结构化 Elements 如果表格 / 图片 / 页码不满足要求 再用 PyMuPDF 做补充提取

例如:

Unstructured 负责标题、正文、表格初步解析。 PyMuPDF 负责页面截图、图片抽取、坐标和页码补充。

十四、RAG 入库数据结构推荐

无论使用 PyMuPDF 还是 Unstructured,最终建议统一成类似结构:

{"id":"manual_pdf_page_1_qa_1","embedding_text":"问题:访问中心答案摘要:需要硬件、软件、网络、账号条件。关键词:Windows10、Chrome、固定出口 IP、白名单、账号。","content":"完整答案正文...","metadata":{"source":"manual.pdf","page":1,"section":"1","type":"qa","question":"访问中心站","images":[{"path":"/assets/page_1_image_1.png","caption":"硬件条件示意图"}],"tables":[{"path":"/tables/page_1_table_1.csv","summary":"硬件配置要求表"}]}}

向量库里主要存:

embedding_text metadata

回答时再根据 metadata 取:

完整答案 Markdown 表格 图片说明 原始文件路径 页码来源

十五、总结

场景推荐工具推荐处理方式
普通可复制 PDFPyMuPDF / Unstructured提取文本,按页和标题切 chunk
扫描件 PDFPyMuPDF + OCR / Unstructured hi_res页面渲染或 OCR 解析
多格式文档Unstructuredpartition 成 Elements,再 chunk
标题结构明显的文档Unstructuredchunk_by_title
QA / FAQ 文档自定义规则 + Unstructured按 QA 单元入库
图片多的文档PyMuPDF + OCR/caption图片说明参与向量化,原图保存路径
表格多的文档Unstructured / PyMuPDF / pdfplumberMarkdown + CSV/JSON + 表格摘要
需要精确页码和坐标PyMuPDF保存 page、bbox metadata

PyMuPDF 和 Unstructured 在 RAG 中不是互相替代,而是互补关系:

PyMuPDF 适合精细控制 PDF:文本、图片、坐标、页面渲染、表格检测。 Unstructured 适合统一处理多格式文档:Title、NarrativeText、ListItem、Table 等结构化 Elements。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询