Python:关于解析人类可读文本的问题

时间:2009-07-20 12:08:22

标签: python parsing

我正在解析人类可读的科学文本,主要是在化学领域。我感兴趣的是将文本分成单词列表,科学术语(下面有更多内容)和标点符号。

因此,例如,我希望文本“你好,世界”。打破4个令牌:1)“你好”; 2)逗号; 3)“世界”和4)时期。请注意,空格不需要专门的令牌。

问题与“科学术语”有关:这些是化学式的名称,例如“1-甲基-4-苯基吡啶鎓”。任何学过化学的人都知道这些公式可能会很长,可能包含数字,短划线和逗号,有时甚至是括号,但我认为假设这些可爱的表达式不能包含空格是安全的。另外,我相信这些表达式必须以数字开头。我希望每个这样的表达式都作为单个标记出现。

今天我使用手动解析来查找以数字开头并以空格,换行符或标点符号后跟空格或换行符结尾的文本“块”。

我想知道是否有智能解决方案(正则表达式或其他)我可以用来根据上述规范对文本进行标记。我在使用Python,但这可能与语言无关。

示例输入(显然忽略内容......):

“你好.1-甲基-4-苯基吡啶是极差的。但是,1-甲基-4-苯基-1,2,3,6-四氢吡啶更差。”

示例输出(每个令牌在其自己的行中):

Hello
.
1-methyl-4-phenylpyridinium
is
ultra
-
bad
.
However
,
1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine
is
worse
.

3 个答案:

答案 0 :(得分:2)

这将解决您当前的示例。它可以调整为更大的数据集。

import re
splitterForIndexing = re.compile(r"(?:[a-zA-Z0-9\-,]+[a-zA-Z0-9\-])|(?:[,.])")
source = "Hello. 1-methyl-4-phenylpyridinium is ultra-bad. However, 1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine is worse."
print "\n".join( splitterForIndexing.findall(source))

结果是:

"""
Hello
.
1-methyl-4-phenylpyridinium
is
ultra-bad
.
However
,
1-methyl-4-phenyl-1,2,3,6-tetrahydropyridine
is
worse
.
"""

抱歉没看到超坏。如果有必要将这些词分开..

import re
splitterForIndexing = re.compile(r"(?:[a-zA-Z]+)|(?:[a-zA-Z0-9][a-zA-Z0-9\-(),]+[a-zA-Z0-9\-()])|(?:[,.-])")
source = "Hello. 1-methyl-4-phenylpyridinium is ultra-bad. However, 1-methyl-4-phenyl-1,(2,3),6-tetrahydropyridine is worse."
print "\n".join( splitterForIndexing.findall(source))

给出:

"""
Hello
.
1-methyl-4-phenylpyridinium
is
ultra
-
bad
.
However
,
1-methyl-4-phenyl-1,(2,3),6-tetrahydropyridine
is
worse
.
"""

答案 1 :(得分:0)

可能有一个正则表达式解析你想要的东西,但我认为它不会非常易读/可维护。我的建议是使用像ANTLR这样的解析器生成器。我认为你必须抛弃你的概念,你可以使化学描述成为一个单一的标记,太复杂了。 ANTLR甚至有一个调试器,所以你可以看到为什么它没有解析你认为应该的东西,我认为不可能使用正则表达式。

此致

Sebastiaan

答案 2 :(得分:0)

我同意Sebastiaan Megens的观点,即正则表达式解决方案可能是可行的,但可能不具有可读性或可维护性,特别是如果您还不熟悉正则表达式。如果您坚持使用Python(我认为这是一个不错的选择),我会推荐pyparsing module

如果您的解析需求应该增长或改变,额外的可维护性将非常方便。 (而且我相信很多人都会说“何时”而不是“如果”!例如,有人已经评论说你可能需要更复杂的概念来说明化学名称需要什么。也许你的要求已经是在你选择工具之前改变!)