如何使用 BeautifulSoup 将 UTF-8 编码的 HTML 正确解析为 Unicode 字符串? [复制]
Posted
技术标签:
【中文标题】如何使用 BeautifulSoup 将 UTF-8 编码的 HTML 正确解析为 Unicode 字符串? [复制]【英文标题】:How to correctly parse UTF-8 encoded HTML to Unicode strings with BeautifulSoup? [duplicate] 【发布时间】:2013-12-10 21:50:28 【问题描述】:我正在运行一个获取 UTF-8 编码网页的 Python 程序,并使用 BeautifulSoup 从 html 中提取一些文本。
但是,当我将此文本写入文件(或在控制台上打印)时,它会以意外的编码写入。
示例程序:
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'])
运行它会给出结果:
# u'Hier k\u0102\u015bnnen Sie sich kostenlos registrieren und / oder einloggen!'
但我希望 Python Unicode 字符串将单词 können
中的 ö
呈现为 \xf6
:
# u'Hier k\xf6bnnen Sie sich kostenlos registrieren und / oder einloggen!'
我尝试将 'fromEncoding' 参数传递给 BeautifulSoup,并尝试将 decode()
和 decode()
传递给 response
对象,但它要么没有任何区别,要么引发错误。
使用命令curl www.voxnow.de | hexdump -C
,我可以看到对于ö
字符,网页确实是UTF-8 编码(即它包含0xc3 0xb6
):
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 能力的极限,所以我不知道如何进一步调试它。有什么建议吗?
【问题讨论】:
奇怪.. 因为\u0102\u015b
是'Ăś'
..
@justhalf 我想我看到了这个问题,但不认为我得到了相同的结果。不过我会再检查一次,谢谢。
我会倾向于那个答案并使用请求库和原始内容***.com/a/36833440/3806595
【参考方案1】:
正如刚才一半指出的那样,我的问题本质上是 this question 的重复。
HTML 内容将自身报告为 UTF-8 编码,并且大部分情况下是这样,除了一两个流氓无效 UTF-8 字符。
这显然使 BeautifulSoup 混淆了正在使用哪种编码,以及在将内容传递给 BeautifulSoup 时尝试首先解码为 UTF-8 时 这个:
soup = BeautifulSoup(response.read().decode('utf-8'))
我会得到错误:
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 186812-186813:
invalid continuation byte
更仔细地查看输出,有一个字符 Ü
的实例被错误地编码为无效字节序列 0xe3 0x9c
,而不是正确的 0xc3 0x9c
。
正如当前highest-rated answer 在该问题上所建议的那样,可以在解析时删除无效的 UTF-8 字符,以便仅将有效数据传递给 BeautifulSoup:
soup = BeautifulSoup(response.read().decode('utf-8', 'ignore'))
【讨论】:
【参考方案2】:将结果编码为utf-8
似乎对我有用:
print (soup.find('div', id='navbutton_account')['title']).encode('utf-8')
它产生:
Hier können Sie sich kostenlos registrieren und / oder einloggen!
【讨论】:
嗯.. 我在几台机器上试过(使用 Python 2.7.3);该代码给了我四个字节,而不是您为ö
字符获得的两个字节:c4 82 c5 9b
以上是关于如何使用 BeautifulSoup 将 UTF-8 编码的 HTML 正确解析为 Unicode 字符串? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Python BeautifulSoup 将输出写入 html 文件
如何使用BeautifulSoup中的Python将单行中多列分隔的数据导出为.csv或.xls?
如何让 Beautifulsoup 不添加 <html> 或 <?xml ?>