BeautifulSoupは、まっすぐなUnicodeではなく、unicode + htmlシンボルを提供します。これはバグですか、誤解ですか?

StackOverflow https://stackoverflow.com/questions/629999

質問

BeautifulSoupを使用してWebサイトをスクレイピングしています。ウェブサイトのページはブラウザで正常にレンダリングされます:

  

Oxfam Internationalの“ Offside!というレポート    http://www.coopamerica.org/programs/responsibleshopper/company.cfm ?id = 271

特に、一重引用符と二重引用符は適切に見えます。アスキーではなくHTMLシンボルに見えますが、FF3でソースを表示すると奇妙なことに、通常のアスキーに見えます。

残念ながら、こすったとき、私はこのようなものを得ます

  

u'Oxfam International \ xe2€™のレポート   \ xe2€œ Offside!というタイトルです

おっと、これは:

u'Oxfam International\xe2€™s report entitled \xe2€œOffside!

ページのメタデータは「iso-88959-1」エンコーディングを示しています。私はさまざまなエンコーディングを試し、unicode-> asciiとhtml-> asciiのサードパーティ関数で遊んで、MS / iso-8859-1の不一致を調べましたが、問題の事実は™単一引用符とは何の関係もないし、unicode + htmlsymbolコンボを正しいasciiやhtmlシンボルに変えることはできないようだ-私の限られた知識では、だからこそ私は助けを求めている。

アスキーの二重引用符"に満足します。または"

以下の問題は、間違ってデコードされた他の面白いシンボルがあることを心配していることです。

\xe2€™

以下は、私が見ているものを再現するためのpythonです。次に、試したことを示します。

import twill
from twill import get_browser
from twill.commands import go

from BeautifulSoup import BeautifulSoup as BSoup

url = 'http://www.coopamerica.org/programs/responsibleshopper/company.cfm?id=271'
twill.commands.go(url)
soup = BSoup(twill.commands.get_browser().get_html())
ps = soup.body("p")
p = ps[52]

>>> p         
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe2' in position 22: ordinal not in range(128)

>>> p.string
u'Oxfam International\xe2€™s report entitled \xe2€œOffside!<elided>\r\n'

http://groups.google.com/group/comp.lang.python/browse_frm/thread/9b7bb3f621b4b8e4/3b00a890cf3a5e46?q=htmlentitydefs&rnum=3&hl=en#3b00a890cf3a5e46

http://www.fourmilab.ch/webtools/demoroniser/

http://www.crummy.com/software/BeautifulSoup/documentation.html

http://www.cs.tut.fi/~ jkorpela / www / windows-chars.html

>>> AsciiDammit.asciiDammit(p.decode())
u'<p>Oxfam International\xe2€™s report entitled \xe2€œOffside!

>>> handle_html_entities(p.decode())
u'<p>Oxfam International\xe2\u20ac\u2122s report entitled \xe2\u20ac\u0153Offside! 

>>> unicodedata.normalize('NFKC', p.decode()).encode('ascii','ignore')
'<p>Oxfam International€™s report entitled €œOffside!

>>> htmlStripEscapes(p.string)
u'Oxfam International\xe2TMs report entitled \xe2Offside!

編集:

別のBSパーサーを使用してみました:

import html5lib
bsoup_parser = html5lib.HTMLParser(tree=html5lib.treebuilders.getTreeBuilder("beautifulsoup"))
soup = bsoup_parser.parse(twill.commands.get_browser().get_html())
ps = soup.body("p")
ps[55].decode()

これは私にこれを与える

u'<p>Oxfam International\xe2\u20ac\u2122s report entitled \xe2\u20ac\u0153Offside!

ベストケースのデコードでも同じ結果が得られるようです:

unicodedata.normalize('NFKC', p.decode()).encode('ascii','ignore')
'<p>Oxfam InternationalTMs report entitled Offside! 

編集2:

Mac OS X 4でFF 3.0.7とFirebugを実行しています

Python 2.5(うわー、最初からこれを述べていなかったとは信じられない)

役に立ちましたか?

解決

それは、エンコードに関して賢明に台無しにされたページです:-)

あなたのアプローチにまったく問題はありません。たぶん、私が頑固だからといって、BeautifulSoupに渡す前に変換を行う傾向があるでしょう:

import urllib
html = urllib.urlopen('http://www.coopamerica.org/programs/responsibleshopper/company.cfm?id=271').read()
h = html.decode('iso-8859-1')
soup = BeautifulSoup(h)

この場合、ページのメタタグはエンコーディングに関するものです。ページは実際にはutf-8です。Firefoxのページ情報は実際のエンコーディングを示しており、サーバーから返される応答ヘッダーでこの文字セットを実際に確認できます。

curl -i http://www.coopamerica.org/programs/responsibleshopper/company.cfm?id=271
HTTP/1.1 200 OK
Connection: close
Date: Tue, 10 Mar 2009 13:14:29 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Set-Cookie: COMPANYID=271;path=/
Content-Language: en-US
Content-Type: text/html; charset=UTF-8

'utf-8'を使用してデコードを行う場合、それはあなたのために機能します(または、少なくとも、私のためにされました):

import urllib
html = urllib.urlopen('http://www.coopamerica.org/programs/responsibleshopper/company.cfm?id=271').read()
h = html.decode('utf-8')
soup = BeautifulSoup(h)
ps = soup.body("p")
p = ps[52]
print p

他のヒント

実際には、CP1252として誤ってエンコードされたUTF-8:

>>> print u'Oxfam International\xe2€™s report entitled \xe2€œOffside!'.encode('cp1252').decode('utf8')
Oxfam International’s report entitled “Offside!
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top