先看现象。用 PaddleOCR 3.0 识别一批扫描发票,抽出的金额里出现「1280.00」这种全角数字,下游 float 转换直接报 ValueError,30% 的样本需要人工回填。

这类报错背后常见的原因有几处,逐个排除就行。OCR 引擎按字形输出,全角半角不做转换。还有一种是清洗流程只 strip 了空格没做 NFKC 归一。

还有一种情况,小数点被识别成中文句号「.」。

另外,千分位逗号与小数点在不同票据上混用。

第一件事是统计语料里全角字符的占比

python -c "import re;s=open('ocr.txt',encoding='utf-8').read();print(len(re.findall(r'[0-9.,]',s)))"

接着在解析前统一做 NFKC 归一

python -c "import unicodedata;print(unicodedata.normalize('NFKC','1280.00'))"

再往下用正则抽出金额并统一小数点

python -c "import re;s='合计 1,280.00 元';t=s.replace(',',',').replace('.','.');print(re.search(r'[0-9][0-9,]*\.[0-9]{2}',t).group())"

等前面都确认过,再把归一后的结果与人工标注抽样比对

python verify_amount.py --ocr ocr.csv --label sample.csv --sample 200

怎么算真的好了,看的是同一批现象。全角金额全部转成半角浮点,float 转换不再报错,200 条抽样里金额一致率达到 99%,人工回填量降到个位数。

全角字符在 OCR 输出里极常见,归一化要放在解析之前而不是之后,顺序错了后面所有正则都要重写。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189