一尘不染

读取文字的算法或模式

algorithm

我公司有一个客户,它跟踪来自不同位置的不同公司的产品价格。该信息进入数据库。

这些公司每天通过电子邮件将价格发送给我们的客户,当然,电子邮件的格式也有所不同。不可能有任何一家公司更改其格式-他们不会这样做。

一些看起来像这样:

    这是示例文本,可能长达多行...

    位置1
    产品1产品2产品3
    $ 20.99 $ 21.99 $ 33.79

    位置2
    产品1产品2产品3
    $ 24.99 $ 22.88 $ 35.59

其他人看起来像这样:

    产品价格+ /-
    ------------ -------- -------
    位置1
    1 2007.30 +048.20
    2 2022.50 +048.20

    也许这里有一些关于假期的多行文字...

    位置2
    1 2017.30 +048.20
    2 2032.50 +048.20

目前,我们为每个公司的电子邮件格式编写了单独的解析器。但是这些格式经常会稍微改变。我们不能指望每次都在同一行或同一列上的价格。

对于我们来说,查看电子邮件并确定哪个价格与哪个位置的产品价格无关紧要。但是对于我们的代码而言,并不是很多。因此,我正在尝试找到一种更灵活的解决方案,并希望您对采用哪种方法提出建议。我对从正则表达式到神经网络的任何事物都开放-
我将学习完成这项工作所需的知识,我只是不知道我需要学习什么。这是一个词法/解析问题吗?更类似于OCR?

该代码不必自己找出所有格式。电子邮件分为上述几种主要的“样式”。我们确实需要代码足够灵活,以至于新产品线或空格或其他东西不会使文件不可解析。

感谢您提供有关从何入手的建议。


阅读 265

收藏
2020-07-28

共1个答案

一尘不染

我认为这个问题将适合于适当的解析器生成器。如果正则表达式出错,则很难对其进行测试和调试。但是,我会选择一个易于使用的解析器生成器,就像它是语言的一部分一样。

对于这些类型的任务,我将使用pyparsing,因为它具有完整的lr解析器的功能,但语法定义困难且辅助函数非常好。该代码也很容易阅读。

from pyparsing import *

aaa ="""    This is example text that could be many lines long...
             another line

    Location 1
    Product 1     Product 2     Product 3
    $20.99        $21.99        $33.79

    stuff in here you want to ignore

    Location 2
    Product 1     Product 2     Product 3
    $24.99        $22.88        $35.59 """

result = SkipTo("Location").suppress() \  
# in place of "location" could be any type of match like a re.
         + OneOrMore(Word(alphas) + Word(nums)) \
         + OneOrMore(Word(nums+"$.")) \

all_results = OneOrMore(Group(result))

parsed = all_results.parseString(aaa)

for block in parsed:
    print block

这将返回列表列表。

['Location', '1', 'Product', '1', 'Product', '2', 'Product', '3', '$20.99', '$21.99', '$33.79']
['Location', '2', 'Product', '1', 'Product', '2', 'Product', '3', '$24.99', '$22.88', '$35.59']

您可以根据需要对事物进行分组,但为简单起见,我只返回了列表。默认情况下会忽略空格,这使事情变得更加简单。

我不知道其他语言是否等效。

2020-07-28