爬取网站时,网页源代码出现中文乱码问题。之前关于爬虫乱码的问题有各种各样,今天就跟大家总结一下网络爬虫的乱码问题。注意这里不仅是中文乱码,还有日文、韩文、俄文、藏文等部分乱码。因为他们的解决方案是一致的,所以在这里解释一下。1、乱码的出现。以抓取51job网站为例,谈谈为什么会出现“乱码”问题,如何解决以及背后的机制。代码示例:importrequestsurl="http://search.51job.com"res=requests.get(url)print(res.text)显示结果:打印res.text时,发现了什么?中文乱码!!!但是发现,网页的字符集类型采用的是gbk编码格式。我们知道Requests会根据HTTP标头对响应的编码进行有根据的猜测。当您访问r.text时,请求将使用其猜测的文本编码。您可以找出Requests使用的编码,并可以使用r.encoding属性更改它。接下来,让我们通过resquests的一些用法,看看Requests是如何根据HTTP标头对响应进行编码的。print(res.encoding)#查看网页返回的字符集类型print(res.apparent_encoding)#自动判断字符集类型输出结果:可以找到Requests推测的文本编码(即编码转换后的编码)返回网页并抓取))与源网页代码不一致,可见是乱码的原因。2、乱码背后的玄机当源网页的编码转换与爬取后的编码转换不一致时,比如源网页是gbk编码的字节流,我们抓取后的程序直接使用utf-8编码输出到存储文件中,这样难免会造成乱码,即当源网页的编码与捕获后程序直接使用的编码一致时,不会出现乱码乱码,再统一字符编码就不会出现乱码了。所有最终爬取到的网页,不管是什么编码格式,都会转为utf-8格式存储。注意:区分源网络编码A-gbk、程序直接使用的编码B-ISO-8859-1、统一转换字符的编码C-utf-8。这里,我们展开说说unicode、ISO-8859-1、gbk2312、gbk、utf-8等的区别,大致如下:最早的编码是iso8859-1,类似于ascii编码。但是,为了方便各种语言的表示,逐渐出现了很多标准的编码。iso8859-1为单字节编码,最大可表示字符范围为0-255,用于英文系列。显然,iso8859-1编码表示的字符范围很窄,不能表示汉字。1981年,中国人民对ASCII码进行了扩充改造,产生了GB2312码,可以表示6000多个常用汉字。但是汉字太多了,包括繁体字和各种字,所以产生了GBK编码,其中包括了GB2312中的编码,同时扩展了很多。中国也是一个多民族国家,几乎所有民族都有自己独立的语言系统。为了表示这些字符,GBK码继续扩展为GB18030码。每个国家,比如中国,都有自己的语言编码,所以出现了各种各样的编码。如果不安装对应的代码,就无法说明对应的代码想表达什么。终于,一个叫ISO的组织看不下去了。他们一起创建了一个名为UNICODE的代码,它的大小可以容纳世界上任何字符和徽标。所以只要电脑有UNICODE编码系统,不管世界上是什么文字,你只要把文件保存成UNICODE编码,其他电脑就可以正常解读了。在UNICODE的网络传输中,出现了UTF-8和UTF-16两种标准,每次分别传输8位和16位。那么有人会有疑惑,既然UTF-8可以保存这么多的字符和符号,为什么国内还有这么多人使用GBK等编码呢?因为UTF-8等编码的体积比较大,占用的计算机空间也很大。大部分用户是中国人,也可以使用GBK等编码。也可以这样理解:字符串是由字符组成的,字符在计算机硬件中是以二进制形式存储的。这种二进制形式就是编码。如果直接使用“string??character??binaryrepresentation(encoding)”,会增加不同类型编码之间转换的复杂度。因此,引入了一个抽象层,“字符串??字符??存储无关表示??二进制表示(编码)”,让字符可以用存储无关的形式表示,不同编码之间转换时,可以在转换为其他编码形式之前,首先转换为该抽象层。这里,unicode是“存储无关的表示”,utf-8是“二进制表示”。3、乱码的解决方法根据原因寻找解决方法很简单。方法一:直接指定res.encodingimportrequestsurl="http://search.51job.com"res=requests.get(url)res.encoding="gbk"html=res.textprint(html)方法二:通过res.apparent_encoding属性规范importrequestsurl="http://search.51job.com"res=requests.get(url)res.encoding=res.aparent_encodinghtml=res.textprint(html)方法三:通过编码解码importrequestsurl="http://search.51job.com"res=requests.get(url)html=res.text.encode('iso-8859-1').decode('gbk')print(html)输出结果:基本思路三Stepby步骤:确定源网页的编码A---gbk,程序通过编码B---ISO-8859-1还原源网页的数据,统一转换编码C-utf-8的字符。至于为什么会有统一转码的步骤?网络爬虫系统中有很多数据源。当无法使用数据时,将其转换为原始数据。这样做是没有用的。所以一般的爬虫系统都必须对爬取的结果进行统一的编码,这样才能在使用的时候保持一致,方便使用。比如我们要保存网页数据,会转成utf-8,代码如下:withopen("a.txt",'w',encoding='utf-8')asf:f.write(html)4.总结关于网络爬虫乱码问题,本文不仅给出了解决方案,还深入了原理。这个问题引出了很多有趣的问题,例如,utf-8、gbk、gb2312的编码方式是什么?为什么这个转换可以解决问题?
