Python中经常遇到这样那样的字符编码问题,尤其在处理网页源码时(特别是爬虫中):

UnicodeDecodeError: ‘XXX' codec can't decode bytes in position 12-15: illegal multibyte...

每次看到上面这段文字的时候,感觉整个世界都昏暗了,然后就只能各种搜索找资料,过后就忘了。下次遇到时就让世界再昏暗一次。为了彻底解决这个拦路虎,今天咱们就好好的来唠嗑唠嗑。

下面以汉字'哈'来解释作示例解释所有的问题,汉字“哈”的各种编码如下:

1 UNICODE(UTF8-16): 0xC854

2 UTF-8: 0xE59388

3 GBK: 0xB9FE

除此之外还有如gb2312, big5等。例如一些含有繁体字的页面,比如www.google.com.hk首页中用的就是big5码,

不知道港台的码农同时处理简体字繁体字是不是更郁闷(笑脸)

处理解决

首先,在python中提到unicode,一般指的是unicode对象,例如'哈哈'的unicode对象为u'\u54c8\u54c8'

而str是一个字节数组,这个字节数组表示的是对unicode对象编码后(如utf-8、gbk、cp936、GB2312)的存储的格式,这里它仅是一个字节流,没有其它的含义,如果你想使这个字节流显示的内容有意义,就必须用正确的编码格式,解码显示。

例如:(注意是在windows下)

s = u'哈哈'

s_utf8 = s.encode('utf-8')

pirnt s_utf8

>>> 鍝堝搱

悲剧...

s_utf8这时实际上是'\xe5\x93\x88\xe5\x93\x88'

而下面的代码才可以正常显示:

s_gdb = s.encode('gbk') # s_gdk 这时是'\xb9\xfe\xb9\xfe'

print s_gbk

>>> 哈哈 #正常了

因为print语句它的实现是将要输出的内容传 送了操作系统,操作系统会根据系统的编码对输入的字节流进行编码,这就解释了utf-8格式的字符串“哈哈”,输出的是“鍝堝搱”,因为 '\xe5\x93\x88\xe5\x93\x88'用GB2312去解释,其显示的出来就“鍝堝搱”。

这里再强调一下,str记录的是字节数组,只是某种编码的存储格式,至于输出到文件或是打印出来是什么格式,完全取决其解码的编码将它解码成什么样子。

str和unicode对象的转换,通过encode和decode实现,具体使用如下:再次强调windows下:

s = '哈哈'

print s.decode('gbk').encode('utf-8')

>>> 鍝堝搱

反之亦然,有兴趣可以尝试其他转换

有时当我们遇到把s(gbk字符串)直接编码成utf-8的时候,将抛出异常,但是通过调用如下代码:

import sys

reload(sys)

sys.setdefaultencoding('gbk')

后就可以转换成功,为什么呢?

在python中str和unicode在编码和解码过程中,如果将一个str直接编码成另一种编码,会先把str解码成unicode,采用默认编码,一般默认编码是anscii,所以在上面示例代码中第一次转换的时候会出错,

当设定当前默认编码为'gbk'后,就不会出错了。至于reload(sys)是因为Python2.5 初始化后会删除 sys.setdefaultencoding 这个方法,我们需要重新载入。一般不推荐这样使用。本来reload都是应该避免使用的函数。

对于操作不同文件的编码格式的文件,也会遇到这样的问题

建立一个文件test.txt,文件格式用ANSI,内容为:

abc中文

然后用python来读取

# coding=gbk

print open("Test.txt").read()

结果:abc中文

把文件格式改成UTF-8:

结果:abc涓枃,显然,这里需要解码:

# coding=gbk

import codecs

print open("Test.txt").read().decode("utf-8")

结果:abc中文

上面的test.txt我是用Editplus来编辑的,但当我用Windows自带的记事本编辑并存成UTF-8格式时,

运行时报错:

Traceback (most recent call last):

File "ChineseTest.py", line 3, in

print open("Test.txt").read().decode("utf-8")

UnicodeEncodeError: 'gbk' codec can't encode character u'\ufeff' in position 0: illegal multibyte sequence

原来,某些软件,如notepad,在保存一个以UTF-8编码的文件时,

会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM)。

因此我们在读取时需要自己去掉这些字符,python中的codecs module定义了这个常量:

# coding=gbk

import codecs

data = open("Test.txt").read()

if data[:3] == codecs.BOM_UTF8:

data = data[3:]

print data.decode("utf-8")

结果:abc中文

最后,有些时候编码搞对了,但是遇到了非法字符,比如产生字符串的来源发生错误,引入了错误值等,这时再次遇到异常

例如:全角空格往往有多种不同的实现方式,比如\xa3\xa0,或者\xa4\x57,

这些字符,看起来都是全角空格,但它们并不是“合法”的全角空格

真正的全角空格是\xa1\xa1,因此在转码的过程中出现了异常。

而之前在处理新浪微博数据时,遇到了非法空格问题导致无法正确解析数据。

解决办法:

将获取的字符串strTxt做decode时,指明ignore,会忽略非法字符,

当然对于gbk等编码,处理同样问题的方法是类似的

strTest = strTxt.decode('utf-8', 'ignore')

return strTest

默认的参数就是strict,代表遇到非法字符时抛出异常;

如果设置为ignore,则会忽略非法字符;

如果设置为replace,则会用?号取代非法字符;

如果设置为xmlcharrefreplace,则使用XML的字符引用。

Python 字符编码处理总结的更多相关文章

  1. python 字符编码练习

    通过下面的练习,加深对python字符编码的认识 # \x00 - \xff 256个字符 >>> a = range(256)>>> b = bytes(a) # ...

  2. Python字符编码讲解

    声明:本文参考 Python字符编码详解 在计算机中我们不管用什么语言和程序,最终数据在计算机中的都是字节码(也就是01形式)的形式存在的,如果 计算机直接把字节码显示在屏幕上,很明显一般人看不懂字节 ...

  3. 深入理解Python字符编码--转

    http://blog.51cto.com/9478652/2057896 不论你是有着多年经验的 Python 老司机还是刚入门 Python 不久,你一定遇到过UnicodeEncodeError ...

  4. 深入理解Python字符编码

    不论你是有着多年经验的 Python 老司机还是刚入门 Python 不久,你一定遇到过UnicodeEncodeError.UnicodeDecodeError 错误,每当遇到错误我们就拿着 enc ...

  5. Python字符编码详解,str,bytes

    什么是明文 “明文”是可以是文本,音乐,可以编码成mp3文件.明文可以是图像的,可以编码为gif.png或jpg文件.明文是电影的,可以编码成wmv文件.不一而足. 什么是编码?把明文变成计算机语言 ...

  6. Python字符编码补充

    字符编码: Python字符编码贯穿Python学习的始终,现在应用的是Python2中字符编码的问题是很多的. 这次是要彻底解决Python字符编码的问题!!! 1 字符编码的发展过程: 1 .AS ...

  7. python --- 字符编码学习小结(二)

    距离上一篇的python --- 字符编码学习小结(一)已经过去2年了,2年的时间里,确实也遇到了各种各样的字符编码问题,也能解决,但是每次都是把所有的方法都试一遍,然后终于正常.这种方法显然是不科学 ...

  8. 转1:Python字符编码详解

    Python27字符编码详解 声明 一 字符编码基础 1 抽象字符清单ACR 2 已编码字符集CCS 3 字符编码格式CEF 31 ASCII初创 311 ASCII 312 EASCII 32 MB ...

  9. 转2:Python字符编码详解

    1. 字符编码简介 1.1. ASCII ASCII(American Standard Code for Information Interchange),是一种单字节的编码.计算机世界里一开始只有 ...

  10. python字符编码(二)

    一.什么是字符编码 计算机要想工作必须通电,也就是说‘电’驱使计算机干活,而‘电’的特性,就是高低电压(高低压即二进制数1,低电压即二进制数0),也就是说计算机只认识数字 编程的目的是让计算机干活,而 ...

随机推荐

  1. Activiti历史查看

    流程执行完毕后,究竟去了哪里有些疑问. 虽然已完成的任务在act_ru_task和act_ru_execution表中都已被删除,但是这些数据还存在activiti的数据库中,作为历史改由Histor ...

  2. T2988 删除数字【状压Dp+前缀和优化】

    Online Judge:从Topcoder搬过来,具体哪一题不清楚 Label:状压Dp+前缀和优化 题目描述 给定两个数A和N,形成一个长度为N+1的序列,(A,A+1,A+2,...,A+N-1 ...

  3. ERP或PLM系统-物料编码管理的技术实现

    1 企业现状 企业日常经营过程中会产生大量的文档,如设计图纸.变更单.计算书.设计方案等,如果是制造企业还会产生大量的产品.组成产品的零部件等物料,这些数据在进入信息系统前都需要有一个唯一的标识,也就 ...

  4. mysql密码管理

    1.密码丢失找回: (1)关闭mysql服务进程(2)跳过mysql权限检测:在mysql的配置文件中的mysqld节点下面添加skip-grant-tables的服务器配置项,或者启动服务时加上-- ...

  5. windows下和linux下运行jar

    需要在windows下运行jar,首先需要我们打包出来可执行jar idea打包可执行jar可以参考我的另一篇博客[https://mp.csdn.net/postedit/88653200] 一.w ...

  6. 最小费用最大流——EK+SPFA

    终于把最小费用最大流学会了啊-- 各种奇奇怪怪的解释我已经看多了,但在某些大佬的指点下,我终于会了. 原来是个好水的东西. 最小费用最大流是什么? 不可能不知道网络流吧?如果不知道,自行百度去-- 费 ...

  7. vim 插入行号

    :let i=1000000|g/^/s//\=i.' '/|let i=i+1

  8. APT甲级——A1069 The Black Hole of Numbers

    For any 4-digit integer except the ones with all the digits being the same, if we sort the digits in ...

  9. angular7.X配置同时使用localhost和本机IP访问项目

    1.项目中找到此文件“node_modules/webpack-dev-server/lib/Server.js”,按照下图修改: 二.修改配置文件package.json,见下图: 三.npm st ...

  10. Django项目:CRM(客户关系管理系统)--41--33PerfectCRM实现King_admin编辑整张表限制

    readonly_table=False#默认表单不锁定 readonly_table=True#默认表单不锁定 # forms.py # ————————19PerfectCRM实现King_adm ...