我会把这个任务看作是分块任务,并使用nltk的词性标注器和正则表达式分块器。这将允许您根据句子中单词的词性而不是单词本身定义基于正则表达式的模式。对于给定的句子,您可以执行以下操作:
import nltk
# example sentence
sent = 'send me a table with a price greater than $100'
我首先要做的是稍微修改你的句子,以避免让词性标注器感到困惑。以下是一些可以进行的更改示例(使用非常简单的正则表达式),但你可以尝试并查看是否有其他更改:
$10 -> 10 dollars
200lbs -> 200 lbs
5-7 -> 5 - 7 OR 5 to 7
所以我们得到:
sent = 'send me a table with a price greater than 100 dollars'
现在您可以从句子中获取词性:
sent_pos = nltk.pos_tag(sent.split())
print(sent_pos)
[('send', 'VB'), ('me', 'PRP'), ('a', 'DT'), ('table', 'NN'), ('with', 'IN'), ('a', 'DT'), ('price', 'NN'), ('greater', 'JJR'), ('than', 'IN'), ('100', 'CD'), ('dollars', 'NNS')]
我们现在可以创建一个
分块器, 它可以根据(相对)简单的正则表达式将你的POS标注文本分块:
grammar = 'NumericalPhrase: {<NN|NNS>?<RB>?<JJR><IN><CD><NN|NNS>?}'
parser = nltk.RegexpParser(grammar)
这定义了一个带有语法的解析器,用于分块数字短语(我们将其称为您的短语类型)。它将您的数字短语定义为:可选的名词,后跟可选的副词,后跟比较级形容词、介词、数字和可选的名词。
这只是一种定义短语的建议方式,但我认为这比在单词本身上使用正则表达式要简单得多。
要获取您的短语,您可以执行以下操作:
print(parser.parse(sent_pos))
(S
send/VB
me/PRP
a/DT
table/NN
with/IN
a/DT
(NumericalPhrase price/NN greater/JJR than/IN 100/CD dollars/NNS))
或者只获取您的短语,您可以执行以下操作:
print([tree.leaves() for tree in parser.parse(sent_pos).subtrees() if tree.label() == 'NumericalPhrase'])
[[('price', 'NN'),
('greater', 'JJR'),
('than', 'IN'),
('100', 'CD'),
('dollars', 'NNS')]]