UnicodeEncodeError:'gbk'编解码器无法对位置43的字符u'\ u200e'进行编码:非法multib

原链接:HTTP://www.crifan.com/unicodeencodeerror_gbk_codec_can_not_encode_character_in_position_illegal_multibyte_sequence/

【问题】

蟒蛇中已获取网页:

http://blog.csdn.net/hfahe/article/details/5494895

的HTML源码,其时UTF-8编码的。

提取出其标题部分:

?

1 2 3 4 5 <span class="link_title"><a href="/hfahe/article/details/5494895">   在2008 Beijing Perl 大会的演讲-使用Mason开发高性能的Web站点‎   </a></span>

中的标题文字:

在2008北京Perl大会的演讲 – 使用梅森开发高性能的网站站点

然后用:

titleUni = unicode(titleHtml,“UTF-8”);

titleUni = titleHtml.decode(“UTF-8”);

将其解码成Unicode的,但是却会出错:

UnicodeEncodeError:’gbk’编解码器无法对字符u’\ u200e’进行位置43:非法多字节序列

 

【解决过程】

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

等,对应提取出来的内容,都是可以正常解码为统一的。

因为本身其编码的确是UTF-8的。

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

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

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

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

4.找了些其他帖子:

Python UnicodeEncodeError:非法多字节序列

但是讨论的都是关于从统一编码为GBK或GB2312,然后出错的。

而我这里的错误是,本身内容是UTF-8的,然后想要还原为Unicode的,结果却提示GBK解码错误的…

5.这里:探索UTF-8中文编码的BOM问题标记提到了,可能是由于UTF-8的BOM造成的不能正常解码,所以试着去将返回的HTML导出为HTML文件,然后用记事本++查看,结果还是没看出是否有BOM,反正是文字内容,都可以查看到的。

然后也试了类似代码:

titleUni = titleHtml [1:]。decode(“UTF-8”);

titleUni = titleHtml [2:]。decode(“UTF-8”);

但是都还是不行。

在后来这里也。看到了,关于UTF-8的BOM的问题的解释,但同样不是我要的。

6.在这里:Python Unicode与中文处理(文摘)看到了:

s.decode(’gbk’,’ignore’)。encode(’utf-8’)

然后才想起来,之前是看到过类似的解释,即添加忽略来忽略非法的字符,然后又参考:

蟒蛇字符串解码中遇到非法字符的问题

然后去找了对应语法:

海峡。解码( [ 编码 [,  错误 ]] 

使用注册编码的编码解码器解码字符串  。 编码  默认为默认的字符串编码。  可能会给出错误来设置不同的错误处理方案。缺省值是  ‘strict’,这意味着编码错误会引发UnicodeError其他可能的值是  ‘ignore’,  ‘replace’  和通过codecs.register_error()注册的任何其他名称  ,请参见  编解码器基类

2.2版本中的新功能。

在版本2.3中进行了更改:添加了对其他错误处理方案的支持。

在2.7版本中进行了更改:添加了对关键字参数的支持。

试了:

titleUni = titleHtml.decode(“UTF-8”,’ignore’);

和:

titleUni = titleHtml.decode(“UTF-8”,’replace’);

但是结果仍是:

打印“titleUni =”,titleUni;

会出现上述“’gbk’codec can not encode”的错误。

但是后来无意间发现,在打印titleUni之前,添加了一行调试代码:

打印“len(titleUni)=”,len(titleUni);

却是可以正常打印的,这就说明,此处的titleUni变量,正常解码为统一的值了,即上述解码是正常的。

然后又重新试了试,之前的:

titleUni = titleHtml.decode(“UTF-8”);

结果也是一样的,即print“len(titleUni)=”,len(titleUni);也是可以正常输出的。

然后此时才明白,原来出现’gbk’codec can not encode“的错误的根本原因是,对于前面的,不论是用

titleHtml.decode(“UTF-8”);

还是

titleHtml.decode(“UTF-8”,’忽略’);

还是

titleHtml.decode(“UTF-8”,’替换’);

都是可以得到正常的titleUni的统一字符的,然后对于此统一的字符,需要打印出来的话,由于本地系统是Win7的中的CMD,默认代码页是CP936,即GBK的编码,所以需要先将上述的统一的titleUni先编码为GBK,然后再在cmd中显示出来,然后由于titleUni中包含一些GBK中无法显示的字符,导致此时提示“’gbk’编解码器无法编码”的错误的。

【总结】

对于此(类)问题:

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

(2)’gbk’codec can not encode character – >说明是将Unicode字符编码为GBK时候出现的问题;

此时,往往最大的可能就是,本身的Unicode类型的字符中,包含了一些无法转换为GBK编码的一些字符。

解决办法是:

  • 方案1:

在对Unicode的字符编码时,添加忽略参数,忽略无法无法编码的字符,这样就可以正常编码为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’);

这样可以实现,即使对于那些,相对来说是无关紧要的一些特殊字符,也可以成功编码,避免编码出错,提高程序的健壮性。

    原文作者:sunnyNO123
    原文地址: https://blog.csdn.net/sunnyNO123/article/details/79372024
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞