Ошибка кодирования при анализе RSS с LXML
-
25-10-2019 - |
Вопрос
Я хочу анализировать скачание RSS с LXML, но я не знаю, как справиться с UnicoDedeCodeError?
request = urllib2.Request('http://wiadomosci.onet.pl/kraj/rss.xml')
response = urllib2.urlopen(request)
response = response.read()
encd = chardet.detect(response)['encoding']
parser = etree.XMLParser(ns_clean=True,recover=True,encoding=encd)
tree = etree.parse(response, parser)
Но я получаю ошибку:
tree = etree.parse(response, parser)
File "lxml.etree.pyx", line 2692, in lxml.etree.parse (src/lxml/lxml.etree.c:49594)
File "parser.pxi", line 1500, in lxml.etree._parseDocument (src/lxml/lxml.etree.c:71364)
File "parser.pxi", line 1529, in lxml.etree._parseDocumentFromURL (src/lxml/lxml.etree.c:71647)
File "parser.pxi", line 1429, in lxml.etree._parseDocFromFile (src/lxml/lxml.etree.c:70742)
File "parser.pxi", line 975, in lxml.etree._BaseParser._parseDocFromFile (src/lxml/lxml.etree.c:67
740)
File "parser.pxi", line 539, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etr
ee.c:63824)
File "parser.pxi", line 625, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:64745)
File "parser.pxi", line 559, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:64027)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc5 in position 97: ordinal not in range(128)
Решение
Вы, вероятно, должны только попытаться определить кодировку персонажа как последнее средство, так как ясно, что кодирование основано на XML -прологе (если не на заголовках HTTP). В любом случае, не нужно передавать кодирование etree.XMLParser
Если вы не хотите переопределить кодирование; Так что избавьтесь от encoding
параметр, и он должен работать.
РЕДАКТИРОВАТЬ: Хорошо, проблема на самом деле, кажется, с lxml
. Анкет Следующее работает по какой -либо причине:
parser = etree.XMLParser(ns_clean=True, recover=True)
etree.parse('http://wiadomosci.onet.pl/kraj/rss.xml', parser)
Другие советы
Я столкнулся с аналогичной проблемой, и оказывается, что это не имеет ничего общего с кодировками. Что происходит, так это это - LXML бросает вам совершенно не связанную с ошибкой. В этом случае ошибка состоит в том, что функция .parse ожидает имя файла или URL, а не строку с самим содержимым. Однако, когда он пытается распечатать ошибку, она задыхается от символов, не являющихся символами, и показывает, что совершенно запутанное сообщение об ошибке. Это очень прискорбно, и другие люди прокомментировали этот вопрос здесь:
https://mailman-mail5.webfaction.com/pipermail/lxml/2009-february/004393.html
К счастью, у вас очень простое исправление. Просто замените .parse на.
request = urllib2.Request('http://wiadomosci.onet.pl/kraj/rss.xml')
response = urllib2.urlopen(request)
response = response.read()
encd = chardet.detect(response)['encoding']
parser = etree.XMLParser(ns_clean=True,recover=True,encoding=encd)
## lxml Y U NO MAKE SENSE!!!
tree = etree.fromstring(response, parser)
Только что проверил это на моей машине, и это работало нормально. Надеюсь, поможет!
Часто сначала легче заправить строку и разобраться для библиотеки LXML, а затем вызовать его, а не полагаться на функцию lxml.etree.parse () и ее трудно управлять параметрами кодирования.
Этот конкретный файл RSS начинается с объявления кодирования, поэтому все должно просто работать:
<?xml version="1.0" encoding="utf-8"?>
В следующем коде показаны некоторые из различных вариаций, которые вы можете применить, чтобы сделать Etree Parse для различных кодировки. Вы также можете попросить его написать разные кодировки, которые появятся в заголовках.
import lxml.etree
import urllib2
request = urllib2.Request('http://wiadomosci.onet.pl/kraj/rss.xml')
response = urllib2.urlopen(request).read()
print [response]
# ['<?xml version="1.0" encoding="utf-8"?>\n<feed xmlns=... <title>Wiadomo\xc5\x9bci...']
uresponse = response.decode("utf8")
print [uresponse]
# [u'<?xml version="1.0" encoding="utf-8"?>\n<feed xmlns=... <title>Wiadomo\u015bci...']
tree = lxml.etree.fromstring(response)
res = lxml.etree.tostring(tree)
print [res]
# ['<feed xmlns="http://www.w3.org/2005/Atom">\n<title>Wiadomości...']
lres = lxml.etree.tostring(tree, encoding="latin1")
print [lres]
# ["<?xml version='1.0' encoding='latin1'?>\n<feed xmlns=...<title>Wiadomości...']
# works because the 38 character encoding declaration is sliced off
print lxml.etree.fromstring(uresponse[38:])
# throws ValueError(u'Unicode strings with encoding declaration are not supported.',)
print lxml.etree.fromstring(uresponse)
Код можно попробовать здесь: http://scraperwiki.com/scrapers/lxml_and_encoding_declarations/edit/#