2011-04-27 4 views
9

Deseo analizar el RSS descargado con lxml, pero no sé cómo manejarlo con UnicodeDecodeError?Error de codificación al analizar RSS con lxml

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) 

Pero me da un error:

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) 

Respuesta

0

Sólo debe probablemente esté tratando de definir la codificación de caracteres, como último recurso, ya que está claro cuál es la codificación se basa en el prólogo XML (si no por los encabezados HTTP.) De todos modos, no es necesario pasar la codificación a etree.XMLParser a menos que desee sobrescribir la codificación; así que deshazte del parámetro encoding y debería funcionar.

Editar: bien, el problema en realidad parece ser con lxml. Las siguientes obras, por cualquier razón:

parser = etree.XMLParser(ns_clean=True, recover=True) 
etree.parse('http://wiadomosci.onet.pl/kraj/rss.xml', parser) 
+0

Todavía hay el mismo error cuando ejecuto el script sin el parámetro de codificación ...; /. ¿Por qué etree.XMLParser termina con un error a pesar de pasar la codificación correcta? – domi

+1

Está funcionando ahora, pero tuve que actualizar lxml a la versión 2.2.8, porque con 2.2.4 no pude analizar la URL remota. Además, el código de mi pregunta funciona cuando cambio esto: tree = etree.parse (StringIO.StringIO (response), parser) – domi

4

A menudo es más fácil obtener la cadena de carga y se solucionó para la biblioteca lxml primero, y luego llamar fromstring en él, en lugar de confiar en la lxml.etree.parse () función y es difícil de administrar las opciones de codificación.

Este archivo RSS en particular comienza con la declaración de codificación, así que todo debería funcionar simplemente:

<?xml version="1.0" encoding="utf-8"?> 

El código siguiente muestra algunas de las diferentes variaciones que se pueden aplicar para hacer análisis sintáctico etree para diferentes codificaciones. También puede solicitar que escriba diferentes codificaciones, que aparecerán en los encabezados.

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&#347;ci...'] 

lres = lxml.etree.tostring(tree, encoding="latin1") 
print [lres] 
     # ["<?xml version='1.0' encoding='latin1'?>\n<feed xmlns=...<title>Wiadomo&#347;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) 

Código puede ser juzgado aquí: http://scraperwiki.com/scrapers/lxml_and_encoding_declarations/edit/#

44

me encontré con un problema similar, y resulta que esto no tiene nada que ver con las codificaciones. Lo que está sucediendo es esto: lxml te arroja un error totalmente diferente. En este caso, el error es que la función .parse espera un nombre de archivo o URL, y no una cadena con los contenidos en sí. Sin embargo, cuando intenta imprimir el error, se ahoga en caracteres que no son ASCII y muestra un mensaje de error completamente confuso. Es muy desafortunado y otras personas han comentado sobre este tema aquí:

https://mailman-mail5.webfaction.com/pipermail/lxml/2009-February/004393.html

Por suerte, la suya es una solución muy fácil. Basta con sustituir .parse con .fromstring y que debe estar totalmente bueno para ir:

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) 

simplemente probado esto en mi máquina y funcionó bien. ¡Espero eso ayude!

+0

parse() -> fromstring() hizo el truco para mí. ¡Gracias! –

+8

¡QUE SUS DÍAS SEAN BENDECIDOS CON LA BELLEZA ETERNA Y LA ARMONÍA SIR! – Art

+0

me salvaste probablemente una hora de locura, gracias – mottalrd

Cuestiones relacionadas