【问题标题】:Extracting page titles and contributors from MediaWiki XML从 MediaWiki XML 中提取页面标题和贡献者
【发布时间】:2012-12-15 18:53:43
【问题描述】:

我有一个非常大 (7GB) 的 MediaWiki XML 转储,其中包含对 Wiki 的每个页面所做的每次更改的记录。我正在尝试记录哪些用户对每个页面做出了贡献,因此我想从 XML 中提取它。

XML 看起来像:

<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/">
 <page>
  <title>Unique Page title</title>
  <id>11</id>
  <restrictions>sysop</restrictions>
  <revision>
    <id>11</id>
    <timestamp>2005-10-26T02:23:03Z</timestamp>
    <contributor>
      <ip>MediaWiki default</ip>
    </contributor>
    <text xml:space="preserve">i</text>
  </revision>
 </page>
 <page> ... </page>
 <page> ... </page>
 ...
</mediawiki>

对于这种大小的文件,我相信我需要使用 iterparse。现在,我只是想打印出标题,但是当我运行以下代码时,它会打印“None”。

NS = '{http://www.mediawiki.org/xml/export-0.3/}'
from xml.etree.ElementTree import iterparse
with open('XMLFile.xml') as f:
    for event, elem in iterparse(f):
        if elem.tag == NS + 'page':
            for node in elem:
                if node.tag == NS + 'title':
                    print node.text()
        elem.clear()

【问题讨论】:

标签: python xml-parsing python-2.7 mediawiki elementtree


【解决方案1】:

尝试在迭代解析期间直接拉出“标题”元素,而不是进行二次循环:

NS = '{http://www.mediawiki.org/xml/export-0.3/}'
from xml.etree.ElementTree import iterparse
with open('XMLFile.xml') as f:
    for event, elem in iterparse(f):
            if elem.tag == NS + 'title':
                print elem.text
            elem.clear()

似乎对我有用。

【讨论】:

  • 我需要确保标题元素和贡献者都引用相同的修订版——也就是说,它们都具有相同的父元素。看起来这个解决方案没有这样做,对吗?
【解决方案2】:

在打印title 元素的文本内容时会得到None,因为您“太早”使用elem.clear()。默认情况下,iterparse() 仅生成“结束”事件。当page 的“结束”事件被触发时,它的所有子元素,包括title,都已经被清除(清空)了。

如果问题代码中的elem.clear() 仅向右移动一个缩进级别(四个空格),它将按预期工作。使您的代码工作的另一种方法是将iterparse(f) 更改为iterparse(f, events=["start"])

node.text() 应该是node.text

有关iterparse() 的更多详细信息,请参阅http://effbot.org/zone/element-iterparse.htm


假设 XML 转储 (mw.xml) 如下所示:

<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/">
  <page>
    <title>Unique Page title 1</title>
    <id>11</id>
    <restrictions>sysop</restrictions>
    <revision>
      <id>11</id>
      <timestamp>2005-10-26T02:23:03Z</timestamp>
      <contributor>
       <username>Alice</username>
      </contributor>
      <text xml:space="preserve">i</text>
    </revision>
  </page>

  <page>
    <title>Unique Page title 2</title>
    <id>11</id>
    <restrictions>sysop</restrictions>
    <revision>
      <id>11</id>
      <timestamp>2005-10-26T02:23:03Z</timestamp>
      <contributor>
       <username>Bob</username>
      </contributor>
      <text xml:space="preserve">j</text>
    </revision>
  </page>
</mediawiki>

以下是关于如何获得标题和贡献者的建议:

from xml.etree.ElementTree import iterparse

NS = '{http://www.mediawiki.org/xml/export-0.3/}'

with open('mw.xml') as f:
    for event, elem in iterparse(f):
        if elem.tag == '{0}page'.format(NS):
            title = elem.find("{0}title".format(NS))
            contr = elem.find(".//{0}username".format(NS))

            if title is not None:
                print title.text
            if contr is not None:
                print contr.text

            elem.clear()

输出:

Unique Page title 1 
Alice
Unique Page title 2 
Bob

我假设您想要贡献者的用户名。根据最新的XML Schemacontributor 可以包含usernameip 和/或id 子元素(对于 0.3 版本的架构也是如此)。

【讨论】:

    【解决方案3】:

    我没有使用 Python 和 iterparse 的经验,但一般来说,使用迭代 XML 解析器的方式是这样的:

    • 在解析循环之外,设置变量来存储当前页面标题和贡献者列表。
    • 在循环内部,每当打开page 标记时,重置变量。
    • 遇到title 标记时,将页面标题变量设置为其内容。
    • 当您遇到contributor 标签时,将其内容添加到贡献者列表中。
    • page标签关闭时,输出收集到的标题和贡献者列表。

    【讨论】:

      猜你喜欢
      • 2020-11-29
      • 2011-09-13
      • 1970-01-01
      • 2018-07-26
      • 2017-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-24
      相关资源
      最近更新 更多