一、前言
Python爬虫新手不可逃避又很烦人的事:响应数据的类型和编码问题!
-
数据类型又出错了?
-
数据编码又不对了?
-
怎么全都是乱码?
我也不例外,已经被python爬虫的数据类型和编码坑了无数次!但每次都是得过且过,解决完又不总结原因,下次遇到还得调试。这一次决定痛定思痛,一锅端了这个烦人的知识盲区!
想学会如何正确处理响应数据的不同类型和编码,得先摸清楚响应数据的类型和编码的原理。
二、响应数据的类型
在讲数据类型之前,先举个例子:你在网上购物,商品在商家发货前,商品会放在包装盒里,包装盒会放在包装袋里,包装袋会放在快递盒里。经过快递员送达到你手上后,你会先拆快递盒拿出包装袋,再拆包装袋拿出包装盒,最后拆包装盒拿出商品。
其实数据在网络中传输,就好像你网购的商品一样。在服务器发出之前,先将数据进行JSON格式编码,然后进行字符编码,最后进行压缩。终端接收到数据后,先进行解压,然后进行字符解码,最后进行JSON格式解码。
终端接收到的数据就是原始流式数据,原始流式数据被解压后就是字节类型数据,字节类型数据再被字符解码后则是文本类型数据,文本类型数据最后被JSON格式解码得到JSON格式数据。
这所说的原始流式、字节类型、文本类型和JSON格式就是响应数据的4种类型。
三、响应数据的编码
这里说的数据编码指的是字符编码,编码问题主要出现在获取文本类型数据过程中,编码的原理之前也已经写过,这里就不重复了,大家可以参考以前的两篇文章:
四、Requests获取不同类型和编码的数据
(一)获取原始流式的响应数据
先在请求中设置参数stream=Ture
,然后通过访问Response.raw
即可获取到原始的响应数据。代码如下:
>>> r = requests.get('https://api.github.com/events', stream=True)
>>> r.raw
<urllib3.response.HTTPResponse object at 0x101194810>
>>> r.raw.read(10)
b'x1fx8bx08x00x00x00x00x00x00x03'
(二)获取字节类型的响应数据
通过Response.content
可以获取到字节类型的响应数据,并且会自动解压gzip、deflate、br格式的压缩数据(解压br格式的数据需要先安装像brotli或者brotlicffi库)。代码如下:
>>> r.content
b'[{"repository":{"open_issues":0,"url":"https://github.com/...
你可以将字节类型的响应数据保存成一张图片,实现图片下载,代码如下:
>>> from PIL import Image
>>> from io import BytesIO
>>> i = Image.open(BytesIO(r.content))
你可以将字节类型的响应数据保存成一个文件,实现流媒体下载,代码如下:
with open(filename, 'wb') as fd:
for chunk in r.iter_content(chunk_size=128):
fd.write(chunk)
Response.iter_content
是对Response.content
的遍历,其中chunk_size可以自由调整为一个适合的数字。
参考案例:一个妹子套图python爬虫(完整源码)
(三)获取文本类型的响应数据
通过Response.text
可以获取到文本类型(字符串类型)的响应数据,并且会自动解压(gzip、deflate、br格式)和解码(ASCII、GBK、UTF-8编码)数据。代码如下:
>>> import requests
>>> r = requests.get('https://api.github.com/events')
>>> r.text
'[{"repository":{"open_issues":0,"url":"https://github.com/...
Requests库是根据HTTP协议头来判断响应数据的编码,然后在你访问Response.text
时进行解码。因此,你可以通过Response.encoding
查看并改变编码。
>>> r.encoding
'utf-8'
>>> r.encoding = 'ISO-8859-1'
例如,HTML和XML的编码可以在数据主体中确定,你可以先使用Response.content
查找正确的编码,然后再通过Response.encoding
进行设置。
参考案例:Python爬虫|4399最新小游戏
(四)获取JSON格式的响应数据
Requests库有内置的JSON解码器,通过Response.json()
可以获取响应数据并解码成JSON数据。
>>> import requests
>>> r = requests.get('https://api.github.com/events')
>>> r.json()
[{'repository': {'open_issues': 0, 'url': 'https://github.com/...
-
如果JSON解码失败,
Response.json()
将引发requests.exceptions.JSONDecodeError
异常。(如:204响应、响应包含无效的JSON数据) -
如果JSON解码成功,也不代表请求成功,因为有的服务器即使请求失败也会返回一个JSON对象。(如:500响应)
只有Response.raise_for_status()
或者Response.status_code
才能确定请求是否成功!
参考案例:Python威武!比亚迪官网全系车型
五、最后总结
-
原始流式:极少会用到;
-
字节类型:使用Response.content,可用来获取图片、音频、视频等非文本类数据;
-
文本类型:使用Response.text,可用来获取字符串文本类数据(可使用r.encoding设置编码);
-
JSON格式:使用Response.json(),可用来获取JSON数据。
原文始发于微信公众号(愤怒的it男):被python爬虫的数据类型和编码坑了无数次!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/249183.html