夜雨聆风学习资料网

ARTICLE · 1134202

Day 2:合同 PDF 解析:怎么把扫描版合同变成可搜索文本

Day 2:合同 PDF 解析:怎么把扫描版合同变成可搜索文本

Day 2:合同 PDF 解析——怎么把扫描版合同变成可搜索文本

小码哥 · 2026-10-05 · 阅读约 7 分钟 · 30 天 AI 实战系列

一、今天做了什么

昨天把骨架搭好了,今天啃第一块硬骨头:PDF 解析。现实里的合同分两种——一种是「真 PDF」(带文字层,能直接复制),另一种是「扫描件」(本质是一张图片,复制出来全是乱码)。前者用 pdfplumber 就能提文字,后者必须上 OCR。

我写了 pdf_parser.py:先尝试提取文字层,提取不到或页数太少就自动降级到 pytesseract 做 OCR。这样一份扫描版投资协议也能变成可搜索文本,喂给后面的提取和审查模块。

📸 图1:后台运行截图(pdf_parser 解析一份扫描合同)

二、核心代码

📸 图2:代码截图(pdf_parser.py 主逻辑)

📋 代码块:pdf_parser.py

# pdf_parser.py —— 合同 PDF 解析(文本层 + OCR 降级) from pathlib import Path import pdfplumber from PIL import Image import pytesseract  MIN_TEXT_LEN = 30  # 单页少于这么多字符,判定为扫描件  def extract_text(pdf_path: str) -> str:     text_parts = []     with pdfplumber.open(pdf_path) as pdf:         for i, page in enumerate(pdf.pages):             txt = page.extract_text() or ""             if len(txt.strip()) < MIN_TEXT_LEN:                 txt = ocr_page(pdf_path, i)  # 降级 OCR             text_parts.append(txt)     return "\n".join(text_parts)  def ocr_page(pdf_path: str, page_no: int) -> str:     img = Image.open(pdf_path)     # 真实场景用 fitz 按页转图更稳,这里示意     return pytesseract.image_to_string(img, lang="chi_sim+eng")  if __name__ == "__main__":     out = extract_text("sample_contract.pdf")     Path("data/contract.txt").write_text(out, encoding="utf-8")     print(f"✅ 提取文本 {len(out)} 字")

📸 图3:代码截图(OCR 参数与中文语言包配置)

三、踩坑记录

📸 图4:报错截图 / Debug 截图

⚠️ 坑1:Tesseract 找不到中文包 → 装 chi_sim 语言包,lang="chi_sim+eng" 才生效。   ⚠️ 坑2:扫描件倾斜导致识别率暴跌 → 加一步 deskew 二值化预处理,准确率从 60% 提到 90%+。   ⚠️ 坑3:pdfplumber 大文件内存爆 → 逐页处理 + 及时释放,别一次性 load 整本。

四、运行效果

📸 图5:运行结果截图(扫描合同→可搜索文本)

📸 图6:后台进程截图(解析队列)

五、今日代码

📦 今日代码:对应模块已放入项目 ai-contract-review/(day2 文件),随 Day 27 统一开源说明打包提供。

六、明日预告

Day 3:合同结构拆解——自动识别「甲方乙方」「金额」「违约条款」(extractor.py)。

七、互动

你手上的合同,扫描件多还是真 PDF 多?OCR 这块最头疼的是哪种(盖章遮挡?表格?手写?)👇

小码哥 · 30 天 AI 实战系列 · 明日 Day 3

相关学习资料