我正在尝试使用pyparsing解析维基百科信息框中的数据字段。首先,以下代码工作:
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))产生的结果:
['Infobox', 'company', ['name', 'Exxon', 'Mobil', 'Corp'], ['num_employees_year', '2015']]问题是当我将测试字符串更改为
test_line = """{{Infobox company | name = Exxon Mobil Corp. | num_employees_year = 2015 }}"""失败是因为我介绍了“。”作为“公司”的一部分。我认为我可以通过将Group对象更改为
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()
)但我得到了以下错误:
pyparsing.ParseException: Expected "}}" (at char 91), (line:1, col:92)我在这里错过了什么?提前谢谢。
发布于 2016-10-03 23:12:38
只是几件事。最重要的是,pyparsing不像regex那样进行相同的回溯。也就是说,这样的事情是行不通的:
data = '{' + OneOrMore(Word(printables))("data") + '}'
print(data.parseString('{ this is some data }'))为什么?因为终止'}‘也匹配为Word(printables),所以OneOrMore将一直运行到结束,然后失败,因为读取数据之后找不到终止的'}’。
直到最近,解决方案还是在OneOrMore表达式中包括一个守卫,这个负面的外观实际上是“我想要单词(可打印),但是首先检查它是否是'}‘--我不想那样”,这看起来如下所示:
data = '{' + OneOrMore(~Literal('}') + Word(printables))("data") + '}'但是这种情况很常见,最近我在ZeroOrMore和OneOrMore中添加了一个可选的OneOrMore参数。
data = '{' + OneOrMore(Word(printables), stopOn=Literal('}'))("data") + '}'在您的例子中,每个data_group解析一个key=value对,当您只解析OneOrMore(Word(alphanums))时,您的值就很好了。但是,一旦您将其更改为OneOrMore(Word(alphanums+printables)),您的重复术语就会贪婪地匹配下一条“\”或终止“}”,并且会失败,就像上面的例子一样。
其他几个项目:
Word("Infobox")。在您的有限示例中,这匹配ok,但请记住,单词是用您希望匹配的一组字符定义的,因此Word("Infobox")不仅将匹配"Infobox",而且还将匹配由字母'I‘、'n’、'f‘、'o’、'b‘和/或'x’组成的任何其他单词,例如“收件箱”、"IbIx“、"xoxoxox”等。在这种情况下,您想要的matches解析类将是Literal或Keyword。key=value对,带有分隔的‘key=value’s。我建议在这方面使用delimitedList。dump()输出已解析的数据,它将有助于可视化结构和结果名称。通过这些更改,代码如下所示:
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())给予:
['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: 2015https://stackoverflow.com/questions/39840633
复制相似问题