2015-12-04 64 views
1

我有一个代码使用正则表达式从文本(format = mm-dd-yyyy)中提取日期。如何获得最接近的匹配正则表达式

注意:该文本是使用OCR在票据图像上获得的。所以,预期的日期格式是mm-dd-yyyy,但它可以是使用OCR获取的任何随机文本。

import re 
date_reg_exp = re.compile('\d{2}[-/.]\d{2}[-/.]\d{4}') #works for mm-dd-yyyy 
matches_list=date_reg_exp.findall(test_str) 
for match in matches_list2: 
    print match 

如果我有一个字符串'This is a text extracted from OCR 09-11-2015'上面的代码工作和结果的日期作为输出'09-11-2015'。但是,如果我有一个字符串'This is o text extractud fram OCR 09-11-201 5''This is o text xtractud fram OCR 09-11-201''This is o text xtractud fram OCR O9-11-201'它会失败。我如何为这样的场景编写代码,在这个场景中它也挑选最接近的匹配项。

+1

它取决于“最近”的定义。你的例子可以通过在匹配之前删除空格来处理。 – eph

+0

好的。让我更具体一些。如果我有一个字符串''字符串是09-11-201',这是正则表达式最接近的匹配。这应该被打印为输出。 输出 - '09-11-201' –

+0

所有的月份和日期都是正确的格式,只是年份已经搞乱了吗? –

回答

0

试戴

O?\d{1,2}[-/\.]\d{2}[-/\.][\d\s]{2,} 

由于如下─

>>>import re 
>>>s = """If I have a string 'This is a text extracted from OCR 09-11-2015' the above code works and results the Date as output '09-11-2015'. But, if I have a string 'This is o text extractud fram OCR 09-11-201 5' or 'This is o text xtractud fram OCR 09-11-201' or 'This is o text xtractud fram OCR O9-11-201' it fails. How to I write a code for such scenario where it also picks up the nearest match.""" 
>>>re.findall(r'O?\d{1,2}[-/\.]\d{2}[-/\.][\d\s]{2,}',s) 
>>>['09-11-2015', '09-11-2015', '09-11-201 5', '09-11-201', 'O9-11-201'] 

然后尝试所有O0取代。

>>>[i.replace('O','0') for i in ['09-11-2015', '09-11-2015', '09-11-201 5', '09-11-201', 'O9-11-201']] 
>>>['09-11-2015', '09-11-2015', '09-11-201 5', '09-11-201', '09-11-201'] 

查看即时DEMO

或 - 如果日期分隔符在日期如/,.,-然后下面应提取日期 - 它认为所有l33t字符。像$5

\b[\w\$\s]{2}\s*[\.-/-]\s*[\w\$]{2,}\s*[\.-/-]\s*[\w\$]{2,} 

查看即时DEMO

注:你不会得到100%准确的结果,因为你的数据是一场灾难,而是使用好的ocr引擎,如Abbyy,这可以提高准确性。


编辑

如果你想实现某种fuzzymatch的/ Levenshtein Distance然后使用FuzzyWuzzy模块。

+0

这适用于额外的空间。但是如果缺少像'09 -11-201'这样的数字,它就会失败。我需要一个通用的'正则表达式'或某种算法来帮助挑选这样的场景。 –

+0

你可以发布所有可能的日期格式,而我可以使正则表达式一般化。 – SIslam

+0

现在我只有一种格式的日期'mm-dd-yyyy'。我实际上正在从事OCR(从账单提取日期)。所以我需要这个场景。听说Levenshtein,但我并没有意识到它在这种情况下的实现,因为“日期”不是英文单词。 –

0

这不是标题要求 但是如您所说的Levenshtein距离可能对您的情况有用。

from dateutil.parser import parse 

s = 'This is o text xtractud fram OCR O9-11-201' 

parse(s, fuzzy=True) 

datetime.datetime(201, 9, 11, 0, 0) 

Dateutil提供了一个模糊的日期时间分析器。

这适用于'09-11-201'但不会对'09-11-201 5'

+0

它会适用于“O9-11-2015”或“09 -11-201S”吗?因为OCR引擎可能会对'0'和'O'以及'5'和'S'产生混淆。 –

+0

在上面的例子中,我错误地使用了'O'而不是'0'。它在这里工作,因为字母表不在日期之间,而是简单地停止。 因此,它不适用于字母表。如果您无法找到您应该找到的日期,则可以在更换所有S和O后编写更多代码来提取日期。 – Shivendra

2

工作有几种方法你可以实现正则表达式的近似匹配。最“理论上直接”的方法很可能会要求您对DFA执行edit-distance类似dynamic programming的计算。

这是一个相当棘手的编码算法,它没有太多的实现。最有名的是Agrep(从技术上说,agrep工具实现了几种算法,但其中最为人熟知的是模糊正则表达式匹配)。

通过此关键字使用Google搜索简短的this library,它似乎有Python绑定,可能正是你需要的。

+0

如果您对图书馆很熟悉,请通过提供示例帮助我理解。 –

+0

已经在那里给出的例子有什么问题? https://github.com/laurikari/tre/blob/master/python/example.py –

相关问题