Frage

Ich möchte heruntergeladene RSS mit LXML analysieren, aber ich weiß nicht, wie ich mit UnicodEdeCodeError umgehen soll?

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)

Aber ich bekomme einen Fehler:

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)
War es hilfreich?

Lösung

Sie sollten wahrscheinlich nur versuchen, die Charaktercodierung als letztes Mittel zu definieren, da klar ist, was die Codierung auf dem XML -Prolog basiert (wenn nicht von den HTTP -Headern). etree.XMLParser Es sei denn, Sie möchten die Codierung außer Kraft setzen; Also räumen Sie das los encoding Parameter und es sollte funktionieren.

Bearbeiten: Okay, das Problem scheint tatsächlich mit zu sein lxml. Das folgende funktioniert aus irgendeinem Grund:

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

Andere Tipps

Ich bin auf ein ähnliches Problem gestoßen, und es stellt sich heraus, dass dies nichts mit Codings zu tun hat. Was passiert ist, ist dies - LXML wirft Ihnen einen völlig unabhängigen Fehler. In diesem Fall ist der Fehler, dass die .Parse -Funktion einen Dateinamen oder eine URL und keine Zeichenfolge mit dem Inhalt selbst erwartet. Wenn es jedoch versucht, den Fehler auszudrucken, erstickt er nicht-ASCII-Zeichen und zeigt diese völlig verwirrende Fehlermeldung an. Es ist sehr unglücklich und andere Leute haben hier zu diesem Thema kommentiert:

https://mailman-ymail55.webfaction.com/pipermail/lxml/2009-february/004393.html

Glücklicherweise ist Ihre eine sehr einfache Lösung. Ersetzen Sie einfach .Parse durch .fromstring und Sie sollten völlig gut sein:

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)

Ich habe dies gerade auf meiner Maschine getestet und es hat gut funktioniert. Ich hoffe es hilft!

Es ist oft einfacher, zuerst die Zeichenfolge zu laden und für die LXML -Bibliothek zu sortieren, und dann nicht auf die Funktion lxml.etree.Parse () aufzurufen, und es ist schwierig, Codierungsoptionen zu verwalten.

Diese spezielle RSS -Datei beginnt mit der Codierungserklärung, sodass alles nur funktionieren sollte:

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

Der folgende Code zeigt einige der unterschiedlichen Variationen, die Sie anwenden können, um ETREE -Analyse für verschiedene Kodierungen zu machen. Sie können es auch auffordern, verschiedene Encodings zu schreiben, die in den Headers angezeigt werden.

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)

Der Code kann hier ausprobiert werden: http://scraperwiki.com/scrapers/lxml_and_encoding_declarations/edit/#

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top