作者 丁彦军,一个痴恋于Python语言的程序猿

在爬取某网站时,网页的源代码出现了中文乱码问题。之前 关于爬虫乱码有各式各样的问题,今天与大家一起总结下关于网络爬虫的乱码处理。注意,这里不仅是中文乱码,还包括一些如日文、韩文 、俄文、藏文之类的乱码处理,因为他们的解决方式 是一致的,故在此统一说明。

一、乱码问题的出现

就以 爬取51job网站举例,讲讲为何会出现“乱码”问题,如何解决它以及其背后的机制。

代码示例:

import requests

url = "http://search.51job.com"
res = requests.get(url)
print(res.text)

显示结果:

打印res.text时,发现了什么?中文乱码!!!不过发现,网页的字符集类型采用的gbk编码格式。

我们知道Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。当你访问 r.text 之时,Requests 会使用其推测的文本编码。你可以找出 Requests 使用了什么编码,并且能够使用r.encoding 属性来改变它。

接下来,我们一起通过resquests的一些用法,来看看 Requests 会基于 HTTP 头部对响应的编码方式。

print(res.encoding)  #查看网页返回的字符集类型
print(res.apparent_encoding) #自动判断字符集类型

输出结果为:

可以发现R equests 推测的文本编码(也就是网页返回即 爬取下来后的编码转换 )与 源网页编码不一致,由此可知其正是导致乱码原因。

二、乱码背后的奥秘

当源网页编码和爬取下来后的编码转换不一致时,如源网页为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 等编码也可以。

也可以这样来理解:字符串是由字符构成,字符在计算机硬件中通过二进制形式存储,这种二进制形式就是编码。如果直接使用 “字符串↔️字符↔️二进制表示(编码)” ,会增加不同类型编码之间转换的复杂性。所以引入了一个抽象层,“字符串↔️字符↔️与存储无关的表示↔️二进制表示(编码)” ,这样,可以用一种与存储无关的形式表示字符,不同的编码之间转换时可以先转换到这个抽象层,然后再转换为其他编码形式。在这里,unicode 就是 “与存储无关的表示”,utf—8 就是 “二进制表示”。

三、乱码的解决方法

根据原因来找解决方法,就非常简单了。

方法一:直接指定res.encoding

import requests

url = "http://search.51job.com"
res = requests.get(url)
res.encoding = "gbk"
html = res.text
print(html)

方法二:通过 res.apparent_encoding属性指定

import requests

url = "http://search.51job.com"
res = requests.get(url)
res.encoding = res.apparent_encoding
html = res.text
print(html)

方法三:通过编码、解码的方式

import requests

url = "http://search.51job.com"
res = requests.get(url)
html = res.text.encode('iso-8859-1').decode('gbk')
print(html)

输出结果:

基本思路三步走:确定源网页的编码A---gbk、 程序通过编码B--- ISO-8859-1 对源网页数据还原、 统一转换字符的编码C-utf-8。至于为啥为出现统一转码这一步呢? 网络爬虫系统数据来源很多,不可能使用数据时,再转化为其原始的数据,假使这样做是很废事的。所以一般的爬虫系统都要对抓取下来的结果进行统一编码,从而在使用时做到一致对外,方便使用。

比如如果我们想讲网页数据保存下来,则会将起转为utf-8,代码如下:

with open("a.txt",'w',encoding='utf-8'as f:
    f.write(html)

关于网络爬虫乱码问题,本文不仅给出了一个解决方案,还深入到其中的原理,由此问题引申出很多有意思的问题,如,utf-8、gbk、gb2312的编码方式怎样的?为什么这样转化就可以解决问题?

Python中文社区作为一个去中心化的全球技术社区,以成为全球20万Python中文开发者的精神部落为愿景,目前覆盖各大主流媒体和协作平台,与阿里、腾讯、百度、微软、亚马逊、开源中国、CSDN等业界知名公司和技术社区建立了广泛的联系,拥有来自十多个国家和地区数万名登记会员,会员来自以公安部、工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司,全平台近20万开发者关注。

Python迭代器使用详解

一文读懂Python可迭代对象、迭代器和生成器

用Python爬取金融市场数据

搭建CNN模型破解网站验证码

用Python进行图文识别(OCR)

投稿邮箱:pythonpost@163.com

点击下方 阅读原文 免费成为 数据科学 俱乐部 会员

相信大家通过前几篇文章,已经了解了 MySQL 字符集使用相关注意事项。那么数据 问题 在这儿显得就非常简单了,或许说可能不会出现这样的 问题 。 数据之所以会 码,在 MySQL 里无非有以下几类情况: 一、转码失败 在数据写入到表的过程中转码失败,数据库端也没有进行恰当的处理,导致存放在表里的数据 码。 针对这种情况,前几篇文章介绍过客户端发送请求到服务端。 其中任意一个编码不一致,都会导致表里的数据存入不正确的编码而产生 码。 比如下面简单一条语句: set @a = "文本字符串"; insert i.
libcurl是一个很好的Windows系统中RESTFul测试库。 但是,如果在Windows的命令行(console)环境下执行,则会出现中文 码的 问题 。这个是因为一般网页端的编码格式为UTF-8,而Windows的console环境,编码格式为GBK。 因此,需要用到编码转换工具LibIconv转码所需文件 iconv.exe libcharset1.dll libiconv2.dll
近日使用了libcurl这个库,功能强大、使用方便就不多说了。在使用过程中还是遇到挺多的 问题 的,无奈libcurl开发文档(貌似没有,index.html也没有错误解决部分)实在看不懂,因此为一些小 问题 耽搁了不少时间。比如libcurl的中文 问题 ~~。         遇到这 问题 时,我想多半是文件的编码 问题 ,于是我将保存有libcurl下载的网页源码的文件执行“另存为”操作,编码方式改为AN
相信大家在爬虫网站的时候,网页的源代码会出现 问题 ,如何解决呢?本文带你探讨一下关于一些 码的处理方法,基本大多数语言 问题 处理的方式是差不多的,所以只说一个可以了。 问题 的出现 就以爬取 51job网站举例,讲讲为何会出现“ 码” 问题 ,如何解决它以及其背后的机制。 [import](http://www.yidianzixun.com/channel/w/import) reque...
//在数据头设置字符集为UTF-8,解决中文 问题 struct curl_slist *head = NULL; head = curl_slist_append(head, "Content-Type:application/x-www-form-urlencoded;charset=UTF-8"); curl_easy_setopt(curl, CURLOPT_HTT
在Linux下,当使用 libcurl 库发送邮件时,发现 windows 下的 foxmail 接收邮件 码,而浏览器端不 码。 解决办法: 内容类型和 utf-8 编码设置 在设置邮件内容 "To: ", 'From: ' 等内容之前添加: "content-type:text/plain;charset=utf-8\r\n"即可 此外,如果你想发送 html 格式的邮件内容,可以设
中文转ascii码 char[] descriptionCharArray = jo.getString("alertContent").toCharArray(); StringBuffer sbDescription = new StringBuffer(); for (int j = 0; j < descriptionCharArray.length; j++) { if(j !=...
使用eclipse时,eclipse打开properties文件,原本应该显示中文,却显示ASCII码,通过安PropertiesEditor来解决中文显示ASCII码的 问题 。 1.打开eclipse的hellp=>Install New Software 2.添加插件PropertiesEditor,输入名字和地址 名字:properties 地址:http://propedit.
Python 是一种简洁而强大的编程语言,广泛应用于各个领域。学习 Python 可以帮助我们更高效地进行数据处理、学术研究、软件开发等工作。由于 Python 的易学性和丰富的库支持,想要深入学习 Python 是一个不错的选择。 当我们想要深入学习 Python 时,有许多学习资源可供选择,其中之一就是 深入浅出 Python 的PDF下载。 首先,通过PDF下载的方式,我们可以方便地将学习材料保存到本地,随时随地进行学习。不论是在交通工具上、等候时间中还是在家中,我们都可以打开PDF进行学习,提高学习的效率。 其次, 深入浅出 Python 作为一本优质的学习教材,通过PDF下载可以让我们拥有完整的学习内容。这本书适合初学者,可以帮助我们了解 Python 语言的基础知识和核心概念。通过系统的学习,我们可以获得更全面的知识结构。 同时,PDF下载也提供了便捷的检索功能,让我们能够快速地找到需要的学习内容。如果忘记了某个概念或方法的具体用法,只需打开PDF并使用搜索功能,就能够迅速找到相关内容,解决疑惑。 最后, 深入浅出 Python 的PDF下载免费,我们不需要花费额外的金钱购买或订阅。将有限的学习资源用于其他的学习方面,使我们更容易进一步深入学习 Python 。 综上所述, 深入浅出 Python PDF下载是一种方便、全面、免费的学习资源,能够帮助我们深入学习 Python 编程语言,提高我们的编程能力。推荐对 Python 感兴趣的朋友们利用PDF下载的方式进行学习,探索更多 Python 编程的奥秘。