PyPDF2和pypdf对扫描PDF完全失效,因其仅解析文本对象流,而扫描PDF只含图像(/XObject),无字符编码、字体或文本坐标信息,调用extract_text()静默返回空字符串或乱码。

扫描版PDF本身不含可选中文本,直接用 PyPDF2 或 pypdf 读不出文字——必须先做OCR。跳过这步,脚本永远返回空字符串。
为什么 PyPDF2 和 pypdf 对扫描PDF完全失效
这两库只解析PDF中的文本对象流,而扫描PDF里只有图像(/XObject 类型),没有字符编码、字体或坐标文本信息。调用 page.extract_text() 会静默返回空或乱码,不报错,容易误判为“PDF没问题”。
- 用
pdfplumber打开扫描PDF时,page.chars长度为 0,page.rects可能有但无文字关联 -
fitz.Page.get_text("text")(PyMuPDF)同样返回空,除非PDF带隐藏图层文本(极少见) - 验证方法:用
pdfinfo input.pdf查看输出中是否有Pages:但Encrypted:附近无Text相关提示
用 pytesseract + pdf2image 做端到端OCR提取
这是目前最稳的开源组合:先转图,再逐页OCR。注意不是所有PDF都适合直接喂给Tesseract——图像质量决定识别率。
-
pdf2image.convert_from_path()默认用 Ghostscript,需提前安装系统级依赖(Ubuntu:sudo apt install poppler-utils;macOS:brew install poppler) - 关键参数:
dpi=300(低于200易漏字),grayscale=True(减少噪点),thread_count=2(避免多核竞争崩溃) -
pytesseract.image_to_string(img, lang="chi_sim+eng")必须显式指定语言,中文默认不启用,chi_sim比chi_tra对简体印刷体更准 - 每页OCR耗时约 2–8 秒(i7 CPU),别用
image_to_data()获取坐标——除非你要框选字段,否则纯拖慢速度
绕不开的预处理:PDF图像质量差怎么办
扫描件常见模糊、倾斜、底纹、阴影,直接OCR错误率超40%。不能全靠Tesseract自适应——得加轻量预处理。
立即学习“Python免费学习笔记(深入)”;
- 用
cv2.threshold()做自适应二值化(cv2.ADAPTIVE_THRESH_GAUSSIAN_C),比全局阈值更抗阴影 - 用
cv2.fastNlMeansDenoising()降噪,h=10足够,h>15开始模糊文字边缘 - 倾斜校正用
cv2.minAreaRect()找文本行主方向,但仅对长段落有效;标题/表格建议人工定义ROI区域再OCR - 避开过度锐化:
cv2.filter2D()加强边缘常导致“一”变“丨”,得测试后决定是否启用
真正卡住进度的往往不是代码逻辑,而是PDF来源杂(A4/信纸/裁切偏移)、扫描仪自动纠偏失败、以及中英文混排时Tesseract把数字当字母(比如“0”→“O”)。建议先抽10页人工核对OCR结果,再批量跑全量。



















