记录一下那天晚上的排查过程。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 的数量就能判断是扫描件还是编码问题。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
