Skip to main content
 首页 » 编程设计

python之流解析 Wiki Xml 转储

2025年05月04日7emanlee

我不确定以前是否有人问过这个问题,但我找不到它,请原谅我的无知。我想解析(流解析)大约 40 Gig 的维基百科 xml 转储。我正在尝试使用 lxml iterparse aka 流解析器来为我完成这项工作,但由于某种原因,我编写的代码对我不起作用。在我解释我想做什么之前,让我们考虑一下这种 xml 格式

<root> 
  <page> 
    <title> A  </title> 
    <text> ..........blah blah...... </text> 
  </page> 
 
  <page> 
  <title> B </title> 
  <text> This is a line of sample text in title B  </text> 
  </page> 
 
  <page> 
  <title> C </title> 
  <text> ............blah blah........ </text> 
  </page> 
</root> 

在上面的 xml 结构中,这是 wiki 转储所具有的,我想做的是使用 python 流解析器读取“页面”标签(基本上分隔转储中的不同文章)内的每一件事作为 lxml(不将整个 xml 树加载到内存中,这是不可能的)并对其执行正则表达式。正是我想要做的是,如果在当前的“page”元素中查找“Category:Living People”文本标签内的内容,如果找到这样匹配的正则表达式,则将“text”标签内的全部内容写成文本文件。但在正则表达式部分之前,我遇到了 lxml 解析器本身的问题。我在下面尝试的示例代码。提前致谢:)

#LXML parser 
from lxml import etree 
 
def fast_iter(context, func): 
    for event, elem in context: 
        func(elem) 
        elem.clear() 
        while elem.getprevious() is not None: 
            del elem.getparent()[0] 
    del context 
 
def process_element(elem): 
    print elem.xpath( 'description/text( )' ) 
 
context = etree.iterparse( MYFILE, tag='item' ) 
fast_iter(context,process_element) 

请随意完全更改代码并提供您自己的版本,只要我解决了我的问题,我真的不介意!

请有人帮忙!

请您参考如下方法:

from xml.sax import ContentHandler, parseString 
from StringIO import StringIO 
from lxml import etree 
 
CONTENT = """ 
<root> 
  <page> 
    <title> A  </title> 
    <text> ..........blah blah...... </text> 
  </page> 
 
  <page> 
  <title> B </title> 
  <text> This is a line of sample text in title B  </text> 
  </page> 
 
  <page> 
  <title> C </title> 
  <text> ............blah blah........ </text> 
  </page> 
</root> 
""" 
 
def fast_iter(context, func): 
    for action, elem in context: 
        func(elem) 
        elem.clear() 
        while elem.getprevious() is not None: 
            del elem.getparent()[0] 
    del context 
 
def process_element(elem): 
    print elem.xpath( './text/text( )' ) 
 
class WikiContentHandler(ContentHandler): 
 
    def startDocument(self): 
        self.character_buffer = None 
 
    def startElement(self, name, attrs): 
        if name == 'text': 
            self.character_buffer = StringIO() 
 
    def endElement(self, name): 
        if name == 'text': 
            print self.character_buffer.getvalue() 
            self.character_buffer.close() 
            self.character_buffer = None 
 
    def characters(self, content): 
        if self.character_buffer != None: 
            self.character_buffer.write(content) 
 
def parse_wiki(): 
    parseString(CONTENT, WikiContentHandler()) 
 
if __name__ == '__main__': 
    parse_wiki() 
 
    context = etree.iterparse( StringIO(CONTENT), tag='page' ) 
    fast_iter(context, process_element) 

以上是两种解析XML的方式,一种是使用lxml,另一种是使用Python标准库。两者都打印出<text>中的所有信息标签。只需查看打印语句的位置并进行额外处理即可。