如何使用python解析超大XML文档

如题所述

  在工作时最有吸引力的地方在于可以尽量避免使用昔日的技术。主机、租用线路、COBOL语言......没有人应该要处理这些东西了,对不对?不幸的是,你最终会与现实发生冲突,即使是2014年,大家都知道JSON是最好的方式,你的票务供应商(你无法控制的)会告诉你,只有使用XML导出才能让大容量的数据输出他们的系统。
  唉~~~~,好,很好,无所谓。这只是一次性的事情,我不需要照顾和养活这个XML,我只需要解析它并将数据保存到Postgres中,我们就可以利用它。不应该太困难,我需要写一点python脚本…
  import xml.etree.cElementTree as ET
  tree = ET.parse('huge.xml')
  for ticket_node in tree.findall('ticket'):
  #etc...
  ......这将工作的非常好,如果我们谈论的是一个几MB的XML文档,但是如果遇到的是huge.xml它是1.3GB的巨大文档,这种方法只会融化你的笔记本电脑(以16GB的MacBookPro,一旦python的过程花了超过约3GB的内存,系统变得几乎完全反应迟钝,并且它几乎还没有完成)。回到原点。
  首先让我们快速浏览一下我们的数据。
  <?xml version="1.0" encoding="UTF-8"?>
  <tickets report_date="20140217">
  <ticket>
  <!-- various ticket fields, some of which I want -->
  <comments type="array">
  <comment>
  <!-- various comment fields, some of which I want -->
  </comment>
  <!-- possibly more comment tags -->
  </comments>
  </ticket>
  <!-- many, many ticket tags -->
  </tickets>
  不是很复杂,作为一个整体它不是一个真正的文件中,<ticket>节点只是一个列表,每一类又是一个小文件,我想挑出几部分出来。我不需要做针对树的任何复杂的遍历,只是希望从每个<ticket>节点获得一些数据然后把它扔掉再读下一个。原来ElementTree的对眼前这个场景提供了一个工具:iterparse()。让我们再试一次:
  import xml.etree.cElementTree as ET
  for event, element in ET.iterparse('huge.xml'):
  if event == 'end' and element.tag == 'ticket':
  #process ticket...
  …什么? !我的笔记本电脑又融化了!跟parse-the-whole-file的方法一样使用了完全相同的内存(和系统响应能力)。到底发生了什么事?
  好吧,稍微google了一下,google告诉我,当iterparse()读取元素时,它仍然是在内存中建立了一个完整的文档树,就像我一开始使用parse()方法一样。几个博客和stackoverflow的答案推荐添加element.clear()方法在循环结束时清理你不需要的对象,可以限制内存消耗。我拯救了你的麻烦:它不工作。其他博客,so的答案,甚至一个IBM白皮书表明需要在循环结束时进行更彻底的清扫工作结束:
  import lxml.etree as ET #the IBM piece used lxml but I tried cElementTree also
  for event, element in ET.iterparse('huge.xml'):
  if event == 'end' and element.tag == 'ticket':
  #process ticket...
  element.clear()
  while elem.getprevious() is not None:
  del elem.getparent()[0]
  ......哎呀!我溶化了另一台笔记本电脑!
  为什么不工作?坦率地说,我不知道。
  我稍微离题一下来说说为什么我爱Python。作为一个DBA和系统工程师,我面对着大量的一次性编程挑战。移动这个从这里到那里、Munge数据、将数据从这里迁移到哪里。这种类型的挑战是非常适合于蛮力编程解决问题的这种方式。总之,有时是不值得在建立一个优雅的、易于维护的解决方案上花费任何时间。有时候,你只需要解决这个问题,然后忘掉它。 在处理这类问题上Python最棒的,简洁的语法、良好的设计理念、丰富的库都有助于这个工具,很容易快速解决您碰到的任何问题。即使速度比同等的Java解决方案的10倍还慢,如果需要5分钟的时间写而不是5小时,我更愿意使用python,因为人类工时比CPU工时更有价值。
  所有这一切都证明下述方式解决了我的问题,而不会融化的笔记本电脑:
  import xml.etree.cElementTree as ET
  def process_buffer(buf):
  tnode = ET.fromstring(buf)
  #pull it apart and stick it in the database
  inputbuffer = ''
  with open('huge.xml','rb') as inputfile:
  append = False
  for line in inputfile:
  if '<ticket>' in line:
  inputbuffer = line
  append = True
  elif '</ticket>' in line:
  inputbuffer += line
  append = False
  process_buffer(inputbuffer)
  inputbuffer = None
  del inputbuffer #probably redundant...
  elif append:
  inputbuffer += line
  不是最优雅,或有效率,或者通用的解决方案,但它可以工作。刚刚看了手边的手册,利用其结构的简单性,在解析之前根据xml文件的内容将它切成可管理的块,然后解析和处理每个块,终于可以确保不再需要更长的时间来把它全部处理完。
温馨提示:内容为网友见解,仅供参考
第1个回答  2016-12-19
超大 xml 文档在哪呢?

深入解读Python解析XML的几种方式
笔者建议,在使用Python进行XML解析时,首选使用ET模块,除非你有其他特别的需求,可能需要另外的模块来满足。 解析XML的这几种API并不是Python独创的,Python也是通过借鉴其他语言或者直接从其他语言引入进来的。例如expat就是一个用C语言开发的、用来解析XML文档的开发库。而SAX最初是由DavidMegginson采用java语言开发的,DOM...

用Python解析XML的几种常见方法的介绍
其中解析器负责读取XML文档,并向事件处理器发送事件,如元素开始跟元素结束事件;而事件处理器则负责对事件作出相应,对传递的XML数据进行处理。python中使用sax方式处理xml要先引入xml.sax中的parse函数,还有xml.sax.handler中的ContentHandler。常使用在如下的情况下:一、对大型文件进行处理;二、只需要文件的部分内容,或者...

如何用Python解析三层结构XML?几种常见方法介绍!
另一种解析XML的方法是使用Minidom模块。Minidom模块提供了DOM(文档对象模型)视图,允许我们遍历、修改和创建XML文档。Minidom通过parse()函数解析文件或parseString()函数解析字符串。使用Minidom模块获取XML数据,我们首先需要解析XML文档,然后可以调用节点的属性和方法来访问和操作数据。Minidom支持访问元素、...

Python XML处理中级篇:深入探索lxml库
在处理大型XML文档时,一次性加载整个文档可能会造成内存压力。为了解决这一问题,我们可以利用lxml库的解析器进行增量解析。代码示例如下:在这个示例中,我们定义了一个处理类`ElementHandler`,创建了一个解析器,并将处理类作为目标传递给解析器。然后,通过`etree.parse`解析XML数据。解析器会在解析过程...

python怎么读取xml文件?
解析XML文件是处理XML数据的第一步。ET提供了两种主要方式来解析XML文件:直接从文件解析或从字符串解析。从文件解析:这段代码会加载example.xml文件,并获取其根元素。从字符串解析:这段代码会解析一个包含XML数据的字符串。读取、解析和获取元素:获取了根元素后,你可以遍历XML树并获取你感兴趣的数据...

如何解析超大xml文档
首先,选择适合的XML解析库至关重要。例如,使用DOM(Document Object Model)解析方式虽直观,但对内存消耗较大,不适用于大型文件。相比之下,SAX(Simple API for XML)解析方式更适合处理大型XML文档,因为它是事件驱动的,只在需要时加载和处理数据,而非一次性加载整个文档。在实际应用中,处理超大...

python xml文件怎么打开方式
首先,它是有标签对组成,<aa><\/aa> 标签可以有属性:<aa id=’123’><\/aa> 标签对可以嵌入数据:<aa>abc<\/aa> 标签可以嵌入子标签(具有层级关系):<aa> <bb><\/bb> <\/aa> 获得标签属性 那么,下面来介绍如何用python来读取这种类型的文件。coding=utf-8import xml.dom.minidom#打开xml...

Python XML处理初级篇:入门lxml库
首先,安装lxml至关重要。在Python环境中,你可以通过命令行输入以下命令来安装:在实际操作中,lxml提供了多种解析XML文档的方式,如从文件、字符串或网络链接。例如,解析字符串XML的步骤如下:通过导入etree模块,将包含XML数据的字符串xml_data传入etree.fromstring()函数,即可将数据转化为ElementTree对象...

利用python读取xml中的数据
另一种方法是利用read_xml()函数,这种方法相对更为直接,可以更准确地解析XML结构,减少因标签顺序问题引发的错误。通过这种方法,你可以确保数据的正确提取。最后,如果你的数据结构适合,还可以尝试使用pandas库的pd.json_normalize()函数。这种方法将XML转换为JSON格式,再转换为DataFrame,方便进行数据...

如何用python读取接口返回的xml中的数据?
首先,通过pip安装xmltodict库。安装库后,了解如何将XML数据解析为Python字典。以示例XML数据为例,使用xmltodict.parse函数将其转换为字典。访问Python字典中的数据,例如获取书籍标题或作者,只需使用字典索引。修改字典中的数据后,使用xmltodict.unparse函数将修改后的字典转换回XML格式。高级用法包括处理XM...

相似回答