编码和urllib问题

1 投票
2 回答
4919 浏览
提问于 2025-04-15 22:42

我正在使用urllib加载网页。网页中有俄文字符,但页面的编码是'utf-8'

1

pageData = unicode(requestHandler.read()).decode('utf-8')

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 262: ordinal not in range(128)

2

pageData = requestHandler.read()
soupHandler = BeautifulSoup(pageData)
print soupHandler.findAll(...)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 340-345: ordinal not in range(128)

2 个回答

1

如果 requestHandler.read() 返回的是一个UTF-8编码的流,那么

pageData = requestHandler.read().decode('utf-8')

就会把它解码成一个Unicode字符串(在这个时候,正如Dietrich Epp正确指出的,unicode()这个调用就不再需要了)。

如果它抛出一个异常,那说明输入显然不是UTF-8编码的。

2

在你提到的第一个代码片段中,调用 unicode(requestHandler.read()) 是在告诉 Python 把 read 返回的字节串转换成 unicode。因为没有指定转换的编码方式,所以它尝试使用 ascii,但失败了。它根本没有到你要调用 .decode 的那一步(而且在这个 unicode 对象上调用 .decode 其实也没有意义)。

你可以使用 unicode(requestHandler.read(), 'utf-8'),或者 requestHandler.read().decode('utf-8'):这两种方式都应该能正确生成一个 unicode 对象,前提是编码确实是 utf-8(那个 D0 字节的出现可能表明编码不是 utf-8,但仅凭一个非 ascii 字符是无法判断的)。

打印 Unicode 数据是另一个问题,需要一个配置良好且能配合的终端模拟器——也就是那个能让 Python 在启动时设置 sys.stdout.encoding 的终端。例如,在 Mac 上,使用苹果的 Terminal.App:

>>> sys.stdout.encoding
'UTF-8'

在这里打印 Unicode 对象是没问题的:

>>> print u'\xabutf8\xbb'
«utf8»

打印 utf8 编码的字节串也可以:

>>> print u'\xabutf8\xbb'.encode('utf8')
«utf8»

但在其他机器上,只有后者能正常工作(使用终端模拟器自己的编码,而你需要自己去了解这个编码,因为终端模拟器不会告诉 Python;-)。

撰写回答