Domanda

Voglio analizzare RSS scaricato con lxml, ma non so come gestire con 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)

Ma ottengo un errore:

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)
È stato utile?

Soluzione

Si deve probabilmente solo cercare di definire il carattere codifica come ultima risorsa, perché è chiaro che cosa la codifica si basa sul prologo XML (se non dal intestazioni HTTP.) In ogni caso, è necessario passare la codifica a etree.XMLParser a meno che non si desidera ignorare la codifica; Così sbarazzarsi del parametro encoding e dovrebbe funzionare.

Modifica: va bene, il problema sembra in realtà essere con lxml. I seguenti lavori, per qualsiasi motivo:

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

Altri suggerimenti

mi sono imbattuto in un problema simile, e si scopre questo non ha nulla a che fare con codifiche. Quello che sta succedendo è questo - lxml si sta gettando un errore di totalmente estranei. In questo caso, l'errore è che la funzione .parse aspetta un nome di file o URL, e non una stringa con i contenuti stesso. Tuttavia, quando si tenta di stampare l'errore, si soffoca in caratteri non-ASCII e spettacoli che completamente confondendo messaggio di errore. E 'molto spiacevole e le altre persone hanno commentato su questo tema qui:

https://mailman-mail5.webfaction.com/ Pipermail / lxml / 2009-febbraio / 004393.html

Per fortuna, la vostra è una soluzione molto semplice. Basta sostituire .parse con .fromstring e si dovrebbe essere completamente pronti per partire:

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)

appena testato questo sulla mia macchina e ha funzionato bene. Speranza che aiuta!

E 'spesso più facile ottenere la stringa caricata e risolto per la biblioteca lxml prima, e quindi chiamare fromstring su di esso, piuttosto che fare affidamento sulla funzione lxml.etree.parse () e la sua difficile da gestire le opzioni di codifica.

Questo particolare file RSS inizia con la dichiarazione di codifica, quindi tutto dovrebbe funzionare:

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

I seguenti spettacoli codice alcune delle diverse varianti che si possono applicare per rendere eTree parse per differenti codifiche. È anche possibile richiedere per scrivere le differenti codifiche troppo, che apparirà nelle intestazioni.

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)

Il codice può essere provato qui: http://scraperwiki.com/scrapers/lxml_and_encoding_declarations/edit/#

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top