问题

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

解决过程

  1. 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 的.

  1. 去试了试用 chardet. detect 分析其真正编码的, 得到的结果是:

    encInfo= {‘confidence’: 0.99, ‘encoding’: ‘utf-8’}

也是和其他网页内容得到的结果是一样的.

  1. 此问题觉得很诡异的是, 本身调用 UTF-8 去 decode, 但是解码出错却提示的是 GBK 的, 而不是 UTF-8 相关解码出错.

  2. 找了些其他帖子:

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 的问题的解释, 但同样不是我要的.

  1. 在这里: 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 “的错误的.

总结

对于此 (类) 问题:

  1. 出现 UnicodeEncodeError –> 说明是 Unicode 编码时候的问题;

  2. ’ 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’); 这样可以实现, 即使对于那些, 相对来说是无关紧要的一些特殊字符, 也可以成功编码, 避免编码出错, 提高程序的健壮性.