質問

ダウンロードした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を期待することです。ただし、エラーを印刷しようとすると、ASCII以外の文字を窒息させ、完全に混乱するエラーメッセージが表示されます。それは非常に不幸であり、他の人々はここでこの問題についてコメントしています:

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

幸いなことに、あなたはとても簡単な修正です。 .Parseを.Fromstringに置き換えるだけで、あなたは完全に行くのが良いはずです:

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.etree.parse()関数に依存し、エンコードオプションを管理するのが難しい場合ではなく、最初に文字列をロードしてソートすることができ、次にfromStringを呼び出します。

この特定のRSSファイルは、エンコード宣言から始まるため、すべてが機能するはずです。

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

次のコードは、さまざまなエンコーディングのためにetreeを作成するために適用できるさまざまなバリエーションの一部を示しています。また、ヘッダーに表示されるさまざまなエンコーディングも書き出すようにリクエストすることもできます。

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)

ここでコードを試すことができます: http://scraperwiki.com/scrapers/lxml_and_encoding_declarations/edit/#

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top