2009-03-10 10 views
5

Estoy usando BeautifulSoup para raspar un sitio web. La página del sitio web funciona bien en mi navegador:BeautifulSoup me da símbolos unicode + html, en lugar de unicode directo. ¿Es esto un error o un malentendido?

El informe de Oxfam International titulado "Fuera de juego! http://www.coopamerica.org/programs/responsibleshopper/company.cfm?id=271

En particular, las comillas simples y dobles se ven bien. Miran símbolos html en lugar de ascii, aunque extrañamente cuando veo fuente en FF3 parecen ser ascii normales.

Por desgracia, cuando raspo me sale algo como esto

u'Oxfam Internacional \ reporte € ™ s XE2 titulado \ XE2 € œOffside!

perdón, quiero decir esto:

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

meta datos de la página indica la codificación 'iso-88959-1'. Probé diferentes codificaciones, jugué con funciones de unicode-> ascii y html-> ascii de terceros, y miré la discrepancia MS/iso-8859-1, pero el hecho es que ™ no tiene nada que ver con una comillas simples, y parece que no puedo convertir el combo Unicode + htmlsymbol en el símbolo ascii o html correcto, en mi limitado conocimiento, por lo que busco ayuda.

estaría feliz con una doble comilla ASCII "o"

El problema siguiente es que a mí respecta, hay otros símbolos divertidos decodificados incorrectamente.

\xe2€™ 

A continuación se muestra un pitón para reproducir lo que estoy viendo, seguido de las cosas que he intentado.

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:

He intentado usar un analizador diferente 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() 

que me da este

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

la mejor decodificación caso me parece dar los mismos resultados:

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

EDITAR 2:

Estoy ejecutando Mac OS X 4 con FF 3.0.7 y Firebug

Python 2.5 (wow, no puedo creer que no declaró esto desde el principio)

+0

¿Qué significa "Uy me refiero a esto "¿significa? ¿Tu tecla de retroceso no funcionó? –

+0

@ S.Lott: ¿hay una tecla de retroceso en mac? – SilentGhost

+3

@SilentGhost: hay uno en cada uno de mis Mac. El "¡Uy, quiero decir esto!" Es muy, muy irritante. ¿Por qué no retroceder? ¿Qué tiene de importante repetir los mismos personajes en un marcado diferente? Es gracioso"? –

Respuesta

8

Esa es una en mal estado seriamente página, :-) codificación en cuanto

No hay nada realmente mal con su enfoque en absoluto. Yo probablemente tienden a hacer la conversión antes de pasarla a BeautifulSoup, sólo porque soy 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) 

En este caso, la etiqueta meta de la página está mintiendo acerca de la codificación. La página está en realidad en UTF-8 ... información de la página de Firefox revela la codificación real, y en realidad se puede ver este juego de caracteres en las cabeceras de respuesta devueltos por el servidor:

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 

Si lo hace la decodificación usando 'utf -8' , va a trabajar para usted (o, al menos, es no para mí):

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

Muchas gracias por la respuesta informativa y gentil. De hecho, también funciona para mí. –

4

de hecho, es UTF-8 misencoded como CP1252:

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