python 爬虫如何正确的使用cookie


Posted in Python onOctober 27, 2020

很多时候,我们要查看的内容必须要先登录才能找到,比如知乎的回答,QQ空间的好友列表、微博上关注的人和粉丝等。要使用爬虫直接登录抓取这些信息时,有一个不太好解决的难题,就是这些网站设置的登录规则以及登录时的验证码识别。不过,我们可以想办法绕过去,思路是这样的:先使用浏览器登录,从浏览器获取登录后的“凭证”,然后将这个“凭证”放到爬虫里,模拟用户的行为继续抓取。这里,我们要获取的凭证就是cookie信息。

这次我们尝试使用python和cookie来抓取QQ空间上的好友列表。使用的工具是FireFox浏览器、FireBug和Python。

获取cookie

打开FireFox浏览器,登录QQ空间,启动FireBug,选择FireBug中的Cookies页签,点击页签中的cookies按钮菜单,选择“导出本站点的cookie”即可完成cookie的导出。

python 爬虫如何正确的使用cookie

导出cookie会以一个名为cookies.txt文本文件形式存在。

程序实现

然后我们会使用获取的cookie新建一个opener来替换之前请求时使用的默认的opener。将获取的cookies拷贝到程序目录下,编写脚本如下:

#!python
# encoding: utf-8
from http.cookiejar import MozillaCookieJar
from urllib.request import Request, build_opener, HTTPCookieProcessor
 
DEFAULT_HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0"}
DEFAULT_TIMEOUT = 360
 
 
def grab(url):
    cookie = MozillaCookieJar()
    cookie.load('cookies.txt', ignore_discard=True, ignore_expires=True)
    req = Request(url, headers=DEFAULT_HEADERS)
    opener = build_opener(HTTPCookieProcessor(cookie))
    response = opener.open(req, timeout=DEFAULT_TIMEOUT)
    print(response.read().decode('utf8'))
 
 
if __name__ == '__main__':
    grab(<a href="http://user.qzone.qq.com/QQ号/myhome/friends" rel="external nofollow" >http://user.qzone.qq.com/QQ号/myhome/friends</a>)

因为我们使用的是FireFox浏览器导出的cookie文件,所以这里使用的cookieJar是MozillaCookieJar。

执行脚本…然而报错了:

Traceback (most recent call last):
  File "D:/pythonDevelop/spider/use_cookie.py", line 17, in <module>
    start()
  File "D:/pythonDevelop/spider/use_cookie.py", line 9, in start
    cookie.load('cookies.txt', ignore_discard=True, ignore_expires=True)
  File "D:\Program Files\python\python35\lib\http\cookiejar.py", line 1781, in load
    self._really_load(f, filename, ignore_discard, ignore_expires)
  File "D:\Program Files\python\python35\lib\http\cookiejar.py", line 2004, in _really_load
    filename)
http.cookiejar.LoadError: 'cookies.txt' does not look like a Netscape format cookies file

问题出在cookies文件上,说是不像一个Netscape格式的cookie文件。不过也好解决,只需要在cookies文件开始一行添加如下内容即可:

# Netscape HTTP Cookie File

通过这行内容提示python cookie解析器这是一个FireFox浏览器适用的cookie。

再次执行,还是会报错,因为比较长我就只贴关键的部分出来:

http.cookiejar.LoadError: invalid Netscape format cookies file 'cookies.txt': '.qzone.qq.com\tTRUE\t/\tFALSE\tblabla\tdynamic'

意思是cookie中某些行存在格式错误。具体错在哪儿,需要先了解下FireFox浏览器的cookie格式。MozillaCookieJar认为每行cookie需要包含以下信息,每条信息以制表符分隔:

名称 domain domain_specified path secure expires name value
类型 字符串 布尔型 字符串 布尔型 长整型 字符串 字符串
说明 域名 适用路径 是否使用安全协议 过期时间 名称

其中domain_specified是什么意思我不很清楚,以后弄明白了再补上。再来看看我们获取的cookie的部分行:

user.qzone.qq.com	FALSE	/	FALSE	814849905_todaycount	0
user.qzone.qq.com	FALSE	/	FALSE	814849905_totalcount	0
.qzone.qq.com	TRUE	/	FALSE	1473955201	Loading	Yes
.qzone.qq.com	TRUE	/	FALSE	1789265237	QZ_FE_WEBP_SUPPORT	0

前两行格式是错误的,后两行格式是正确的。前两行缺少“expires”属性。该怎么办呢——补上就好了呗。在其他的cookie中随意选一个时间补上就OK了。

补全cookie后,再次执行是正常的,没有报错。但是没有如预期的打印出好友信息,因为网址错了。使用firebug可以找出正确的网址:

https://h5.qzone.qq.com/proxy/domain/r.qzone.qq.com/cgi-bin/tfriend/friend_ship_manager.cgi?uin=QQ号&do=1&rd=0.44948123599838985&fupdate=1&clean=0&g_tk=515169388

这样就抓取到好友列表了。好友列表是一个json字符串。

python 爬虫如何正确的使用cookie

至于如何解析json,会在下一节进行说明。

动态获取cookie

cookie是有过期时间的。如果想长时间抓取网页,就需要每隔一段时间就更新一次cookie。如果都是从FireFox浏览器来手动获取显得有些笨了。从浏览器获取的cookie只是作为一个入口,之后再进行请求还是要依靠python主动获取cookie。下面是一段获取cookie的程序:

#!python
# encoding: utf-8
from http.cookiejar import CookieJar
from urllib.request import Request, HTTPCookieProcessor, build_opener
 
DEFAULT_HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0"}
DEFAULT_TIMEOUT = 360
 
 
def get(url):
    cookie = CookieJar()
    handler = HTTPCookieProcessor(cookie)
    opener = build_opener(handler)
    req = Request(url, headers=DEFAULT_HEADERS)
    response = opener.open(req, timeout=DEFAULT_TIMEOUT)
    for item in cookie:
        print(item.name + " = " + item.value)
    response.close()

在示例程序中演示了如何获取cookie,并打印了cookie的name和value两项属性。通过实例可以看到每次执行http请求都会重新获取cookie,因此可以将我们的程序调整一下:执行第一次请求时使用我们通过浏览器获取的cookie,之后的每次请求都可以使用上次请求时获取的cookie。调整后的程序:

#!python
# encoding: utf-8
from http.cookiejar import MozillaCookieJar, CookieJar
from urllib.request import Request, build_opener, HTTPCookieProcessor, urlopen
 
DEFAULT_HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0"}
DEFAULT_TIMEOUT = 360
 
 
def gen_login_cookie():
    cookie = MozillaCookieJar()
    cookie.load('cookies.txt', ignore_discard=True, ignore_expires=True)
    return cookie
 
 
def grab(cookie, url):
    req = Request(url, headers=DEFAULT_HEADERS)
    opener = build_opener(HTTPCookieProcessor(cookie))
    response = opener.open(req, timeout=DEFAULT_TIMEOUT)
    print(response.read().decode("utf8"))
    response.close()
 
 
def start(url1, url2):
    cookie = gen_login_cookie()
    grab(cookie, url1)
    grab(cookie, url2)
 
 
if __name__ == '__main__':
    u1 = "https://user.qzone.qq.com/QQ号/myhome/friends"
    u2 = "https://h5.qzone.qq.com/proxy/domain/r.qzone.qq.com/cgi-bin/tfriend/friend_ship_manager.cgi?uin=QQ号&do=2&rd=0.44948123599838985&fupdate=1&clean=0&g_tk=515169388"
    start(u1, u2)

就这样。

其他

其实在登录QQ空间时使用cookie还有另一种法子——通过观察,也可以在http 请求头中添加cookie信息。

获取请求头中cookie的方式:打开FireFox浏览器,打开FireBug并激活FireBug的network页签,在FireFox浏览器上登录QQ空间,然后在FireBug中找到登录页请求,然后就可以找到请求头中的cookie信息了。

python 爬虫如何正确的使用cookie

将cookie信息整理成一行,添加到请求头中就可以直接访问了。这个方法相对简单,减少了修改cookie文件的步骤。

此外,在一篇博客文章中还找到了直接登录QQ空间的方案。这算是已知最好的法子了,只要腾讯不改变登录规则就能很简单的执行请求获取cookie。不过年代久远,不知规则是否还适用

以上就是python 爬虫如何正确的使用cookie的详细内容,更多关于python 爬虫使用cookie的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python中的map、reduce和filter浅析
Apr 26 Python
python中快速进行多个字符替换的方法小结
Dec 15 Python
Python插件virtualenv搭建虚拟环境
Nov 20 Python
Python魔法方法功能与用法简介
Apr 04 Python
基于Python的ModbusTCP客户端实现详解
Jul 13 Python
Python with关键字,上下文管理器,@contextmanager文件操作示例
Oct 17 Python
用python中的matplotlib绘制方程图像代码
Nov 21 Python
Python3 shutil(高级文件操作模块)实例用法总结
Feb 19 Python
Python Tkinter Entry和Text的添加与使用详解
Mar 04 Python
如何实现更换Jupyter Notebook内核Python版本
May 18 Python
PyCharm 安装与使用配置教程(windows,mac通用)
May 12 Python
python超详细实现完整学生成绩管理系统
Mar 17 Python
python+requests实现接口测试的完整步骤
Oct 27 #Python
python设置中文界面实例方法
Oct 27 #Python
使用python-cv2实现Harr+Adaboost人脸识别的示例
Oct 27 #Python
基于python实现坦克大战游戏
Oct 27 #Python
Django xadmin安装及使用详解
Oct 26 #Python
python实现网页录音效果
Oct 26 #Python
python实现录音功能(可随时停止录音)
Oct 26 #Python
You might like
PHP系统流量分析的程序
2006/10/09 PHP
Yii框架日志记录Logging操作示例
2018/07/12 PHP
Javascript模块化编程(三)require.js的用法及功能介绍
2013/01/17 Javascript
jQuery控制文本框只能输入数字和字母及使用方法
2016/05/26 Javascript
基于Bootstrap的UI扩展 StyleBootstrap
2016/06/17 Javascript
Bootstrap简单表单显示学习笔记
2016/11/15 Javascript
js Canvas实现的日历时钟案例分享
2016/12/25 Javascript
基于jQuery实现选项卡效果
2017/01/04 Javascript
Vue.js:使用Vue-Router 2实现路由功能介绍
2017/02/22 Javascript
原生javascript上传图片带进度条【实例分享】
2017/04/06 Javascript
基于JavaScript实现的折半查找算法示例
2017/04/14 Javascript
js 简易版滚动条实例(适用于移动端H5开发)
2017/06/26 Javascript
vue服务端渲染页面缓存和组件缓存的实例详解
2018/09/18 Javascript
微信小程序实现文字跑马灯
2020/05/26 Javascript
使用layui定义一个模块并使用的例子
2019/09/14 Javascript
layui use 定义js外部引用函数的方法
2019/09/26 Javascript
javascript解析json格式的数据方法详解
2020/08/07 Javascript
[02:01]BBC DOTA2国际邀请赛每日综述:八强胜者组鏖战,中国队喜忧参半
2014/07/19 DOTA
[08:54]DOTA2-DPC中国联赛 正赛 Aster vs LBZS 选手采访
2021/03/11 DOTA
Python 3.x 新特性及10大变化
2015/06/12 Python
Python之文字转图片方法
2018/05/10 Python
Python用于学习重要算法的模块pygorithm实例浅析
2018/08/16 Python
Python处理session的方法整理
2019/08/29 Python
python集合常见运算案例解析
2019/10/17 Python
Python 使用threading+Queue实现线程池示例
2019/12/21 Python
python 实现Flask中返回图片流给前端展示
2020/01/09 Python
python实现读取类别频数数据画水平条形图案例
2020/04/24 Python
Jupyter Notebook安装及使用方法解析
2020/11/12 Python
总结python 三种常见的内存泄漏场景
2020/11/20 Python
HTML5 FileReader对象的具体使用方法
2020/05/22 HTML / CSS
迟到检讨书300字
2014/02/14 职场文书
企业优秀员工事迹材料
2014/05/28 职场文书
小学生国庆节演讲稿
2014/09/05 职场文书
教师师德师风整改措施
2014/10/24 职场文书
Javascript中async与await的捕捉错误详解
2022/03/03 Javascript
CSS浮动引起的高度塌陷问题
2022/08/05 HTML / CSS