解决python编码问题大总结

 前言

因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理。最早的计算机在设计时采用8个比特(bit)作为一个字节(byte),所以,一个字节能表示的最大的整数就是255(二进制11111111=十进制255),0 - 255被用来表示大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,


在所有字符集中,最知名的可能要数被称为ASCII的7位字符集了。它是美国标准信息交换代码(American Standard Code for Information Interchange)的缩写, 为美国英语通信所设计。它由128个字符组成,包括大小写字母、数字0-9、标点符号、非打印字符(换行符、制表符等4个)以及控制字符(退格、响铃等)组成。但是,由于他是针对英语设计的,当处理带有音调标号(形如汉语的拼音)的欧洲文字时就会出现问题。


把汉语、日语和越南语的一些相似的字符结合起来,在不同的语言里,使不同的字符代表不同的字,这样只用2个字节就可以编码地球上几乎所有地区的文字。因此,创建了UNICODE编码。它通过增加一个高字节对ISO Latin-1字符集进行扩展,当这些高字节位为0时,低字节就是ISO Latin-1字符。


因为Python的诞生比Unicode标准发布的时间还要早,所以最早的Python只支持ASCII编码,普通的字符串'ABC'在Python内部都是ASCII编码的


python:于1989年发明,第一个公开发行版发行于1991年
Unicode:1990年开始研发,1994年正式公布




事实证明,对可以用ASCII表示的字符使用UNICODE并不高效,因为UNICODE比ASCII占用大一倍的空间,而对ASCII来说高字节的0对他毫无用处。为了解决这个问题,就出现了一些中间格式的字符集,他们被称为Unicode转换格式,即UTF(Unicode Transformation Format)。常见的UTF格式有:UTF-7, UTF-7.5, UTF-8,UTF-16, 以及 UTF-32。

1. python2中的乱码问题解决方法

首先要搞清楚, 字符串在Python2内部的表示是unicode编码,因此,在做编码转换时,通常需要 以unicode作为中间编码即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码


decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode('gb2312'),表示将gb2312编码的字符串转换成unicode编码。


encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode('gb2312'),表示将unicode编码的字符串转换成gb2312编码。


在某些IDE中,字符串的输出总是出现乱码,甚至错误,其实是由于IDE的结果输出控制台自身不能显示字符串的编码,而不是程序本身的问题。


#-*-coding:utf-8-*- 

s='中文'
print type(s) #查看s的字符类型
print s  

s.decode('utf8') #解码utf8,默认的编码方式是unicode
s.decode('gbk', "ignore") #解码utf8,忽略其中有异常的编码,仅显示有效的编码
s.decode('gbk', 'replace')
print type(s)
print s

s.encode('gb2312') ##编码为utf8
print type(s)
print s

test.py编码必需与s.decode('utf8')指定的编码一致,不然会抛出解码异常信息,可以通过s.decode("gbk", "ignore")或s.decode("gbk", "replace")来解决。


另外对于一些包含特殊字符的编码,直接解码可能会报错,可以使用对于的参数来设置。如:
s.decode("utf-8", "ignore") 忽略其中有异常的编码,仅显示有效的编码

s.decode("utf-8", "replace") 替换其中异常的编码,这个相对来可能一眼就知道那些字符编码出问题了。


2. python3中的乱码问题解决方法

在python2里面,u表示unicode string,类型是unicode, 没有u表示byte string,类型是 str。

在python3里面,所有字符串都是unicode string, u前缀没有特殊含义了。python3默认编码为unicode,由str类型进行表示。二进制数据使用byte类型表示,所以不会将str和byte混在一起

r都表示raw string. 与特殊字符的escape规则有关,一般用在正则表达式里面。

r和u可以搭配使用,例如ur"abc"。

所以python3中str类型已经没有decode方法,例如:

s = "python"
s.decode('gbk', "ignore") 
AttributeError                            Traceback (most recent call last)
 in ()
      1 s = "python"
----> 2 s.decode('gbk', "ignore")

AttributeError: 'str' object has no attribute 'decode'

此外,我们可以用dir(s)查看有无此方法。

有几点需要注意:

1:字符串通过编码转换为字节码,字节码通过解码转换为字符串

str--->(encode)--->bytes,bytes--->(decode)--->str

import sys  
import chardet
print('目前系统的编码为:',sys.getdefaultencoding())  
name='小明'  
print(type(name))#首先我们来打印下转码前的name类型,因为它是str,所以可以通过encode来进行编码  
目前系统的编码为: utf-8

{'encoding': 'utf-8', 'language': '', 'confidence': 0.7525}
b'\xe5\xb0\x8f\xe6\x98\x8e'

name1=name.encode('utf-8') print(chardet.detect(name1))print(name1) print(type(name1))

可以看到name的type:str类型通过encode('utf-8')转换成了bytes类型从unicode转str,被看做是把一个信息文本编码为二进制字节流的过程,要用encode方法

name2=name1.decode('utf-8')  
print(type(name2))  
print(name2)  

小明
这里要跟大家说下,decode()括号中为什么写utf-8,而不写gbk,可以这样理解,因为要解码,你总得告诉它我是什么编码的吧,比如我原先是utf-8格式的编码,现在要解码,但是如果冒充utf-8,说自己是gbk,那就会出现乱码,见下:

name = "小明"
name1=name.encode('utf-8')  
name2=name1.decode('utf-8')  
name3=name2.encode('gbk')  
name4=name3.decode('gbk')
print("name:")
print(type(name))  
print(name)
print("name1:")
print(type(name1))  
print(name1)
print("name2:")
print(type(name2))  
print(name2)  
print("name3:")
print(type(name3))  
print(name3)  
print("name4:")
print(type(name4))  
print(name4)
name:

小明
name1:

b'\xe5\xb0\x8f\xe6\x98\x8e'
name2:

小明
name3:

b'\xd0\xa1\xc3\xf7'
name4:

小明
所以不难看出,其实utf-8和gbk之间都是通过unicode来做一个中间转换的操作

3. python3爬虫中的乱码问题解决方法


import urllib.request  
res=urllib.request.urlopen('http://www.baidu.com')  
htmlBytes=res.read()  
print(type(htmlBytes))

htmlStr = htmlBytes.decode('utf-8')

print(htmlBytes)

b'\n\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n        \r\n\t\t\t        \r\n\t\r\n\t\t\t        \r\n\t\r\n\t\t\t        \r\n\t\r\n\t\t\t        \r\n\t\t\t    \r\n\r\n\t\r\n  
htmlBytes为bytes类型所以可通过decode方法解码为str类型
htmlStr
'\n\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\r\n        \r\n\t\t\t        \r\n\t\r\n\t\t\t        \r\n\t\r\n\t\t\t        \r\n\t\r\n\t\t\t        \r\n\t\t\t    \r\n\r\n\t\r\n        \r\n\t\t\t        \r\n\t\r\n\t\t\t        \r\n\t\r\n\t\t\t        \r\n\t\r\n\t\t\t        \r\n\t\t\t    
print(htmlStr)


                    

你可能感兴趣的:(解决python编码问题大总结)