You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合正则与Jaro-Winkler/Levenshtein相似度提取含字符误差的PDF文本值?

基于OCR错误修正+相似度匹配的文本提取方案

核心思路

先预处理修正常见OCR字符错误,再结合Jaro-Winkler/Levenshtein相似度定位目标前后缀,最后提取中间值。

步骤1:预处理修正OCR错误

针对OCR常见的字符混淆(如0↔O、I↔l、1↔I、n↔h),通过字符映射表结合上下文判断(比如单词中的0替换为O)做文本清洗,减少正则匹配障碍。

步骤2:相似度匹配定位前后缀

用Jaro-Winkler(适合短文本相似度)或Levenshtein(基于编辑距离)算法,找到与目标前后缀(如some text和some other text)相似度达标(或编辑距离在允许范围内)的片段,确定提取范围。

步骤3:提取并清洗目标值

在定位到的前后缀之间提取内容,再用正则过滤掉多余的分隔符(如空格、逗号、短横线),得到最终目标值。

Java实现示例

需要引入Apache Commons Text库(提供相似度计算工具),Maven依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.10.0</version>
</dependency>

提取代码:

import org.apache.commons.text.similarity.JaroWinklerDistance;
import java.util.HashMap;
import java.util.Map;

public class OcrValueExtractor {
    // 常见OCR字符错误映射
    private static final Map<Character, Character> OCR_ERROR_MAP = new HashMap<>();
    static {
        OCR_ERROR_MAP.put('0', 'O');
        OCR_ERROR_MAP.put('l', 'I');
        OCR_ERROR_MAP.put('1', 'I');
        OCR_ERROR_MAP.put('n', 'h'); // 适配otner→other的错误
    }

    // 预处理文本,修正常见OCR错误
    private static String preprocessOcrText(String text) {
        StringBuilder sb = new StringBuilder(text);
        for (int i = 0; i < sb.length(); i++) {
            char c = sb.charAt(i);
            if (OCR_ERROR_MAP.containsKey(c)) {
                // 判断是否为单词组成部分,是则替换为对应字母
                boolean isInWord = (i > 0 && Character.isLetter(sb.charAt(i-1))) 
                                || (i < sb.length()-1 && Character.isLetter(sb.charAt(i+1)));
                if (isInWord) {
                    sb.setCharAt(i, OCR_ERROR_MAP.get(c));
                }
            }
        }
        return sb.toString();
    }

    // 用Jaro-Winkler相似度匹配前后缀,提取中间值
    private static String extractTargetValue(String ocrText, String targetPrefix, String targetSuffix, double simThreshold) {
        JaroWinklerDistance distance = new JaroWinklerDistance();
        String processedText = preprocessOcrText(ocrText);

        // 定位前缀位置
        int prefixEnd = -1;
        int prefixLen = targetPrefix.length();
        for (int i = 0; i <= processedText.length() - prefixLen; i++) {
            String sub = processedText.substring(i, i + prefixLen);
            if (distance.apply(sub, targetPrefix) >= simThreshold) {
                prefixEnd = i + prefixLen;
                break;
            }
        }
        if (prefixEnd == -1) return null;

        // 定位后缀位置
        int suffixStart = -1;
        int suffixLen = targetSuffix.length();
        for (int i = prefixEnd; i <= processedText.length() - suffixLen; i++) {
            String sub = processedText.substring(i, i + suffixLen);
            if (distance.apply(sub, targetSuffix) >= simThreshold) {
                suffixStart = i;
                break;
            }
        }
        if (suffixStart == -1) return null;

        // 提取并清洗目标值
        String candidate = processedText.substring(prefixEnd, suffixStart).trim();
        return candidate.replaceAll("^[ -]*(.*?)[ ,-]*$", "$1");
    }

    public static void main(String[] args) {
        String ocrText = "s0me text MY_VALUE, some otner text";
        String prefix = "some text";
        String suffix = "some other text";
        String result = extractTargetValue(ocrText, prefix, suffix, 0.8);
        System.out.println("提取结果:" + result); // 输出 MY_VALUE
    }
}

注意事项

  • 阈值调整:根据OCR错误率调整相似度阈值,错误多则设为0.7-0.8,错误少可设为0.9
  • 扩展错误映射:根据实际PDF的OCR错误类型,补充更多字符映射(如e↔c、t↔f等)
  • 替换相似度算法:如果偏好编辑距离,可改用LevenshteinDistance,判断编辑距离≤2即可认为匹配

内容的提问来源于stack exchange,提问作者Si7ius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 19:43:20