记录一下那天晚上的排查过程。pypdf 4.2 读一份 30 页的扫描版 PDF,每页 extract_text 都返回空字符串,没报错也没提示加密,换 pdfplumber 结果一样。

刚开始盯着「PDF 用了自定义字体编码,映射表缺失」,折腾了半个多小时,排掉了。

排查方向其实有限,先把可能性排一排。扫描件只有图像层,没有可提取的文本对象。少数情况下是没有做 OCR,工具本身不会识别图片。

还有一种情况,页面内容流被压缩成对象流,解析器读不到。

先确认页面里到底有没有文字对象

python -c "import pdfplumber;pdf=pdfplumber.open('scan.pdf');print(len(pdf.pages[0].chars),len(pdf.pages[0].images))"

随后看资源字典里的字体与 XObject

python -c "from pypdf import PdfReader;r=PdfReader('scan.pdf');print(r.pages[0].get('/Resources').keys())"

再往下用 ocrmypdf 加一层文字再提取

ocrmypdf --language chi_sim --force-ocr scan.pdf scan_ocr.pdf

剩下的就是抽三页比对 OCR 前后的字符数

python -c "from pypdf import PdfReader;print([len(p.extract_text() or '') for p in PdfReader('scan_ocr.pdf').pages[:3]])"

别只看报错消失,验证要多做一步。OCR 后每页能提取 800 到 1500 字,抽样三页的关键字段与人工录入一致,入库流程不再产出空文档。

空文本不等于文件损坏,先看 chars 和 images 的数量就能判断是扫描件还是编码问题。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189