首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >混合字词的句法分析

混合字词的句法分析
EN

Stack Overflow用户
提问于 2016-10-03 21:23:37
回答 1查看 1.7K关注 0票数 1

我正在尝试使用pyparsing解析维基百科信息框中的数据字段。首先,以下代码工作:

代码语言:javascript
复制
from pyparsing import *

test_line = """{{Infobox company | name                = Exxon Mobil Corp | num_employees_year  = 2015 }}"""

data_group = Group(
    Suppress("|") +
    OneOrMore(White()).suppress() +
    Word(alphanums + printables)("key") +
    OneOrMore(White()).suppress() +
    Suppress("=") +
    OneOrMore(White()).suppress() +
    OneOrMore(Word(alphanums))("value") +
    ZeroOrMore(White()).suppress()
)

infobox_parser = (
    Literal("{{").suppress() +
    Word("Infobox") +
    White().suppress() +
    Word("company") +
    OneOrMore(White()).suppress() +
    OneOrMore(data_group)("values") +
    Literal("}}").suppress()
)

print(infobox_parser.parseString(test_line))

产生的结果:

代码语言:javascript
复制
['Infobox', 'company', ['name', 'Exxon', 'Mobil', 'Corp'], ['num_employees_year', '2015']]

问题是当我将测试字符串更改为

代码语言:javascript
复制
test_line = """{{Infobox company | name                = Exxon Mobil Corp. | num_employees_year  = 2015 }}"""

失败是因为我介绍了“。”作为“公司”的一部分。我认为我可以通过将Group对象更改为

代码语言:javascript
复制
data_group = Group(
    Suppress("|") +
    OneOrMore(White()).suppress() +
    Word(alphanums + printables)("key") +
    OneOrMore(White()).suppress() +
    Suppress("=") +
    OneOrMore(White()).suppress() +
    OneOrMore(Word(alphanums + printables))("value") +
    ZeroOrMore(White()).suppress()
)

但我得到了以下错误:

代码语言:javascript
复制
pyparsing.ParseException: Expected "}}" (at char 91), (line:1, col:92)

我在这里错过了什么?提前谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-10-03 23:12:38

只是几件事。最重要的是,pyparsing不像regex那样进行相同的回溯。也就是说,这样的事情是行不通的:

代码语言:javascript
复制
data = '{' + OneOrMore(Word(printables))("data") + '}'
print(data.parseString('{ this is some data }'))

为什么?因为终止'}‘也匹配为Word(printables),所以OneOrMore将一直运行到结束,然后失败,因为读取数据之后找不到终止的'}’。

直到最近,解决方案还是在OneOrMore表达式中包括一个守卫,这个负面的外观实际上是“我想要单词(可打印),但是首先检查它是否是'}‘--我不想那样”,这看起来如下所示:

代码语言:javascript
复制
data = '{' + OneOrMore(~Literal('}') + Word(printables))("data") + '}'

但是这种情况很常见,最近我在ZeroOrMoreOneOrMore中添加了一个可选的OneOrMore参数。

代码语言:javascript
复制
data = '{' + OneOrMore(Word(printables), stopOn=Literal('}'))("data") + '}'

在您的例子中,每个data_group解析一个key=value对,当您只解析OneOrMore(Word(alphanums))时,您的值就很好了。但是,一旦您将其更改为OneOrMore(Word(alphanums+printables)),您的重复术语就会贪婪地匹配下一条“\”或终止“}”,并且会失败,就像上面的例子一样。

其他几个项目:

  • pyparsing解析将跳过空白。所有这些White()元素都是完全不必要的。
  • 在几个地方,您使用不正确的词,如在Word("Infobox")。在您的有限示例中,这匹配ok,但请记住,单词是用您希望匹配的一组字符定义的,因此Word("Infobox")不仅将匹配"Infobox",而且还将匹配由字母'I‘、'n’、'f‘、'o’、'b‘和/或'x’组成的任何其他单词,例如“收件箱”、"IbIx“、"xoxoxox”等。在这种情况下,您想要的matches解析类将是LiteralKeyword
  • 退一步看,您的data_groups似乎是key=value对,带有分隔的‘key=value’s。我建议在这方面使用delimitedList
  • 最后,使用dump()输出已解析的数据,它将有助于可视化结构和结果名称。

通过这些更改,代码如下所示:

代码语言:javascript
复制
data_group = Group(
    Word(alphas, alphanums+'_')("key") +
    Suppress("=") +
    originalTextFor(OneOrMore(Word(printables), stopOn=Literal('|') | '}}'))("value") 
)

infobox_parser = (
    Literal("{{").suppress() +
    Keyword("Infobox") +
    Keyword("company") + '|' + 
    Group(delimitedList(data_group, '|'))("values") +
    Literal("}}").suppress()
)

print(infobox_parser.parseString(test_line).dump())

给予:

代码语言:javascript
复制
['Infobox', 'company', '|', [['name', 'Exxon Mobil Corp.'], ['num_employees_year', '2015']]]
- values: [['name', 'Exxon Mobil Corp.'], ['num_employees_year', '2015']]
  [0]:
    ['name', 'Exxon Mobil Corp.']
    - key: name
    - value: Exxon Mobil Corp.
  [1]:
    ['num_employees_year', '2015']
    - key: num_employees_year
    - value: 2015
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39840633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档