Python 高级 PDF 解析工具逐行讲解

🔒 You must be logged in as an Administrator or Editor to listen to this audio.

Python 高级 PDF 解析工具逐行讲解

我会逐行、逐段为你详细讲解这段 Python 代码,用最通俗的方式解释每一部分的作用、逻辑和用途,让你完全看懂这段高级 PDF 解析工具代码

整体功能一句话总结

这是一个类的方法,功能是:高级读取 PDF 文件,同时提取 3 种内容:

  1. 纯文本
  2. 表格(转成 Markdown 格式)
  3. 图片(保存成本地文件,并记录路径) 最后返回:拼接好的完整文本内容 + 图片附件列表

逐行逐段完整讲解

1. 方法定义(函数签名)


def _read_pdf_advanced(self, filepath: str, doc_id: str) -> (str, List[Dict]):
  • def:定义函数/方法
  • _read_pdf_advanced:方法名,下划线开头表示这是类内部使用的私有方法
  • self:类方法必须有的参数,代表实例本身
  • filepath: str:参数注解,PDF 文件路径,字符串类型
  • doc_id: str:文档唯一 ID,用于给图片命名,避免重名
  • -> (str, List[Dict]):返回值注解
    • 第一个返回值:字符串(完整文本)
    • 第二个返回值:字典列表(所有图片附件信息)

2. 文档字符串(说明)


"""
高级 PDF 读取:按页提取文本、表格(HTML)和图片(保存为文件)
"""
  • 说明这个方法的功能:按页提取文本、表格、图片
  • 注释里写的 HTML 是笔误,实际代码里转成了 Markdown 表格

3. 初始化两个空列表


content_parts = []  # 存放所有文本、表格、图片标记
attachments = []    # 存放所有图片的信息(路径、页码等)
  • content_parts:最后会把所有内容拼接成一个大字符串
  • attachments:专门存图片信息,方便外部使用

4. 创建附件文件夹(保存图片)


# 创建附件目录
if not os.path.exists(self.attachments_dir):
    os.makedirs(self.attachments_dir)
  • 检查是否有 attachments 目录
  • 没有就自动创建,所有提取的图片都会存在这里

5. 降级处理:依赖缺失时用最简单方式读取


if not self._pdfplumber_available or not self._fitz_available:
    # 降级处理
    from pypdf import PdfReader
    reader = PdfReader(filepath)
    for i, page in enumerate(reader.pages):
        content_parts.append(page.extract_text() or "")
    return "\n\n".join(content_parts), []

作用:兼容模式

  • 如果系统没安装高级库(pdfplumber / PyMuPDF)
  • 就自动降级,只用轻量库 pypdf 只提取纯文本
  • 不提取表格、不提取图片
  • 最后返回:文本 + 空附件列表

6. 导入高级 PDF 处理库


import pdfplumber
import fitz
  • pdfplumber专门提取文本和表格,准确率极高
  • fitz(PyMuPDF):专门提取图片,速度快、效果好

7. 打开 PDF 文件(两个库同时打开)


pdf_plumber_obj = pdfplumber.open(filepath)
pdf_fitz_obj = fitz.open(filepath)
  • 用两个库分别打开同一个 PDF
  • 各司其职:
    • pdfplumber 处理文字、表格
    • fitz 处理图片

8. try-finally 结构(保证文件一定会关闭)


try:
    # 所有解析逻辑
finally:
    pdf_plumber_obj.close()
    pdf_fitz_obj.close()
  • finally 最重要:无论代码是否报错,一定会关闭 PDF 文件
  • 避免文件占用、内存泄漏

9. 逐页循环处理 PDF


for page_idx in range(len(pdf_plumber_obj.pages)):
    page_num = page_idx + 1
    content_parts.append(f"--- Page {page_num} ---")
  • 一页一页处理
  • page_idx 从 0 开始,page_num 从 1 开始(符合人类阅读习惯)
  • 每页开头加标记:--- Page 1 ---

10. 提取当前页的文本(pdfplumber)


# 1. 提取文本和表格 (pdfplumber)
plumber_page = pdf_plumber_obj.pages[page_idx]
text = plumber_page.extract_text() or ""
if text:
    content_parts.append(text)
  • 获取当前页对象
  • 提取文本
  • 有文本就加入内容列表

11. 提取当前页的表格 → 转成 Markdown


tables = plumber_page.extract_tables()
if tables:
    for i, table in enumerate(tables):
        md_table = self._list_to_md_table(table)
        content_parts.append(f"\n[Table {i+1} on Page {page_num}]\n{md_table}")
  • extract_tables():把表格转成二维列表
  • 循环每一个表格
  • 调用私有方法 _list_to_md_table() 转成 Markdown 格式
  • 加入内容列表,并标注:第几页、第几个表

示例效果:


[Table 1 on Page 2]
| 姓名 | 年龄 |
|------|------|
| 张三 | 20   |

12. 提取当前页的图片(fitz)


# 2. 提取图片 (fitz)
fitz_page = pdf_fitz_obj[page_idx]
image_list = fitz_page.get_images()
  • 获取当前页

  • get_images():获取本页所有图片


13. 循环处理每一张图片


for img_index, img in enumerate(image_list, 1):
    xref = img[0]                  # 图片唯一标识
    pix = fitz.Pixmap(pdf_fitz_obj, xref)

处理 CMYK 色彩模式图片(避免报错)


if pix.n - pix.alpha > 3:
    pix = fitz.Pixmap(fitz.csRGB, pix)
  • 有些 PDF 图片是 CMYK 印刷模式,无法直接保存 PNG
  • 这行代码自动转成 RGB

14. 给图片命名并保存


img_name = f"img_{doc_id}_p{page_num}_i{img_index}.png"
img_path = os.path.join(self.attachments_dir, img_name)
pix.save(img_path)
pix = None  # 释放内存
  • 命名规则:img_文档ID_页码_图片序号.png 例:img_20260407_p3_i2.png
  • 保存到 attachments/ 目录
  • pix = None 释放图片内存

15. 记录图片信息到附件列表


attachments.append({
    "type": "image", "name": img_name, "path": img_path, "page": page_num
})
content_parts.append(f"\n![image](attachments/{img_name})\n")
  • 附件字典包含:类型、文件名、路径、页码
  • 文本内容里加入 Markdown 图片标记:![image](路径)

16. 每页结束加分隔符


content_parts.append("\n") # 页面间距

17. 关闭文件(finally)


finally:
    pdf_plumber_obj.close()
    pdf_fitz_obj.close()

18. 最终返回结果


return "\n\n".join(content_parts), attachments
  • 把所有内容用换行拼接成一个大字符串
  • 返回:(完整文本, 附件列表)

核心技术总结(超清晰)

作用
pdfplumber 提取文本、表格
PyMuPDF(fitz) 提取图片
pypdf 依赖缺失时降级只读文本

代码亮点

  1. 私有方法_ 开头,规范
  2. 类型注解:参数、返回值清晰
  3. 降级兼容:依赖缺失不崩溃
  4. try-finally:保证文件关闭
  5. 图片防重名:用 doc_id + 页码 + 序号命名
  6. 色彩兼容:CMYK → RGB
  7. 结构化输出:文本 + 附件分离

最终输出示例(文本部分)


--- Page 1 ---
这是第一页的文本内容

--- Page 2 ---
这是第二页文本

[Table 1 on Page 2]
| 姓名 | 年龄 |
|------|------|
| 小明 | 18   |

![image](attachments/img_123_p2_i1.png)

总结

  1. 这是一个健壮、完整、生产可用PDF 解析工具方法
  2. 同时提取文本 + 表格 + 图片
  3. 自带降级机制、异常保护、文件管理
  4. 输出格式友好,适合直接用于文档解析、知识库、RAG 系统

如果你需要,我还可以帮你:

  • 补全缺失的 _list_to_md_table 方法
  • 写一个完整可运行的 demo
  • 优化代码、增加日志、增加异常处理