Игнорировать ошибки кодирования в Python (iterparse)? - PullRequest
3 голосов
/ 11 февраля 2012

Я боролся с этим уже час.Я анализирую 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

Ответы [ 5 ]

3 голосов
/ 12 февраля 2012

Вы говорите:

Символ, вызывающий проблему: å,

Откуда ты это знаешь? С чем вы просматриваете текст?

Таким образом, вы не можете опубликовать URL и ваш ключ 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']
>>>

Значит, вы видите электронный круг с последующим 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, вы бы получили ответ намного раньше.

РЕШЕНИЕ перед тем как передать data парсеру lxml, сделайте следующее:

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

Это основано на кодировке, которую они объявляют на своем сайте, но это тоже может быть ложью. В этом случае попробуйте cp1252. Это определенно не iso-8859-2 .

0 голосов
/ 18 мая 2019

Iterparse позволяет вам переопределить кодировки xml в документе, используя его ключевое слово-аргумент «кодировка» (см. https://lxml.de/api/lxml.etree.iterparse-class.html).. В приведенном выше коде вы также можете написать

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

для решениявсе европейские символы в файле.

0 голосов
/ 12 февраля 2012

Чтобы исправить ошибки во время синтаксического анализа, вы можете использовать опцию 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 определяет кодировку символов (это не тривиально).

0 голосов
/ 12 февраля 2012

Однако данные не закодированы должным образом, и я не являюсь их поставщиком, поэтому не могу исправить кодировку.

Они закодированы каким-то образом .Определите кодировку и укажите эту кодировку вместо кодировки UTF-8 (поскольку это, очевидно, не кодировка).

0 голосов
/ 11 февраля 2012

Вы можете использовать закодировать с «заменить» - >>> unicode('\x80abc', errors='replace') таким образом, плохой символ заменяется действительным - u'\ufffdabc'

...