在Python中解析巨大的,编码错误的XML文件


问题内容

我一直在研究解析外部XML文件的代码。其中一些文件非常大,数据量高达千兆字节。不用说,这些文件需要解析为流,因为将它们加载到内存中效率太低,并且经常导致OutOfMemory问题。

我已经使用了miniDOM,ElementTree,cElementTree库,并且当前正在使用lxml。现在,我使用了一个有效的内存有效脚本lxml.etree.iterparse。问题在于,我需要解析的某些XML文件包含编码错误(它们以UTF-8广告,但包含不同编码的字符)。使用lxml.etree.parserecover=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()

iterparse遇到错误字符时发生错误(在本例中为^Y):

lxml.etree.XMLSyntaxError: Input is not proper UTF-8, indicate encoding !
Bytes: 0x19 0x73 0x20 0x65, line 949490, column 25

我什至不希望解码此数据,我可以删除它。但是我不知道跳过元素的任何方法-我尝试过context.nextcontinue在try /
except语句中。

任何帮助,将不胜感激!

更新资料

一些其他信息:这是iterparse失败的行:

<description><![CDATA:[musea de la photographie fonds mercator. Met meer dan 80.000 foto^Ys en 3 miljoen negatieven is het Muse de la...]]></description>

根据etree,错误发生在bytes处0x19 0x73 0x20 0x65
根据hexedit,19 73 20 65将其转换为ASCII .s e
.在此位置应为撇号(foto’s)。

我也发现了这个问题,但没有提供解决方案。


问题答案:

由于问题是由 非法
XML字符引起的,在这种情况下为0x19字节,因此我决定将其剥离。我在该网站上发现了以下正则表达式:

invalid_xml = re.compile(u'[\x00-\x08\x0B-\x0C\x0E-\x1F\x7F]')

我写了这段代码,在保存xml feed的同时删除了非法字节:

conn = urllib2.urlopen(xmlfeed)
xmlfile = open('output', 'w')

while True:
    data = conn.read(4096)
    if data:
        newdata, count = invalid_xml.subn('', data)
        if count > 0 :
            print 'Removed %s illegal characters from XML feed' % count
        xmlfile.write(newdata)

    else:
        break

xmlfile.close()