Question

Je veux analyser téléchargé RSS avec lxml, mais je ne sais pas comment gérer avec 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)

Mais je reçois une erreur:

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)
Était-ce utile?

La solution

Vous devriez probablement seulement essayer de définir le codage de caractères en dernier recours, car il est clair que le codage est basé sur le Prolog XML (sinon par les en-têtes HTTP.) Quoi qu'il en soit, il est inutile de passer le codage à etree.XMLParser sauf si vous voulez remplacer l'encodage; donc se débarrasser du paramètre encoding et il devrait fonctionner.

Edit: d'accord, le problème semble effectivement être avec lxml. Les travaux suivants, pour une raison quelconque:

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

Autres conseils

je suis tombé sur un problème similaire, et il se trouve que cela n'a rien à voir avec encodages. Ce qui se passe est ce - lxml est vous lancer une erreur tout à fait sans rapport. Dans ce cas, l'erreur est que la fonction .parse attend un nom de fichier ou l'URL, et non une chaîne avec le contenu lui-même. Cependant, quand il essaie d'imprimer l'erreur, il étrangle sur les caractères non-ascii et montre que confusion complètement message d'erreur. Il est très regrettable et d'autres personnes ont fait des commentaires sur cette question ici:

https://mailman-mail5.webfaction.com/ pipermail / lxml / 2009-Février / 004393.html

Heureusement, la vôtre est une solution très facile. Il suffit de remplacer .parse avec .fromstring et vous devriez être tout à fait bon pour aller:

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)

Il suffit de tester cela sur ma machine et il a bien fonctionné. Espérons que cela aide!

Il est souvent plus facile d'obtenir la chaîne chargée et triée pour la bibliothèque lxml d'abord, puis appeler fromstring sur elle, plutôt que de compter sur la fonction lxml.etree.parse () et il est difficile de gérer options d'encodage.

Ce fichier particulier rss commence par la déclaration de codage, donc tout devrait fonctionner:

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

Le code suivant montre certaines des différentes variations que vous pouvez appliquer pour faire etree Parse pour encodages différents. Vous pouvez également demander à écrire différents encodages aussi, qui apparaîtra dans les en-têtes.

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)

Le code peut être jugé ici: http://scraperwiki.com/scrapers/lxml_and_encoding_declarations/edit/#

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top