我必须处理足够大的xml文档(高达1GB)并使用python解析它们.我正在使用iterparse()函数(SAX样式解析).
我关注的是,假设你有一个这样的xml
<?xml version="1.0" encoding="UTF-8" ?>
<families>
<family>
<name>Simpson</name>
<members>
<name>Homer</name>
<name>Marge</name>
<name>Bart</name>
</members>
</family>
<family>
<name>Griffin</name>
<members>
<name>Peter</name>
<name>Brian</name>
<name>Meg</name>
</members>
</family>
</families>
Run Code Online (Sandbox Code Playgroud)
问题是,当然知道我什么时候得到一个姓氏(如辛普森一家),当我得到一个家庭成员的名字时(例如荷马)
到目前为止我一直在做的是使用"开关",告诉我是否在"成员"标签内,代码看起来像这样
import xml.etree.cElementTree as ET
__author__ = 'moriano'
file_path = "test.xml"
context = ET.iterparse(file_path, events=("start", "end"))
# turn it into an iterator
context = iter(context)
on_members_tag = False
for event, elem in context:
tag = elem.tag
value = elem.text
if value :
value = value.encode('utf-8').strip()
if event == 'start' :
if tag == …Run Code Online (Sandbox Code Playgroud) 这最终消耗了我所有可用的内存,然后该进程被终止.我已经尝试将标签更改schedule为"较小"标签,但这并没有什么区别.
我做错了什么/如何处理这个大文件iterparse()?
import lxml.etree
for schedule in lxml.etree.iterparse('really-big-file.xml', tag='schedule'):
print "why does this consume all my memory?"
Run Code Online (Sandbox Code Playgroud)
我可以轻松地将其切割并以较小的块处理它,但这比我想要的更糟糕.
我必须使用如下结构解析1Gb XML文件,并在"Author"和"Content"标签中提取文本:
<Database>
<BlogPost>
<Date>MM/DD/YY</Date>
<Author>Last Name, Name</Author>
<Content>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas dictum dictum vehicula.</Content>
</BlogPost>
<BlogPost>
<Date>MM/DD/YY</Date>
<Author>Last Name, Name</Author>
<Content>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas dictum dictum vehicula.</Content>
</BlogPost>
[...]
<BlogPost>
<Date>MM/DD/YY</Date>
<Author>Last Name, Name</Author>
<Content>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas dictum dictum vehicula.</Content>
</BlogPost>
</Database>
Run Code Online (Sandbox Code Playgroud)
到目前为止,我已经尝试了两件事:i)读取整个文件并使用.find(xmltag)和ii)使用lxml和iterparse()解析xml文件.第一个选择我已经让它工作了,但它很慢.第二种选择我没有设法让它开始.
这是我所拥有的一部分:
for event, element in etree.iterparse(path_to_file, tag="BlogPost"):
if element.tag == "BlogPost":
print element.text
else:
print 'Finished'
Run Code Online (Sandbox Code Playgroud)
结果只是空格,没有文字.
我必须做错事,但我无法理解.另外,如果它不够明显,我对python很新,这是我第一次使用lxml.请帮忙!
我一直在研究解析外部XML文件的代码.其中一些文件非常庞大,高达千兆字节的数据.毋庸置疑,这些文件需要作为流进行解析,因为将它们加载到内存中效率太低,并且经常导致OutOfMemory问题.
我使用了库miniDOM,ElementTree,cElementTree,我目前正在使用lxml.现在我有一个工作的,非常有效的内存脚本,使用lxml.etree.iterparse.问题是我需要解析的一些XML文件包含编码错误(它们通告为UTF-8,但包含不同编码的字符).使用lxml.etree.parse此功能时,可以使用recover=True自定义解析器选项进行修复,但iterparse不接受自定义解析器.(另见:这个问题)
我当前的代码如下所示:
from lxml import etree
events = ("start", "end")
context = etree.iterparse(xmlfile, events=events)
event, root_element = context.next() # <items>
for action, element in context:
if action == 'end' and element.tag == 'item':
# <parse>
root_element.clear()
Run Code Online (Sandbox Code Playgroud)
iterparse遇到错误字符时出错(在这种情况下,它是a ^Y):
lxml.etree.XMLSyntaxError: Input is not proper UTF-8, indicate encoding !
Bytes: 0x19 0x73 0x20 0x65, line 949490, column 25
Run Code Online (Sandbox Code Playgroud)
我甚至不想解码这些数据,我可以放弃它.不过,我不知道有什么办法跳过元素-我想context.next和continue中试/ except语句.
任何帮助,将不胜感激!
更新
一些额外的信息:这是iterparse失败的行:
<description><![CDATA:[musea de …
我想使用lxml解析HTML文档.我正在使用python 3.2.3和lxml 2.3.4(http://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml)
我正在使用etree.iterparse解析文档,但它返回以下运行时错误:
Traceback (most recent call last):
File "D:\Eclipse Projects\Python workspace\Crawler\crawler.py", line 12, in <module>
for event, elements in etree.iterparse(some_file_like):
File "iterparse.pxi", line 491, in lxml.etree.iterparse.__next__ (src/lxml\lxml.etree.c:98565)
File "iterparse.pxi", line 512, in lxml.etree.iterparse._read_more_events (src/lxml\lxml.etree.c:98768)
TypeError: reading file objects must return plain strings
Run Code Online (Sandbox Code Playgroud)
问题是:如何解决这个运行时错误?
非常感谢你.
这是代码:
from io import StringIO
from lxml import etree
some_file_like = StringIO("<root><a>data</a></root>")
for event, elements in etree.iterparse(some_file_like): #<-- Run-time error happens here
print("%s, %4s, %s" % (event, elements.tag, elements.text))
Run Code Online (Sandbox Code Playgroud) 我尝试使用XML minidom解析这个巨大的XML文档.虽然它在示例文件上工作正常,但在尝试处理真实文件时(约400 MB)它会阻塞系统.
我尝试从我的xml文件的codereview调整代码(它以流式方式处理数据而不是内存中加载),由于元素的嵌套特性,我无法隔离数据集.我之前处理过简单的XML文件,但不是像这样的内存密集型任务.
这是正确的方法吗?如何将清单和发布者ID与每本书相关联?这就是我计划最终将两个表联系起来的方式.
任何反馈都非常感谢.
是book.xml
<BookDatabase>
<BookHeader>
<Name>BookData</Name>
<BookUniverse>All</BookUniverse>
<AsOfDate>2010-05-02</AsOfDate>
<Version>1.1</Version>
</BookHeader>
<InventoryBody>
<Inventory ID="12">
<PublisherClass ID="34">
<Publisher>
<PublisherDetails>
<Name>Microsoft Press</Name>
<Type>Tech</Type>
<ID>7462</ID>
</PublisherDetails>
</Publisher>
</PublisherClass>
<BookList>
<Listing>
<BookListSummary>
<Date>2009-01-30</Date>
</BookListSummary>
<Book>
<BookDetail ID="67">
<BookName>Code Complete 2</BookName>
<Author>Steve McConnell</Author>
<Pages>960</Pages>
<ISBN>0735619670</ISBN>
</BookDetail>
<BookDetail ID="78">
<BookName>Application Architecture Guide 2</BookName>
<Author>Microsoft Team</Author>
<Pages>496</Pages>
<ISBN>073562710X</ISBN>
</BookDetail>
</Book>
</Listing>
</BookList>
</Inventory>
<Inventory ID="64">
<PublisherClass ID="154">
<Publisher>
<PublisherDetails>
<Name>O'Reilly Media</Name>
<Type>Tech</Type>
<ID>7484</ID>
</PublisherDetails>
</Publisher>
</PublisherClass>
<BookList>
<Listing>
<BookListSummary>
<Date>2009-03-30</Date> …Run Code Online (Sandbox Code Playgroud) from lxml import etree
import StringIO
data= StringIO.StringIO('<root xmlns="http://some.random.schema"><a>One</a><a>Two</a><a>Three</a></root>')
docs = etree.iterparse(data,tag='a')
a,b = docs.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "iterparse.pxi", line 478, in lxml.etree.iterparse.__next__ (src/lxml/lxml.etree.c:95348)
File "iterparse.pxi", line 534, in lxml.etree.iterparse._read_more_events (src/lxml/lxml.etree.c:95938)
StopIteration
Run Code Online (Sandbox Code Playgroud)
工作正常,直到我将命名空间添加到根节点.关于我可以做什么作为一种解决方法的任何想法,或者这样做的正确方法?由于文件很大,我需要被事件驱动.
我目前正在尝试迭代解析一个非常大的HTML文档(我知道.. yuck)以减少使用的内存量.我遇到的问题是我遇到了XML语法错误,例如:
lxml.etree.XMLSyntaxError: Attribute name redefined, line 134, column 59
这会导致一切停止.
有没有办法迭代解析HTML而不会窒息语法错误?
目前我正在从XML语法错误异常中提取行号,从文档中删除该行,然后重新启动该过程.看起来像一个非常恶心的解决方案.有没有更好的办法?
编辑:
这就是我目前正在做的事情:
context = etree.iterparse(tfile, events=('start', 'end'), html=True)
in_table = False
header_row = True
while context:
try:
event, el = context.next()
# do something
# remove old elements
while el.getprevious() is not None:
del el.getparent()[0]
except etree.XMLSyntaxError, e:
print e.msg
lineno = int(re.search(r'line (\d+),', e.msg).group(1))
remove_line(tfilename, lineno)
tfile = open(tfilename)
context = etree.iterparse(tfile, events=('start', 'end'), html=True)
except KeyError:
print 'oops keyerror'
Run Code Online (Sandbox Code Playgroud) filterous被使用 iterparse来解析简单的XML StringIO对象中一个单元测试.但是,在尝试访问该StringIO对象之后,Python将以" ValueError: I/O operation on closed file"消息退出.根据iterparse文档,"从lxml 2.3开始,.close()方法也将在错误情况下被调用,"但我没有收到任何错误消息或Exception来自iterparse.我的IO-foo显然没有达到速度,所以有人有建议吗?
命令和(希望)相关代码:
$ python2.6 setup.py test
Run Code Online (Sandbox Code Playgroud)
setup.py:
from setuptools import setup
from filterous import filterous as package
setup(
...
test_suite = 'tests.tests',
Run Code Online (Sandbox Code Playgroud)
测试/ tests.py:
from cStringIO import StringIO
import unittest
from filterous import filterous
XML = '''<posts tag="" total="3" ...'''
class TestSearch(unittest.TestCase):
def setUp(self):
self.xml = StringIO(XML)
self.result = StringIO()
...
def test_empty_tag_not(self):
"""Empty …Run Code Online (Sandbox Code Playgroud) 我正在使用 .xml 处理大型 xml 文件lxml.iterparse。这很有效,但随着我的文件最近变得更大,我发现 iterparse 行为填满了我的记忆。考虑以下代码,该代码写入一个包含 300000 个元素和 300000 个elem元素和 300000 个other_elem元素的文件:
els = ('<elem><subel1>{0}</subel1><subel2>{0}</subel2><subel3>{0}</subel3><subel4>{0}</subel4><subel5>{0}</subel5><subel6>{0}</subel6></elem>'.format(x) for x in range(300000))
other_els = ('<other_elem><subel1>{0}</subel1><subel2>{0}</subel2><subel3>{0}</subel3><subel4>{0}</subel4><subel5>{0}</subel5><subel6>{0}</subel6></other_elem>'.format(x) for x in range(300000))
with open('/tmp/test.xml', 'w') as fp:
fp.write('<root>\n')
fp.write('<elements>\n')
for el in els:
fp.write(el+'\n')
fp.write('</elements>\n')
fp.write('<other_elements>\n')
for el in other_els:
fp.write(el+'\n')
fp.write('</other_elements>\n')
fp.write('</root>\n')
Run Code Online (Sandbox Code Playgroud)
然后我使用以下内容仅解析elem(而不对它们做任何事情),同时不时打印内存使用情况:
from lxml import etree
import psutil
import os
process = psutil.Process(os.getpid())
gen = etree.iterparse('/tmp/test.xml', tag='elem')
elscount = 0
for ac,el in gen:
elscount …Run Code Online (Sandbox Code Playgroud)