我公司有一个客户,它跟踪来自不同位置的不同公司的产品价格。该信息进入数据库。
这些公司每天通过电子邮件将价格发送给我们的客户,当然,电子邮件的格式也有所不同。不可能有任何一家公司更改其格式-他们不会这样做。
一些看起来像这样:
这是示例文本,可能长达多行... 位置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?
该代码不必自己找出所有格式。电子邮件分为上述几种主要的“样式”。我们确实需要代码足够灵活,以至于新产品线或空格或其他东西不会使文件不可解析。
感谢您提供有关从何入手的建议。
我认为这个问题将适合于适当的解析器生成器。如果正则表达式出错,则很难对其进行测试和调试。但是,我会选择一个易于使用的解析器生成器,就像它是语言的一部分一样。
对于这些类型的任务,我将使用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']
您可以根据需要对事物进行分组,但为简单起见,我只返回了列表。默认情况下会忽略空格,这使事情变得更加简单。
我不知道其他语言是否等效。