用于从wiki模板标记中提取字段的正则表达式



我想使用Python提取在特定字符串后面的MediaWiki标记中格式化的内容。例如,2012年美国总统大选文章包含名为"nominee1"one_answers"nomine2"的字段。玩具示例:

In [1]: markup = get_wikipedia_markup('United States presidential election, 2012')
In [2]: markup
Out[2]:
u"{{
| nominee1 = '''[[Barack Obama]]'''n
| party1 = Democratic Party (United States)n
| home_state1 = [[Illinois]]n
| running_mate1 = '''[[Joe Biden]]'''n
| nominee2 = [[Mitt Romney]]n
| party2 = Republican Party (United States)n
| home_state2 = [[Massachusetts]]n
| running_mate2 = [[Paul Ryan]]n
}}"

以上面的选举文章为例,我想提取"nomineeN"字段后面的信息,但该信息存在于调用下一个字段之前(由pip"|"划分)。因此,在上面的例子中,我最好提取"巴拉克·奥巴马"one_answers"米特·罗姆尼"——或者至少提取它们嵌入的语法("[[巴拉克·奥巴马]]''和[[米特·罗姆尼]])。其他regex已经从wikimarkup中提取了链接,但我(失败的)尝试使用积极的后备断言有点像:

nominees = re.findall(r'(?<=|nomineed=)S+',markup)

我的想法是,它应该找到像"|nomine1="one_answers"|nomINE2="这样的字符串,在"|"、"提名人"one_answers"="之间可能有一些空格,然后返回后面的内容,比如"Barack Obama"one_answers"Mitt Romney"。

使用mwparserfromhell!它浓缩了您的代码,并且对于捕获结果更令人放心。用于此示例:

import mwparserfromhell as mw
text = get_wikipedia_markup('United States presidential election, 2012')
code = mw.parse(text)
templates = code.filter_templates()
for template in templates:
if template.name == 'Infobox election':
nominee1 = template.get('nominee1').value
nominee2 = template.get('nominee2').value
print nominee1
print nominee2

捕捉结果非常简单。

这里不需要Lookbehinds——使用匹配组来指定应该从字符串中提取的内容要容易得多。(事实上,lookbehinds在这里不能与Python的正则表达式引擎一起工作,因为可选的空格使表达式的宽度可变。)

试试这个正则表达式:

|s*nomineed+s*=s*(?:''')?[[([^]]+)]](?:''')?

结果:

re.findall(r"|s*nomineed+s*=s*(?:''')?[[([^]]+)]](?:''')?", markup)
# => ['Barack Obama', 'Mitt Romney']

对于这样的信息框数据,最好使用DBpedia。他们已经为你完成了所有的提取工作:)

http://wiki.dbpedia.org/Downloads38

请参阅"本体信息框属性"文件。在这里,你不必是本体论专家。只需使用简单的tsv解析器即可找到您需要的信息!

首先,nomineed后面缺少一个空格。您可能想要nomineeds*=。此外,您真的不想用regex解析标记。请尝试使用此处的某个建议。

如果必须使用regex,为什么不使用可读性稍高的多行解决方案呢?

import re
markup_string = """{{
| nominee1 = '''[[Barack Obama]]'''
| party1 = Democratic Party (United States)
| home_state1 = [[Illinois]]
| running_mate1 = '''[[Joe Biden]]'''
| nominee2 = [[Mitt Romney]]
| party2 = Republican Party (United States)
| home_state2 = [[Massachusetts]]
| running_mate2 = [[Paul Ryan]]<br>
}}"""
for match in re.finditer(r'(nomineeds*=)[^|]*', markup_string, re.S):
end_nominee, end_line = match.end(1), match.end(0)
print end_nominee, end_line
print markup_string[end_nominee:end_line]

最新更新