一句话概括本文:
本节讲解 Requests 库的常见使用, 以及一个实战项目:
扒取某一篇微信文章里所有的图片, 视频, 音频
尤其在扒取视频和音频的时候思考非常好玩~
配图: 给凉了的大 A 站上香:
引言:
刚学爬虫没多久的时候就知道 requests 这个 HTTP 库了, 不过
因为自己觉得学习新的库需要一定的时间成本, 而且自带的
urllib 写写小爬虫够用, 就没去深入学, 在写上一节的
时候评论有人就提到了 requests, 除了那个 Referer 的坑
外, 在使用 urllib 的时候就遇到一些很繁琐的东西了,
举几个例子:
发送 Get 和 Post 请求
Cookie 处理
设置代理
还有一点 urllib 默认不支持压缩, 要返回压缩格式, 必须在
请求头里写明 accept-encoding, 然后获取返回数据时要在
响应头里是否有 accept-encoding 以此判断是否需要解码,
非常繁琐...
当然你可以自己对 urllib 进行一些常用的封装, 以此规避此类
问题恰逢前几天, 看到我妹蹲在电脑前在呆呆地重复做些
什么事情, 好奇的问了下她:
我妹:
保存微信文章里的图片, 音频, 视频啊, 写公司的文章要用到
我: 这么呆???
是的, 她就这样重复每一篇文章:
右键图片保存, 视频打开 chrome f12 找到 flash 里的视频链接,
然后再发到 http://v.ranks.xin / 解析, 得到下载的 url, 再进行下载
作为技术宅的欧尼酱, 肯定要写个小脚本来帮她脱离这种
重复性的劳动, 作为交换条件, 她需要打扫一周卫生
所以就有了这个实战例子~
(PS: 某宝上有这样的工具, 竟然卖 10 块钱, 还有人买, 2333)
1.Requests 简介
(本节只讲述常用的姿势, 更多内容可到官方文档中翻阅~)
作者: Kenneth Reitz
Gayhub 地址: https://github.com/kennethreitz
官方仓库: https://github.com/requests/requests/
官方文档: http://www.python-requests.org/en/master/
Feature Support:
International Domains and URLs 国际化域名和 URL
Keep-Alive & Connection Pooling Keep-Alive & 连接池
Sessions with Cookie Persistence 带持久 Cookie 的会话
Browser-style SSL Verification 浏览器式的 SSL 认证
Basic/Digest Authentication 基本 / 摘要式的身份认证
Elegant Key/Value Cookies 优雅的 key/value Cookie
Automatic Decompression 自动解压
Automatic Content Decoding 自动内容解码
Unicode Response Bodies Unicode 响应体
Multipart File Uploads 文件分块上传
HTTP(S) Proxy Support HTTP(S)代理支持
Connection Timeouts 连接超时
Streaming Downloads 流下载
.netrc Support 支持. netrc
Chunked Requests Chunked 请求
有些听都听不懂, 感觉很牛逼的样子, 不方, 跟着小猪撸一遍就好~
先通过 pip install request 安装一波库, 然后就可以开始玩了!
2. 三分钟上手 requests
- # 1. 支持各种请求方式: GET,POST,PUT,DELETE,HEAD,OPTION
- r1 = requests.get("http://xxx", params={"x": 1, "y": 2})
- r2 = requests.post("http://xxx", data={"x": 1, "y": 2})
- r3 = requests.put("http://xxx")
- r4 = requests.delete("http://xxx")
- r5 = requests.head("http://xxx")
- r6 = requests.options("http://xxx")
注意:
URL 链接里有中文会自动转码
post 时如果传递的是一个 str 而不是一个 dict, 会直接发送出去!(比如 json 字符串)
2.4.2 版新增: 可以通过 json 参数传递 dict, 自动会把 dict 转换为 json 字符串!
post 上传文件可以通过 file 参数, 如 post(url, files={'file': open('report.xls', 'rb')})
请求的相关设置:
请求头: headers={'xxx':'yyy'}
代理: proxies={'https':'xxx'}
超时(单位秒):timeout=15
处理返回结果
注: 由 requests 发起的请求, 当相应内容经过 gzip 或 deflate 压缩时,
requests 会自动解包, 可以获得通过 content 获得 byte 方式的响应结果
status_code: 获取状态码
reason: 状态信息
url: 获取请求的 url
content: 获取 byte 类型的返回结果, 相当于 urllib.urlopen().read;
raw: 获得原始的返回结果, 请求里需要设置 stream=True;
text: 获取 str 类型的返回结果, 会自动根据响应头部的字符编码进行解码;
可以调用 r.encoding 获得编码方式, 或者在调 text 之前先 r.encoding='编码'
设置编码类型, text 就会按照对应的编码进行解析;
json: 解析序列化为 JSON 格式的数据, 直接就可以 ['xxx'] 拿数据了,
如果解析错误会抛出异常: ValueError: No JSON object could be decoded
除此之外还可以调用 headers 获得响应头比如:
- r = requests.get('http://gank.io/api/data / 福利 / 50/1')
- # 直接根据键获得值
- print(r.headers.get('Date'))
- # 遍历获得请求头里所有键值
- for key, value in r.headers.items():
- print(key + ":" + value)
如果是想获取请求头信息的话: 调用 r.request.headers 就可以获取了
除此之外还有 raise_for_status(), 当响应码不是 200 的时候, 会抛出
HTTPError 异常, 可用于响应码校验;
Cookie:
通过 r.cookies 即可获得 RequestsCookieJar 对象, 行为与字典类似;
如果想带着 cookies 去访问, 可以在请求里添加 cookies={'xxx':'yyy'}参数;
也可以通过 requests.cookies.RequestsCookieJar()调用 set 方法进行构造,
比如: jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere'), 可以调用下述方法遍历 cookies:
- for c in r.cookies:
- print(c.name + ":" + c.value)
附: CookieJar 与字典间的互转
- # 字典 -> CookieJar
- cookies = requests.utils.cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True)
- # CookieJar-> 字典
- cookies = requests.utils.dict_from_cookiejar(r.cookies)
重定向与请求历史:
除了 HEAD 请求, Requests 会自动处理所有重定向, 可以在执行请求的时候
使用
allow_redirects = False
禁止重定向, 可以调用 history 函数追踪请求
历史, 一个 Response 对象的列表, 按照最老到最近的请求进行排序
错误与异常:
注: Requests 显式抛出 的异常都继承自 requests.exceptions.RequestException
1. 遇到网络问题, 会抛出 ConnectionError 异常
2. 请求超时, 会抛出 Timeout 异常
3. 请求超过了设定的最大重定向次数, 会抛出 TooManyRedirects 异常
Session 会话对象:
用于跨请求保持一些参数, 最常见的就是保留 cookies,
Session 对象还提供了 Cookie 持久化和连接池功能,
- s = request.Session() # 建立会话
- s.post('http://xxx.login',data={'xx':'xx'}) # 登录网址
- s.get('http://xxx.user') # 登录后才能访问的网址
- s.close() # 关闭会话
3.Requests 实战: 抓取微信文章的图片与视频
推理分析环节:
随手打开一个微信链接: http://mp.weixin.qq.com/s/JHioeDcopm-98R5lGVemqw
1. 标题拿来做文件夹名字, 很好拿, 直接 title 标签
2. 获取图片: 不难发现图片的标签是这样的
可以通过下面这段代码拿到:
然后呢, 图片可能是 PNG,JPEG 或者 GIF, 观察 data-src 可以看到:
尾部有个 wx_fmt=jpeg,split['='][-1]就能拿到文件格式, 图片名的
话: url.split("/")[-2], 就有了这样一段下载图片的代码:
3. 获取音频:
这个就需要取巧了, 直接看网页结构的话:
src 里的链接粘贴赋值是不能打开的, 这个 mpvoice 貌似是采用的是
js 渲染模块方案, 安卓狗表示不知道是什么, 有兴趣的可以看下这篇
文章: http://m.dian321.com/keji/1174796.html
感觉一时半伙也找不出规则, 要不走一波手机抓包?
啧啧, 原来就这么简单, 所有只需要拿到 mediaid 就可以啦,
而刚好就是 voice_encode_fileid 属性, 然后音频名就直接用
时间戳. mp3 的格式来命名把, 所以有了下面两段代码:
4. 获取视频:
这个就不好搞了, 内嵌在 iframe 里, 貌似是一个 flash 播放器
复制了下 url, 网页重新打开:
同样是拿不到, 手机抓一波包?
看到 vkey 这么长, 猜都猜到是加密后的东西了, 要去推敲不知
得花到何年何月了, 有没有什么取巧的办法呢? 对了, 差点忘
了我妹用的那个视频链接获取网站 http://v.ranks.xin / 了
贴视频地址, 然后解析视频, 就可以得到可下载的视频超链接了,
把前面那个 src 的链接贴下, 清下 chrome 解析那里, 然后准备抓包,
点下解析后, 可以看到发出了一个这样的请求:
点开, 咦, 这不是上一节我们刚了解的 Ajax 动态加载技术吗?
一点不方, 还有点鸡冻,()/
看下 Preview, 哟哟, 这难道是我们想要的超链接?
复制粘贴, 右键看下能否另存为?
稳如狗, 接着就来一波解析, 还有下载视频的代码咯:
核心的东西就这些啦, 接着就简单了, 写一个无限 While 循环,
然后获取用户的输入, 然后输入 Q 直接 exit()就可以了~
随手试两篇文章, 运行结果:
可以, 很 Gay, 都抓到了, 美滋滋~
另外如果出现 Max retries exceeded with url 这样的异常, 可能就是
你的 requests 库太旧了, 可以走一波: pip install --upgrade requests
进行升级
4. 使用 pyinstaller 生成 exe 文件
脚本是有了, 你也不可能在我妹电脑上装个 Python 环境吧?
可以通过 pyinstaller 来生成一波 exe 文件, 然后就可以在我
妹的渣渣 win 本上运行了
键入: pip install pyinstaller, 安装 pyinstaller
新建一个文件夹, 然后把我们的脚本拷进去, 我们还可以弄个应用图标:
接着命令行走一波:
pyinstaller - F - i wechat.ico CatchWeChatRes.py
执行成功后能看到文件夹下多了几个文件:
如果正常生成了 exe 文件的话, 是可以在 dist 目录下找到的
双击执行, 贴个文章的 url:
成功下载到本地, 没毛病~
Tips:
-i 是可选参数, 代表有错误也继续执行
-w 如果不需要命令行, 可以加上 - w
编译中途出现过这个错误:
执行不了脚本, 后来发现是手多在文件里 import 了无关模块, 删掉就可以了;
5. 小结
本来昨天就应该写完了, 因为公司搬家的原因, 还有因为太冷
起不了床的原因, 拖到下午才补完, 尴尬~
后面会学 Python 里自带的图形化模块 Tkinter, 到时再拼凑一个
简单的图形化界面界面吧~
本节源码下载
https://github.com/coder-pig/ReptileSomething
来啊, Py 交易啊
欢迎各种像我一样的 Py 初学者, 或者 Py 大神加入,
一起愉快地交流学习:
因为微信群二维码隔一段时间就过期了, 如果二维码过期可加我,
我拉你进群, 懒得换二维码了~
来源: http://www.jianshu.com/p/1a72986e6484