3

我已经为此奋斗了一个小时。我正在解析一个 XML 字符串iterparse。但是,数据没有正确编码,我不是它的提供者,所以我无法修复编码。

这是我得到的错误:

lxml.etree.XMLSyntaxError: line 8167: Input is not proper UTF-8, indicate encoding !
Bytes: 0xEA 0x76 0x65 0x73

我怎样才能简单地忽略此错误并继续解析?我不介意,如果一个字符没有正确保存,我只需要数据。

这是我尝试过的,全部来自互联网:

data = data.encode('UTF-8','ignore')
data = unicode(data,errors='ignore')
data = unicode(data.strip(codecs.BOM_UTF8), 'utf-8', errors='ignore')

编辑:
我无法显示 url,因为它是私有 API 并且涉及我的 API 密钥,但这是我获取数据的方式:

ur = urlopen(url)
data = ur.read()

导致问题的字符是: å,我猜ä&ö等也会破坏它。

这是我尝试解析它的部分:

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('title/text( )')

context = etree.iterparse(StringIO(data), tag='item')
fast_iter(context, process_element)

编辑 2:当我尝试在 PHP 中解析它时,就会发生
这种情况。澄清一下,F***ing Åmål 是一部戏剧电影=D

该文件以<?xml version="1.0" encoding="UTF-8" ?>

这是我从中得到的print repr(data[offset-10:offset+60])

ence des r\xeaves, La</title>\n\t\t<year>2006</year>\n\t\t<imdb>0354899</imdb>\n
4

5 回答 5

3

你说:

导致问题的字符是:å,

你怎么知道?你用什么看你的文字?

所以你不能发布 URL 和你的 API 密钥;如何读取数据,将其写入文件(以二进制模式)并发布?

当您在 Web 浏览器中打开该文件时,它会检测到什么编码?

至少,做到这一点

data.decode('utf8') # where data is what you get from ur.read()

这将产生一个异常,告诉您非 UTF-8 内容的字节偏移量。

然后这样做:

print repr(data[offset-10:offset+60])

并向我们​​展示结果。

假设编码实际上是cp1252和解码 lxml 错误消息中的字节:

>>> guff = "\xEA\x76\x65\x73"
>>> from unicodedata import name
>>> [name(c) for c in guff.decode('1252')]
['LATIN SMALL LETTER E WITH CIRCUMFLEX', 'LATIN SMALL LETTER V', 'LATIN SMALL LE
TTER E', 'LATIN SMALL LETTER S']
>>>

那么您是否看到 e-circumflex 后跟ves,或 a-ring 后跟ves,或 a-ring 后跟其他东西?

数据是否以类似的 XML 声明开头<?xml version="1.0" encoding="UTF-8"?>?如果不是,它从什么开始?

编码猜测/确认的线索:文本是用什么语言编写的?什么国家?

更新基于提供的进一步信息。

根据您在错误附近显示的片段,电影标题是“La science des rêves”(梦想的科学)。

有趣的是,PHP 如何在“F***ing Åmål”上作呕,但 Python 却扼杀了法国的梦想。你确定你做了同样的查询吗?

您应该提前告诉我们这是 IMDB,您会很快得到答案。

解决方案在传递datalxml解析器之前,请执行以下操作:

data = data.replace('encoding="UTF-8"', 'encoding="iso-8859-1"')

这是基于他们在其网站上声明的编码,但这也可能是一个谎言。在这种情况下,请尝试cp1252。这绝对不是 iso-8859-2

于 2012-02-11T23:14:23.153 回答
0

但是,数据没有正确编码,我不是它的提供者,所以我无法修复编码。

以某种方式编码。确定编码,并指定该编码,而不是 UTF-8 编码(因为那显然不是编码)。

于 2012-02-11T20:46:04.390 回答
0

Iterparse 允许您使用其关键字参数“编码”覆盖文档中的 xml 编码(请参阅https://lxml.de/api/lxml.etree.iterparse-class.html)。在上面的代码中,您还可以编写

context = etree.iterparse(StringIO(data), tag='item', encoding='iso-8859-1') 

处理文件中的所有欧洲字符。

于 2019-05-18T11:22:37.850 回答
-1

要在解析期间从错误中恢复,您可以使用recover选项(在这种情况下可能会忽略某些数据):

import urllib2
from lxml import etree

data = urllib2.urlopen(URL).read()
root = etree.fromstring(data, parser=etree.XMLParser(recover=True))
for item in root.iter('item'):
    # process item here

要覆盖文档编码,您可以使用:

parser=etree.XMLParser(encoding=ENCODING)

这是feedparser检测字符编码的方法(这不是微不足道的)。

于 2012-02-12T11:13:13.417 回答
-1

您可以使用带有“替换”的编码 - >>> unicode('\x80abc', errors='replace') 这样坏字符被替换为有效字符 - u'\ufffdabc'

于 2012-02-11T18:51:20.050 回答