一、字符编码
在编程的过程中,我们会遇到中文乱码的问题。要解决中文乱码我们就要了解计算机的字符编码,计算机有很多编码方式,因为计算机只能处理数字,因为处理文本的话,就必须先转化为数字。最早的时候计算机采用8bit作为一个字节。计算机使用二进制,因此一个字节可以表示256中不同的状态。例如ASCII码,这是我们最早接触的编码方式。但是这种不能表示汉子,中国就使用GB2312作为简体中文的编码方式,两个字节表示一个汉字,可以表示65536个符号。其他国家还有很多编码方式,但是这样的编码不统一,不同的编码不能垮平台使用。因此,出现了Unicode编码,被称为统一码、万国码或单一码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码。包含100多万个符号。
在使用的过程中,Unicode编码还会被编码成其他编码如utf-8,GBK等。是因为Unicode是二个字节的,有的符号只需要一个字节,这样会浪费资源,所以,我们再次对Unicode进行编码。UTF-8的一个特点就是长度可变,可以使用1-4字节表示一个符号,英文字母通常被编为一个字节,汉字通常被编为3个字节。
UTF-8的编码规则:
- 对于单字节的符号,字节的每1位设为0,后面7位为这个符号的Unicode码。对于英文字母,Unicode和UTF-8是相同的。
- 对于n字节的符号,第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10,剩下的没有提及的二进制位全部为这个符号的Unicode码。
二、Python字符编码
我们接下来看看Python的编码方式,Python3中,字符串的编码使用str和bytes两种类型。
- str字符串:使用Unicode编码
- bytes字符串:使用将Unicode转化成的某种类型的编码,如UTF-8、GBK
Python中默认使用的str编码,也就是Unicode编码。可以使用type()查看字符串默认编码类型。
查看字符串的类型:
str1 = "我们"
print(str1)
print(type(str1))
我们 <class 'str'>
将str字符串转换为bytes字符串的方法
encode过程:
- encode :作用是将Unicode编码转换成其他编码的字符串
- decode:作用是将其他编码的字符串转换成Unicode编码
str1 = "我们"
str_utf8 = str1.encode('utf-8')
print(str_utf8)
print(type(str_utf8))
b'\xe6\x88\x91\xe4\xbb\xac'
<class 'bytes'>
\xe6\x88\x91代表“我”,\xe4\xbb\xac代表“们”
decode过程:
str_decode = "我们".encode("utf-8").decode("utf-8")
print(str_decode)
print(type(str_decode))
我们
<class 'str'>
我们还可以使用encode编码为其他格式,比如GBK。并且查看具体的编码类型。
import chardet
str_gbk = "我们".encode("gbk")
chardet.detect(str_gbk)
{'confidence': 0.8095977270813678, 'encoding': 'TIS-620', 'language': 'Thai'}
注意:Unicode编码不能再进行decode,已经encode为utf-8编码,也不能在编码为其他格式编码,如果想实现必须decode为Unicode编码,在encode为gbk。
三、解决中文编码问题
在进行爬虫时,也会出现中文乱码的问题。主要有以下这几种情况:
- 问题1:使用Reques获得网站内容后,发现中文显示乱码
- 问题2:将某个字符串decode的时候,字符串中有非法字符,程序抛出异常
- 问题3:网页使用gzip压缩,解析网页数据的时候中文乱码显示
- 问题4:写入和读取文件的时候,文件显示的字符串不是正确的中文
1. 解决问题1
我们爬取w3school网站,获取网页的标题(领先的Web技术教程-全部免费)
import requests
from bs4 import BeautifulSoup
url = 'http://w3school.com.cn/'
r = requests.get(url)
soup = BeautifulSoup(r.text, "lxml")
xx = soup.find('div', id='d1').h2.text
print(xx)
ÁìÏ鵀 Web ¼¼Êõ½Ì³Ì - È«²¿Ãâ·Ñ
乱码的原因是代码中获得的网页响应体r和网站的编码方式不同。键入r.encodeing.得到的结果是ISO-8859-1,意思是requets推测文本编码是这个,而实际上是gb2312.因此,我么需要制定和网页相同的编码格式。
import requests
from bs4 import BeautifulSoup
url = 'http://w3school.com.cn/'
r = requests.get(url)
r.encoding = 'gb2312'
soup = BeautifulSoup(r.text, "lxml")
xx = soup.find('div', id='d1').h2.text
print(xx)
领先的 Web 技术教程 - 全部免费
注意:大多数网页的编码方式为UTF-8.Requests会自动解码来自于服务器的内容。
2. 解决问题2
当我们对字符串进行‘GBK’解码时,有时会报出错误,这是因为有些网站编码不规范,一个页面里混了多种编码,于是出现了非法字符。解决这种问题很简单,只需忽略解码这些非法字符。
str1.decode('GBK', 'ignore')
decode方法的第二个参数有三种形式,默认为strict,遇到非法字符时会抛出异常。如下:
- ignore,忽略其中的非法字符,仅显示有效字符
- replace,使用符号代替非法字符,如‘?’
- xmlcharrefreplace,使用XML字符引用代替非法字符
3. 解决问题3
使用Requests获取新浪网首页。新浪网是UTF-8编码。
import requests
url = "http://www.sina.com.cn/"
r = requests.get(url)
print(r.text)
出现乱码的情况,出现这种情况的原因是新浪网使用gzip将网页压缩了。必须先对其解码。使用r.content会自动解码gzip和deflate传输编码的响应数据。
import requests
import chardet
url = "http://www.sina.com.cn/"
r = requests.get(url)
after_gzip = r.content
print("解压后的字符串编码为", chardet.detect(after_gzip))
print(after_gzip.decode('UTF-8'))
4. 解决问题4
在使用Python3读取和保存文件的时候要注明编码方式,首先,我们创建一个txt文件,命名test_ANSI.txt,里面保存“abc中文”.使用默认的ANSI编码保存文件。然后创建另外一个TXT文件,命名为test_utf8.txt。保存同样的内容,并且另存为,在最下方编码处选择utf-8.接下来使用Python来读取这两个文件。
result = open('test_ANSI.txt', 'r').read()
print(result)
abc中文
result = open('test_utf8.txt', 'r').read()
print(result)
UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 8: illegal multibyte sequence
读取utf-8编码方式的文件出错了,这是因为Windows系统安装的是简体中文版,默认的编码方式是GBK(也就是ANSI)。因此在读取的时候必须声明编码方式。
result = open('test_utf8.txt', 'r', encoding='utf-8').read()
print(result)
abc中文
而在保存文件的时候,依然要指定编码格式
title = '我们'
with open('title.txt', 'a+', encoding='UTF-8') as f:
f.write(title)
f.close()
上面的方式是对于txt和csv文件的,对于json文件,保存数据时,默认的是Unicode编码处理。
import json
title = "我们 love 你们"
with open('title.json', 'w', encoding='UTF-8') as f:
json.dump([title], f)
["\u6211\u4eec love \u4f60\u4eec"]
想要以中文显示,则修改代码
import json
title = "我们 love 你们"
with open('title.json', 'w', encoding='UTF-8') as f:
json.dump([title], f, ensure_ascii=False)
["我们 love 你们"]
总结:本篇文章解决了平时编程,遇到的中文乱码问题,我在平时编程时,也会遇到这个问题,也找到了解决方法,但是都不知道为什么,通过本章的学习,了解了中文乱码问题的解决方法。
注意:本篇学习笔记,是总结唐松老师的《Python网络爬虫从入门到实践》这本书的内容,如果想了解书中详细内容,请自行购买