在使用request模块写爬虫爬取教务处信息时,cookie过一段时间便会自动失效,这时爬虫程序就无法继续运行,让人很是无奈。

我们知道,cookie里面保存着我们的身份信息,网站服务器通过cookie来识别我们的身份,为了安全,一般cookie都会有有效时间,过了这个时间,则cookie会自动失效,此时,服务器便无法识别我们身份,这时如果我们请求一个需要登录才能查看的资源,网站会自动跳转到登录界面。

刚开始想到的方法是使用服务器返回的url信息判断是否与发送的url相等,如果两个url相等,则说明cookie依然有效,如果两个url不想等则说明发生了跳转,也就是cookie已经失效了,这时我们再次手动输入cookie,通过手动更新cookie可以让程序继续运行,下次失效后则再次手动输入,代码如下:

1
2
3
4
5
6
if r.url == pic_url:
break
else:
print 'Please input another Cookie:'
headers['Cookie'] = raw_input()
s.headers.update(headers)

这个方法虽然算是一个解决办法,但是当需要的数据量大时,程序运行时间很长时,我们总不能守在电脑旁看着程序运行,时刻监视着cookie是否已经失效吧!

通过多方搜索,找到了如下解决办法:查阅文档得知,request中提供了一个高级用法:session

session会话对象让你能够跨请求保持某些参数。它也会在同一个Session实例发出的所有请求之间保持cookies。

也就是session可以自动更新请求时的headers,这功能真是让我喜出望外,立刻改写了程序去试了试,
但是…………
事实很残酷,虽然我们使用了session对象,cookie依旧会失效。
到底是request文档出错了还是我的使用方法错了?

在谷歌上查找半天,终于发现了问题所在,session确实会根据服务器响应的信息自动更新下次请求的headers,但是,它并不是简单的覆盖原来的headers,而是与程序中我们自己设置的原来的headers合并,而且,用户设置的优先度更高,也就是说,合并时,新的cookie被丢弃了,而我们设置的旧的cookie却保留下来了。所以程序中的cookie依旧会失效,因为cookie一直没有更新嘛!

找到了问题出现的原因,也就找到了解决方法:请求后自行更新cookie,代码如下:

1
2
3
r = s.get(pic_url,timeout=40)   #GET命令获取图片
if r.cookies.get_dict(): #保持cookie有效
s.cookies.update(r.cookies)

这样cookie即可保持一直有效。
关于完整版代码,请查看我github中的spider_photos_nuaa项目