2009-03-10 8 views
5

Sto utilizzando BeautifulSoup per analizzare un sito Web. La pagina del sito web viene visualizzata correttamente nel mio browser:BeautifulSoup mi fornisce simboli unicode + html, piuttosto che unicode diritto. È un bug o un malinteso?

La relazione di Oxfam International intitolata "Fuorigioco! http://www.coopamerica.org/programs/responsibleshopper/company.cfm?id=271

In particolare, le virgolette singole e doppie osservano benissimo. Sembrano simboli html piuttosto che ascii, anche se stranamente quando guardo la fonte in FF3 sembrano essere normali ascii.

Purtroppo, quando ho raschiare ottengo qualcosa di simile

u'Oxfam Internazionale \ xe2 € ™ s rapporto intitolato \ xe2 € œOffside!

oops, voglio dire questo:

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

metadati della pagina indica la codifica 'iso-88.959-1'. Ho provato diverse codifiche, giocato con le funzioni di unicode-> ascii e html-> ascii di terze parti, e ho esaminato la discrepanza MS/iso-8859-1, ma il fatto è che ™ non ha nulla a che fare con un citazione singola, e non riesco a trasformare la combinazione unicode + htmlsymbol nel giusto simbolo ascii o html - nella mia conoscenza limitata, ed è per questo che cerco aiuto.

Sarei felice con una doppia citazione ASCII, "o"

Il problema seguente è che mi riguarda ci sono altri simboli divertenti decodificati in modo non corretto.

\xe2€™ 

seguito alcune pitone di riprodurre quello che sto vedendo, seguita dalle cose che ho provato.

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! 

EDIT:

Ho provato con un altro parser 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() 

che mi dà questa

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

migliore dei casi decodifica sembra darmi gli stessi risultati:

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

EDIT 2:

Sono in esecuzione Mac OS X 4 con FF 3.0.7 e Firebug

Python 2.5 (wow, non riesco a credere che non ha indicato questo fin dal principio)

+0

che cosa significa "oops voglio dire questo " significare? La tua chiave di backspace non funzionava? –

+0

@ S.Lott: c'è una chiave backspace in mac? – SilentGhost

+3

@SilentGhost: ce n'è uno in ciascuno dei miei mac. Il "oops intendo questo" è molto, molto irritante. Perché non backspace? Cosa c'è di così importante nel ripetere gli stessi personaggi in un markup diverso? È divertente"? –

risposta

8

Questo è uno seriamente incasinato pagina, codifica-saggio :-)

Non c'è niente sbagliato con il tuo approccio a tutti. Io probabilmente tendono a fare la conversione prima di passarlo al BeautifulSoup, solo perché sono persnickity:

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) 

In questo caso, meta tag della pagina giace circa la codifica. La pagina è in realtà in UTF-8 ... info page di Firefox rivela la codifica vera, e si può effettivamente vedere questo set di caratteri nelle intestazioni di risposta restituiti dal server:

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 

Se fate la decodifica usando 'utf -8' , funzionerà per voi (o, almeno, è fatto per me):

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 
+0

Grazie mille per la risposta informativa e gentile. Funziona davvero anche per me. –

4

in realtà è UTF-8 misencoded come CP1252:

>>> print u'Oxfam International\xe2€™s report entitled \xe2€œOffside!'.encode('cp1252').decode('utf8') 
Oxfam International’s report entitled “Offside! 
Problemi correlati