BeautifulSoupは、まっすぐなUnicodeではなく、unicode + htmlシンボルを提供します。これはバグですか、誤解ですか?
-
08-07-2019 - |
質問
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://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!