2

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

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”字段但在调用下一个字段之前存在的信息(由点“|”划分)。因此,给定上面的例子,理想情况下我想提取“Barack Obama”和“Mitt Romney”——或者至少是它们嵌入的语法('''[[Barack Obama]]''' and [ [米特·罗姆尼]])。其他正则表达式已经从 wikimarkup 中提取了链接,但是我(失败的)尝试使用积极的后向断言的方式有点像:

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

我的想法是它应该找到像 "|nominee1=" 和 "|nominee2=" 这样的字符串,在 "|"、"nominee"、"=" 之间可能有一些空格,然后返回它后面的内容,比如 "Barack Obama" 和 "米特·罗姆尼”。

4

4 回答 4

3

使用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

捕获结果非常简单。

于 2012-12-31T03:22:52.257 回答
1

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

试试这个正则表达式:

\|\s*nominee\d+\s*=\s*(?:''')?\[\[([^]]+)\]\](?:''')?

结果:

re.findall(r"\|\s*nominee\d+\s*=\s*(?:''')?\[\[([^]]+)\]\](?:''')?", markup)
# => ['Barack Obama', 'Mitt Romney']
于 2012-12-14T23:20:37.453 回答
1

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

http://wiki.dbpedia.org/Downloads38

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

于 2012-12-15T00:24:52.027 回答
0

首先,您在nominee\d. 你可能想要nominee\d\s*\=. 此外,您真的不想用正则表达式解析标记。请尝试使用此处的建议之一。

如果您必须使用正则表达式,为什么不使用更易读的多行​​解决方案呢?

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'(nominee\d\s*\=)[^|]*', 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]
于 2012-12-14T23:44:53.567 回答