BeautifulSoup me donne des symboles unicode + html, plutôt qu'unicode direct. Est-ce un bug ou un malentendu?

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

Question

J'utilise BeautifulSoup pour gratter un site Web. La page du site Web s'affiche bien dans mon navigateur:

  Le rapport d'Oxfam International intitulé "Hors jeu!"    http://www.coopamerica.org/programs/responsibleshopper/company.cfm ? id = 271

En particulier, les guillemets simples et doubles ont bonne apparence. Ils ressemblent à des symboles html plutôt qu’ascii, bien qu’étonnamment, lorsque je visualise la source dans FF3, ils semblent être des caractères ascii normaux.

Malheureusement, lorsque je gratte, je reçois quelque chose comme ça

  Rapport de

u'Oxfam International \ xe2 & # 8364; & # 8482;   intitulé \ xe2 & # 8364; & # 339; Hors jeu!

oups, je veux dire ceci:

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

Les métadonnées de la page indiquent un codage «iso-88959-1». J'ai essayé différents encodages, joué avec les fonctions tierces de l'unicode, ascii et html, et ascii, et examiné la divergence MS / iso-8859-1, mais le fait est que & # 8482; n’a rien à voir avec une seule citation et je n'arrive pas à transformer le combo unicode + htmlsymbol en symbole ascii ou html de droite - à ma connaissance, c’est pourquoi je cherche de l’aide.

Je serais heureux avec une double citation ASCII, " ou "

Le problème suivant est que je crains que d’autres symboles amusants ne soient décodés correctement.

\xe2€™

Ci-dessous, un peu de python pour reproduire ce que je vois, suivi des choses que j'ai essayées.

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!

EDIT:

J'ai essayé d'utiliser un analyseur syntaxique BS différent:

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()

qui me donne cette

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

le meilleur cas de décodage semble me donner les mêmes résultats:

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

EDIT 2:

J'utilise Mac OS X 4 avec FF 3.0.7 et Firebug

Python 2.5 (wow, je ne peux pas croire que je ne l'ai pas dit depuis le début)

Était-ce utile?

La solution

C’est une page sérieusement gâchée en codage: -)

Il n’ya rien de vraiment faux avec votre approche. J'aurais probablement tendance à faire la conversion avant de la passer à BeautifulSoup, simplement parce que je suis perspicace:

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)

Dans ce cas, la balise meta de la page ment au sujet de l'encodage. La page est actuellement en utf-8 ... Les informations sur la page de Firefox révèlent le codage réel, et vous pouvez réellement voir ce jeu de caractères dans les en-têtes de réponse renvoyés par le serveur:

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 vous faites le décodage à l'aide de 'utf-8', cela fonctionnera pour vous (ou du moins, c'est fait pour moi):

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

Autres conseils

C’est en fait le code UTF-8 mal codé en tant que CP1252:

>>> print u'Oxfam International\xe2€™s report entitled \xe2€œOffside!'.encode('cp1252').decode('utf8')
Oxfam International’s report entitled “Offside!
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top