【问题标题】:convert to lxml sax interface from default python xml.sax从默认 python xml.sax 转换为 lxml sax 接口
【发布时间】:2012-02-05 05:23:54
【问题描述】:

我希望加快解析维基百科的一部分,大约 5gb。现在我正在使用一个使用 pythons sax 接口的脚本,lxml 似乎是一个直接的加速解决方案。

但是,我对 lxml sax 文档有点困惑,因此任何指向简单示例的指针/链接都会有所帮助。这是我要转换的有问题的脚本,https://gist.github.com/1739351

【问题讨论】:

  • 您可以尝试使用etree.iterparse 功能。我有一个脚本可以解析维基百科数据库转储并提取文章here
  • 从其他人那里读取代码总是有帮助的,分叉。谢谢。

标签: python xml sax lxml wikipedia


【解决方案1】:

lxml.sax 不是xml.sax 的插件替代品。它提供附加功能:

>>> import lxml.sax
>>> help(lxml.sax)
Help on module lxml.sax in lxml:

NAME
    lxml.sax - SAX-based adapter to copy trees from/to the Python standard libra
ry.

FILE
    c:\python27\lib\site-packages\lxml\sax.py

DESCRIPTION
    Use the `ElementTreeContentHandler` class to build an ElementTree from
    SAX events.

    Use the `ElementTreeProducer` class or the `saxify()` function to fire
    the SAX events of an ElementTree against a SAX ContentHandler.
[snip]

你有两个选择:

选项 1:继续使用 SAX,尝试通过删除所有这些断言或至少使它们更高效来加速代码,例如

def characters(self, content):
    # assert content is not None and len(content) > 0
    assert content
    # if len(self.stack) == 0:
    if not self.stack:
        return
    if self.stack[-1] == "title":
        self.title += content
    elif self.stack[-1] == "text":
        # assert self.title is not None
        assert self.title # This assertion is gross overkill IMHO
        self.text += content

选项 2:忘记 SAX,使用 ElementTree 接口,使用 iterparse 解析,并随时清理您身后的树。阅读this。 ElementTree 界面有 3 种选择:

(a) import xml.etree.ElementTree as et ... 用 Python 编写;太慢了
(b) import xml.etree.cElementTree as et ... 用 C 语言编写;更快
(c) import lxml.etree as et ... 可能比 (b) 慢,但有额外的功能。

如果您需要有关选项 (2) 的帮助,请在 SO 中搜索“[python] iterparse”,然后在必要时提出单独的问题(即不要在 cmets 中就这个问题提问)。

【讨论】:

  • 感谢 John,您澄清说这不是替代品的下降,这让我回到了按照教程学习并使用 lxml 的优势,它的 etree api。
  • 除了,我的阅读是否正确,lxml(即使使用 iterparse)实际上不是流解析器(即,它在内存中构建树)?
  • @mcepl:是的,它在内存中构建了一棵树,但您可以随时修剪树——结果:两全其美;击败 SAX 的 sox。如果您想了解更多信息,请搜索“[python] iterparse”。
【解决方案2】:

也许你可以试试 lxml.etree,它是一种 Python 式的 XML 解析方式,既高效又简洁。

【讨论】:

  • 是的,我想使用 lxml.etree 方法,但我需要一些帮助来理解类似于该脚本中已定义的迭代或类似 sax 的事件。
  • 说真的很简单,它读取xml文件,每次找到一个开始标记它调用处理程序的函数startElement(tag:String, attrs:dict),当它找到一个结束标记它调用函数 endElement(tag:String)
猜你喜欢
  • 2020-09-26
  • 1970-01-01
  • 2011-12-14
  • 1970-01-01
  • 2013-03-29
  • 2023-04-04
  • 2019-11-17
  • 2012-04-06
相关资源
最近更新 更多