我一直在和这个战斗一个小时了。我正在使用iterparse
解析XML字符串。但是,数据编码不正确,我不是它的提供者,所以我无法修复编码。
这是我得到的错误:
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')
修改
我无法显示网址,因为它是私有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中解析它时,会发生This。只是为了澄清,F ***ingÅmål是drama movie = 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
答案 0 :(得分:3)
你说:
导致问题的角色是:å,
你怎么知道的?你在看什么文字?
因此您无法发布网址和API密钥;如何读取数据,将其写入文件(以二进制模式),然后发布?
当您在网络浏览器中打开该文件时,它会检测到哪种编码?
至少,这样做
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 version="1.0" encoding="UTF-8"?>
之类的XML声明开头?如果没有,它从什么开始?
猜测/确认编码的线索:写入的文字是什么语言?什么国家?
根据提供的更多信息更新。
根据你在错误附近展示的片段,电影标题是“La sciencedesrêves”(梦的科学)。
有趣的是PHP如何对“F ***ingÅmål”嗤之以鼻,但Python对法国梦的扼杀。你确定你做了同样的查询吗?
你应该事先告诉我们它是IMDB,你会更早得到答案。
在将data
传递给lxml
解析器之前,解决方案,请执行以下操作:
data = data.replace('encoding="UTF-8"', 'encoding="iso-8859-1"')
这是基于他们在网站上声明的编码,但这也可能是谎言。在这种情况下,请尝试使用cp1252
。这肯定是而不是iso-8859-2 。
答案 1 :(得分:0)
但是,数据编码不正确,我不是它的提供者,所以我无法修复编码。
编码以某种方式。确定编码,并指定编码,而不是UTF-8编码(因为这显然不是编码)。
答案 2 :(得分:0)
Iterparse允许您使用其关键字参数“ encoding”覆盖文档中的xml编码(请参见https://lxml.de/api/lxml.etree.iterparse-class.html)。 在上面的代码中,您还可以编写
context = etree.iterparse(StringIO(data), tag='item', encoding='iso-8859-1')
处理文件中的所有欧洲字符。
答案 3 :(得分:-1)
你可以使用'replace'编码 -
>>> unicode('\x80abc', errors='replace')
这样,坏的角色被有效的角色取代 -
u'\ufffdabc'
答案 4 :(得分:-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
detects character encoding的方式(这不是一件小事)。