首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何用BeautifulSoup正确解析UTF-8编码的HTML到Unicode字符串?

如何用BeautifulSoup正确解析UTF-8编码的HTML到Unicode字符串?
EN

Stack Overflow用户
提问于 2013-11-26 07:15:44
回答 2查看 99.7K关注 0票数 32

我正在运行一个Python程序,该程序获取一个UTF8编码的网页,并使用BeautifulSoup从HTML中提取一些文本。

但是,当我将此文本写入文件(或在控制台上打印它)时,它会以意外的编码写入。

示例程序:

代码语言:javascript
复制
import urllib2
from BeautifulSoup import BeautifulSoup

# Fetch URL
url = 'http://www.voxnow.de/'
request = urllib2.Request(url)
request.add_header('Accept-Encoding', 'utf-8')

# Response has UTF-8 charset header,
# and HTML body which is UTF-8 encoded
response = urllib2.urlopen(request)

# Parse with BeautifulSoup
soup = BeautifulSoup(response)

# Print title attribute of a <div> which uses umlauts (e.g. können)
print repr(soup.find('div', id='navbutton_account')['title'])

运行该命令会得到以下结果:

代码语言:javascript
复制
# u'Hier k\u0102\u015bnnen Sie sich kostenlos registrieren und / oder einloggen!'

但是我希望Python Unicode字符串将单词können中的ö呈现为\xf6

代码语言:javascript
复制
# u'Hier k\xf6bnnen Sie sich kostenlos registrieren und / oder einloggen!'

我尝试将'fromEncoding‘参数传递给BeautifulSoup,并尝试对response对象执行read()decode()操作,但要么没有区别,要么抛出错误。

使用命令curl www.voxnow.de | hexdump -C,我可以看到网页确实是针对ö字符进行了UTF-8编码(即,它包含0xc3 0xb6):

代码语言:javascript
复制
      20 74 69 74 6c 65 3d 22  48 69 65 72 20 6b c3 b6  | title="Hier k..|
      6e 6e 65 6e 20 53 69 65  20 73 69 63 68 20 6b 6f  |nnen Sie sich ko|
      73 74 65 6e 6c 6f 73 20  72 65 67 69 73 74 72 69  |stenlos registri|

我已经超出了我的Python能力的极限,所以我不知道如何进一步调试它。有什么建议吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-26 18:55:31

正如justhalf上面指出的,我的问题本质上是this question的副本。

HTML内容将自身报告为UTF-8编码,除了一两个非法的无效UTF-8字符之外,大多数情况下都是如此。

这显然混淆了BeautifulSoup正在使用哪种编码,以及在将内容传递给BeautifulSoup时尝试首先解码为UTF-8时的情况:

代码语言:javascript
复制
soup = BeautifulSoup(response.read().decode('utf-8'))

我会得到这样的错误:

代码语言:javascript
复制
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 186812-186813: 
                    invalid continuation byte

更仔细地查看输出,发现字符Ü的一个实例被错误地编码为无效的字节序列0xe3 0x9c,而不是正确的0xc3 0x9c

正如该问题的当前highest-rated answer所建议的那样,在解析时可以删除无效的UTF-8字符,以便只将有效数据传递给BeautifulSoup:

代码语言:javascript
复制
soup = BeautifulSoup(response.read().decode('utf-8', 'ignore'))
票数 37
EN

Stack Overflow用户

发布于 2013-11-26 07:35:46

将结果编码成utf-8似乎对我很有效:

代码语言:javascript
复制
print (soup.find('div', id='navbutton_account')['title']).encode('utf-8')

它产生了以下结果:

代码语言:javascript
复制
Hier können Sie sich kostenlos registrieren und / oder einloggen!
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20205455

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档