Python - 正则表达式 "机器学习"

4

我有成千上万行文本需要查找货币表示,例如:

Lorem ipsum dolor sit amet, 100.000,00 USD sadipscing elitr, sed diam nonumy eirmod 
GBP 400 ut labore et dolore magna aliquyam erat, sed diam voluptua. At USD 20 eos et 
accusam et justo duo dolores et 100,000.00 USD  ea rebum. Stet 3,-- USD gubergren, no 

Python脚本应该返回转换为美元的金额。(例如:100000USF、400 GBP -> USD等)
到目前为止,我手动创建了正则表达式以检索数字-货币组合的值,然后将货币与数据库进行比较并计算汇率。
然而,这既不高效也不具有未来性(例如,如果添加另一种货币)。因此,我想知道是否有一种高效的机器学习算法,我可以用一些示例“训练”它,然后它尝试找到这样的“价值-货币”组合?

货币信息是否总是以数字+单位的形式表示,或者您是否想处理像美元一百万这样的情况?如果您处于第一种情况,并且您的数据更或多或少地结构化,则最好选择正则表达式,否则您将需要一种更高级的策略,混合机器学习和自然语言处理... - bendaizer
3个回答

3
一个人是否能学会一个缩略语是一种货币?如果出现新的货币,那么它怎么区别于任何其他任意的缩略语?比如你遇到了类似“1000 CPU”的东西,如果你不知道CPU是什么,你怎么知道它是(或不是)货币?
你可以使用自然语言处理来查看相关数字周围的上下文,但这需要更多的处理,并且你永远也无法确定。
我的观点是:对于这个问题,机器学习是过度杀伤力,即使适用也没必要。
为什么要走弯路,当有另一种更容易和更准确的方法时呢?

不,我不希望它从文字中学习新的货币;我会将这样的数据片段手动添加到训练数据中。 - Chris
那么这与事先拥有所有货币列表有什么区别呢? - Stephen

2
您的问题并没有被明确定义,但是不需要使用机器学习。可能的货币种类是有限且很少的,货币表示的集合不会非常复杂,无法用正则表达式表示。您只是没有充分利用正则表达式的强大功能。
例如,要匹配多个货币,请使用:
    currency = r"((USD)|(GBP)(...))"

你可以表示出数字部分的表示形式。
    numbers = r"([0-9]+[0-9\.,]*)"

编译正则表达式:

    matcher = re.compile(numbers+r"[\s]*+"currency)

您可以创建一个第二个匹配器来首先匹配货币。如果性能不是很重要,您可能可以使用可选捕获组等巧妙的内容,但我建议使用一个简单的第二个匹配器。
    matcher2 = re.compile(currency+r"[\s]*"+numbers)

请注意,'currency'正则表达式无需手动创建。一旦匹配成功,您可以访问适当的组号(1或3)以获取匹配的货币。例如:
    curren = m.group(1)
    amount = m.group(2)

这是可能的,因为整个“货币”正则表达式被视为单个组。
除非您的输入中存在无限的货币表示模式(可能不可能),否则您的问题肯定可以用适当的正则表达式解决。

为了确保您没有遗漏任何字符串,您可以将试编译的正则表达式与示例中的货币表示进行测试。如果有缺失的字符串,您可以简单地调整正则表达式以捕获它们。 - ealfonso
1
Python的正则表达式在使用(|)操作符时不需要在它们前面加上反斜杠。 - user4815162342
啊,你说得对。我可能在想emacs风格的正则表达式。但我相信原帖作者已经明白了这个概念。 - ealfonso

0

我会使用正则表达式来粗略地提取可能的配对:

import re

test = '''Lorem ipsum dolor sit amet, 100.000,00 USD sadipscing elitr, sed diam nonumy eirmod 
GBP 400 ut labore et dolore magna aliquyam erat, sed diam voluptua. At USD 20 eos et 
accusam et justo duo dolores et 100,000.00 USD  ea rebum. Stet 3,-- USD gubergren, no'''

number = r'([\d+.,]+)'
currency = r'([A-Z]{2,3})'

r1 = re.compile(number + r'\s+' + currency)
r2 = re.compile(currency + r'\s+' + number)

matches = r1.findall(test) + r2.findall(test)

print(matches)

我得到:
[('100.000,00', 'USD'), ('100,000.00', 'USD'), ('GBP', '400'), ('USD', '20')]

从那里,您可以解析数字并过滤掉不存在的货币。您只有五个或六个可能的格式,因此在这里真的没有什么机器学习可以为您做的。


最好预定义货币面额:您的匹配器将把任何2-3个字母的字符串视为面额。请参见下面的答案。 - ealfonso
@ealfonso:很少有与数字相邻的2-3个大写字母字符串。我通常会保持正则表达式简单,并在后期过滤掉不匹配的结果。 - Blender
1
他的输入似乎是随机的,因此可能有很多非货币 2-3 字母单词。由于货币代码列表很容易获取,所以我会使用它。 - ealfonso

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接