【问题标题】:BeautifulSoup gives me unicode+html symbols, rather than straight up unicode. Is this a bug or misunderstanding?BeautifulSoup 给了我 unicode+html 符号,而不是直接的 unicode。这是错误还是误解?
【发布时间】:2010-10-12 09:56:43
【问题描述】:

我正在使用 BeautifulSoup 来抓取网站。该网站的页面在我的浏览器中呈现良好:

国际乐施会题为“越位! http://www.coopamerica.org/programs/responsibleshopper/company.cfm?id=271

特别是单引号和双引号看起来不错。它们看起来是 html 符号而不是 ascii,但奇怪的是,当我在 FF3 中查看源代码时,它们似乎是正常的 ascii。

不幸的是,当我刮擦时,我得到了这样的东西

u'Oxfam International\xe2€™ 的报告 题为\xe2€œ越位!

哎呀,我的意思是:

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

页面的元数据表示“iso-88959-1”编码。我尝试了不同的编码,使用了 unicode->ascii 和 html->ascii 第三方函数,并查看了 MS/iso-8859-1 的差异,但事实是 ™ 与单引号,而且我似乎无法将 unicode+htmlsymbol 组合转换为正确的 ascii 或 html 符号——据我所知,这就是我寻求帮助的原因。

我很乐意使用 ascii 双引号," 或 "

以下问题是我担心还有其他有趣的符号解码不正确。

\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:

我正在运行带有 FF 3.0.7 和 Firebug 的 Mac OS X 4

Python 2.5(哇,不敢相信我没有从一开始就说明这一点)

【问题讨论】:

  • “哎呀,我的意思是这个”是什么意思?你的退格键没有用吗?
  • @S.Lott: mac 中有退格键吗?
  • @SilentGhost:我的每台 Mac 上都有一个。 “哎呀,我的意思是这个”非常非常令人恼火。为什么不退格?在不同的标记中重复相同的字符有什么重要的?是不是“好笑”?
  • 那是个意外。第一个是块引用,第二个是代码。我认为其中一个可能会显示我写的实际文本而不是渲染符号。 (我认为代码在预览中是这样做的;看到您的评论后发现它看起来一样,我很惊讶。没必要生气)

标签: python html unicode beautifulsoup


【解决方案1】:

实际上是 UTF-8 错误编码为 CP1252:

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

【讨论】:

    【解决方案2】:

    这是一个严重混乱的页面,编码方式:-)

    您的方法完全没有问题。我可能倾向于在将其传递给 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
    

    【讨论】:

    • 非常感谢您提供信息丰富且温和的回复。它也确实对我有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2014-10-18
    • 2012-05-20
    • 2018-01-09
    • 1970-01-01
    • 1970-01-01
    • 2014-11-22
    相关资源
    最近更新 更多