0

我有一个巨大的 xml 文件(当前的维基百科转储)。这个大小约为 45 GB 的 xml 代表当前维基百科的全部数据。该文件的前几行是(更多的输出):

    <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.8/" xmlns:xsi="http://ww
    w.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/x
    ml/export-0.8/ http://www.mediawiki.org/xml/export-0.8.xsd" version="0.8" xml:la
    ng="en">
      <siteinfo>
        <sitename>Wikipedia</sitename>
        <base>http://en.wikipedia.org/wiki/Main_Page</base>
        <generator>MediaWiki 1.21wmf6</generator>
        <case>first-letter</case>
        <namespaces>
          <namespace key="-2" case="first-letter">Media</namespace>
          <namespace key="-1" case="first-letter">Special</namespace>
          <namespace key="0" case="first-letter" />
          <namespace key="1" case="first-letter">Talk</namespace>
          <namespace key="2" case="first-letter">User</namespace>
          <namespace key="3" case="first-letter">User talk</namespace>
          <namespace key="4" case="first-letter">Wikipedia</namespace>
          <namespace key="5" case="first-letter">Wikipedia talk</namespace>
          <namespace key="6" case="first-letter">File</namespace>
          <namespace key="7" case="first-letter">File talk</namespace>
          <namespace key="8" case="first-letter">MediaWiki</namespace>
          <namespace key="9" case="first-letter">MediaWiki talk</namespace>
          <namespace key="10" case="first-letter">Template</namespace>
          <namespace key="11" case="first-letter">Template talk</namespace>
          <namespace key="12" case="first-letter">Help</namespace>
          <namespace key="13" case="first-letter">Help talk</namespace>
          <namespace key="14" case="first-letter">Category</namespace>
          <namespace key="15" case="first-letter">Category talk</namespace>
          <namespace key="100" case="first-letter">Portal</namespace>
          <namespace key="101" case="first-letter">Portal talk</namespace>
          <namespace key="108" case="first-letter">Book</namespace>
          <namespace key="109" case="first-letter">Book talk</namespace>
          <namespace key="446" case="first-letter">Education Program</namespace>
          <namespace key="447" case="first-letter">Education Program talk</namespace
    >
          <namespace key="710" case="first-letter">TimedText</namespace>
          <namespace key="711" case="first-letter">TimedText talk</namespace>
        </namespaces>
      </siteinfo>
      <page>
        <title>AccessibleComputing</title>
        <ns>0</ns>
        <id>10</id>
        <redirect title="Computer accessibility" />
        <revision>
          <id>381202555</id>
          <parentid>381200179</parentid>
          <timestamp>2010-08-26T22:38:36Z</timestamp>
          <contributor>
            <username>OlEnglish</username>
            <id>7181920</id>
          </contributor>
          <minor />
          <comment>[[Help:Reverting|Reverted]] edits by [[Special:Contributions/76.2
    8.186.133|76.28.186.133]] ([[User talk:76.28.186.133|talk]]) to last version by 
    Gurch</comment>
          <text xml:space="preserve">#REDIRECT [[Computer accessibility]] {{R from C
    amelCase}}</text>
          <sha1>lo15ponaybcg2sf49sstw9gdjmdetnk</sha1>
          <model>wikitext</model>

...等等

注意树中的页面元素。它对应于 Wikipedia 中的唯一页面。给定的 XML 以页面元素的形式包含 Wikipedia 的所有页面。我需要编写一个解析器,在其中我需要从页面中提取所有维基百科页面的标题条目的值,并假设(为简单起见)打印它们。

我正在尝试使用 Python 构建相同的内容(尽管如果提供解决方案,我愿意切换语言)。我知道的唯一方法是使用ElementTree

但是,使用函数 parse('file.xml') 需要首先完全解析整个文档,然后输出任何结果。很明显,我知道整个 xml 由页面元素组成。我希望程序在解析 xml 的其余部分时开始打印标题。这还可能吗。如果是这样,怎么做?

编辑注意:我在这里引用了一个提取标题的示例,以使问题保持​​简单。但是,我确实需要 xml 解析功能,因为我需要在将来提取相同的功能。

4

3 回答 3

3

您需要的是一个基于事件的 XML 库,它会在增量解析时向您发送片段,而不是为整个文档创建树。典型的答案是xml.sax 标准库模块,尽管我确信还有很多其他模块。

于 2013-04-08T23:58:24.330 回答
1

我没有尝试使用这么大的数据集,但我发现lxml 模块既快速又有用。

此处的 lxml.etree 教程提供了一个可能具有指导意义的示例。

关键段落是:

iterparse() 的一个非常重要的用例是解析生成的大型 XML 文件,例如数据库转储。大多数情况下,这些 XML 格式只有一个主要数据项元素直接挂在根节点下方,并且重复了数千次。在这种情况下,最好的做法是让 lxml.etree 进行树构建,并且只在这个元素上截取,使用正常的树 API 进行数据提取。

于 2013-04-09T01:59:19.830 回答
0

当然,这是可能的。以一种丑陋的方式,您可以在文本模式下逐行读取文件。然后使用正则表达式或仅使用简单的字符串搜索方法(关键字 as 和 )作为​​过滤器以获取以下形式的行

<title>AccessibleComputing</title>

然后,您可以获得头衔,并做您想做的事。

于 2013-04-08T23:49:46.460 回答