【问题标题】:Regular expression for extracting fields from wiki template markup用于从 wiki 模板标记中提取字段的正则表达式
【发布时间】:2012-12-02 23:20:44
【问题描述】:

我想使用 Python 在特定字符串之后提取 MediaWiki 标记格式的内容。例如,2012 U.S. presidential election article 包含名为“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 [ [米特·罗姆尼]])。其他正则表达式有extracted links from the wikimarkup,但我(失败的)尝试使用positive lookbehind assertion 有点类似:

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

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

【问题讨论】:

标签: python regex python-2.7 mediawiki wikipedia


【解决方案1】:

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

捕获结果非常简单。

【讨论】:

    【解决方案2】:

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

    http://wiki.dbpedia.org/Downloads38

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

    【讨论】:

      【解决方案3】:

      首先,nominee\d 后面缺少一个空格。你可能想要nominee\d\s*\=。此外,您真的不想使用正则表达式解析标记。尝试改用here 的建议之一。

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

      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]
      

      【讨论】:

        【解决方案4】:

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

        试试这个正则表达式:

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

        结果:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多