爬虫学习----解决中文乱码

一、字符编码

在编程的过程中,我们会遇到中文乱码的问题。要解决中文乱码我们就要了解计算机的字符编码,计算机有很多编码方式,因为计算机只能处理数字,因为处理文本的话,就必须先转化为数字。最早的时候计算机采用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网络爬虫从入门到实践》这本书的内容,如果想了解书中详细内容,请自行购买

猜你喜欢

转载自blog.csdn.net/gyt15663668337/article/details/86488810