问题
python 中已获取网页: http: //blog. csdn. net/hfahe/article/details/5494895 的 html 源码, 其时 UTF-8 编码的.
提取出其标题部分:
<span class="link_title"><a href="/hfahe/article/details/5494895">
在2008 Beijing Perl 大会的演讲-使用Mason开发高性能的Web站点
</a></span>
中的标题文字: 在 2008 Beijing Perl 大会的演讲-使用 Mason 开发高性能的 Web 站点
然后用:
titleUni = unicode(titleHtml, “UTF-8”);
或
titleUni = titleHtml.decode(“UTF-8”);
将其解码成 Unicode, 但是却会出错:
UnicodeEncodeError: ‘gbk’ codec can’t encode character u’\u200e’ in position 43: illegal multibyte sequence
解决过程
- Python 的编码问题, GB18030, UTF-8, Unicode 等问题, 之前遇到过很多次了, 也就解决了. 此处很奇怪的是,
类似的其他的网页, 比如:
http: //blog. csdn. net/v_july_v/article/details/6543438
http: //blog. csdn. net/v_july_v/article/details/5934051
等, 对应提取出来的内容, 都是可以正常解码为 Unicode 的.
因为本身其编码的确是 Utf-8 的.
去试了试用 chardet. detect 分析其真正编码的, 得到的结果是:
encInfo= {‘confidence’: 0.99, ‘encoding’: ‘utf-8’}
也是和其他网页内容得到的结果是一样的.
此问题觉得很诡异的是, 本身调用 UTF-8 去 decode, 但是解码出错却提示的是 GBK 的, 而不是 UTF-8 相关解码出错.
找了些其他帖子:
Python UnicodeEncodeError:illegal multibyte sequence
但是讨论的都是关于从 Unicode 编码为 GBK 或 GB2312, 然后出错的.
而我这里的错误是, 本身内容是 UTF-8 的, 然后想要还原为 Unicode, 结果却提示 GBK 解码错误的......
5. 这里: 探索 UTF-8 中文编码的 BOM 标记问题提到了, 可能是由于 UTF-8 的 BOM 造成的不能正常解码, 所以试着去将返回的 html 导出为 html 文件, 然后用 Notepad++查看, 结果还是没看出是否有 BOM, 反正是文字内容, 都可以查看到的.
然后也试了类似代码:
titleUni = titleHtml[1:].decode(“UTF-8”);
titleUni = titleHtml[2:].decode(“UTF-8”);
但是都还是不行.
后来在这里也看到了, 关于 UTF-8 的 BOM 的问题的解释, 但同样不是我要的.
在这里: Python Unicode 与中文处理 (文摘), 看到了:
s.decode(‘gbk’, ‘ignore’).encode(‘utf-8′)
然后才想起来, 之前是看到过类似的解释, 即添加 ignore 来忽略非法的字符, 然后又参考:
python 字符串 decode 中遇到非法字符的问题
然后去找了对应语法:
str.decode([encoding[, errors]])
Decodes the string using the codec registered for encoding. encoding defaults to
the default string encoding. errors may be given to set a different error
handling scheme. The default is 'strict', meaning that encoding errors raise
UnicodeError. Other possible values are 'ignore', 'replace' and any other name
registered via codecs.register_error(), see section Codec Base Classes.
New in version 2.2.
Changed in version 2.3: Support for other error handling schemes added.
Changed in version 2.7: Support for keyword arguments added.
试了:titleUni = titleHtml.decode(“UTF-8”, ‘ignore’);
和:titleUni = titleHtml.decode(“UTF-8”, ‘replace’);
但是结果仍是:print “titleUni=”,titleUni;
会出现上述 “‘gbk’ codec can ‘t encode” 的错误.
但是后来无意间发现, 在打印 titleUni 之前, 添加了一行调试代码:print “len(titleUni)=”,len(titleUni);
却是可以正常打印的, 这就说明, 此处的 titleUni 变量, 正常解码为 Unicode 的值了, 即上述 decode 是正常的.
然后又重新试了试, 之前的:titleUni = titleHtml.decode(“UTF-8”);
结果也是一样的, 即 print “len (titleUni)=”, len (titleUni); 也是可以正常输出的.
然后此时才明白, 原来出现’ gbk ‘codec can’ t encode “的错误的根本原因是, 对于前面的, 不论是用
还是
titleHtml.decode(“UTF-8”, ‘ignore’);
还是
titleHtml.decode(“UTF-8”, ‘replace’);
都是可以得到正常的 titleUni 的 Unicode 字符的, 然后对于此 Unicode 的字符, 需要 print 出来的话, 由于本地系统是 Win7 中的 cmd, 默认 codepage 是 CP936, 即 GBK 的编码, 所以需要先将上述的 Unicode 的 titleUni 先编码为 GBK, 然后再在 cmd 中显示出来, 然后由于 titleUni 中包含一些 GBK 中无法显示的字符, 导致此时提示” ‘gbk’ codec can ‘t encode “的错误的.
总结
对于此 (类) 问题:
出现 UnicodeEncodeError –> 说明是 Unicode 编码时候的问题;
’ gbk ‘codec can’ t encode character –> 说明是将 Unicode 字符编码为 GBK 时候出现的问题;
此时, 往往最大的可能就是, 本身 Unicode 类型的字符中, 包含了一些无法转换为 GBK 编码的一些字符.
解决办法是:
方案 1
在对 unicode 字符编码时, 添加 ignore 参数, 忽略无法无法编码的字符, 这样就可以正常编码为 GBK 了.
对应代码为:gbkTypeStr = unicodeTypeStr.encode(“GBK“, ‘ignore’);
方案 2
或者, 将其转换为 GBK 编码的超集 GB18030 (即, GBK 是 GB18030 的子集):gb18030TypeStr = unicodeTypeStr.encode(“GB18030“);
对应的得到的字符是 GB18030 的编码.
题外话
对于上述中, 将原先的 utf-8 的字符转换为 Unicode 的时候, 其实更加安全的做法, 也可以将:
titleUni = titleHtml.decode(“UTF-8”);
替换为:
titleUni = titleHtml.decode(“UTF-8”, ‘ignore’);
这样可以实现, 即使对于那些, 相对来说是无关紧要的一些特殊字符, 也可以成功编码, 避免编码出错, 提高程序的健壮性.