cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是‘谁’了。
cookie虽然在一定程度上解决了‘保持状态’的需求,但是由于cookie本身最大支持4096字节,以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,他能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session
cookie存储到客户端
优点:数据存储在客户端。减轻服务端的压力,提高网站的性能
缺点:安全性不高,在客户端很容易被查看或破解用户会话信息
当客户端浏览器第一次请求服务器时,服务器会再response中设置一个Set-Cookies的字段,用来标记用户的身份,客户端浏览器会把cookies放在请求头中一起提交给服务器,服务器检查该Cookies即可找到对应的会话是什么,再通过判断会话来辨认用户的状态。
当我们成功登录网站时,网站会告诉客户端应该设置哪些Cookies信息,以保持登录状态。如果客户端浏览器传给服务器的cookies无效或者会话过期,可能就会收到错误的响应或者跳转到登录页面重新登陆
requests模块处理cookie相关的请求
爬虫中使用cookie
为了能够通过爬虫获取到登陆后的页面,或者是解决通过cookie的反扒,需要使用reques来处理cookie相关的请求
爬虫中使用cookie的利弊
带上cookie的好处
能够访问登陆后的页面
能够实现部分反反爬
带上cookie的坏处
一套cookie往往对应的时一个用户的信息,请求太频繁有更大的可能性被对方识别为爬虫
那么上面的问题如何解决? 使用多个账号
requests处理cookie有三种方法:
cookie字符串放在headers中
吧cookie字典放传给请求方法的cookies参数接收
使用requests提供的session模块
注意:cookie有过期时间,所以直接复制浏览器中的cookie可能意味着下一程序继续运行的时候需要替换代码中的cookie,对应的我们也可以通过一个程序专门来获取cookie供其他程序使用;当然也有很多网站的cookie过期时间很长,这种情况下,直接复制cookie来使用更加简单
使用cookies参数接收字典形式的cookie
cookies的形式:字典
cookies={'cookie的name':'cookie的value'}
使用方法:requests.get(url,headerss=headers,cookies=cookie_dict}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
使用requests.session处理cookie
前面使用手动的方式使用cookie,那么有没有更好的方法在requests中处理cookie呢?
requests提供了一个叫做session类,来实现客户端和服务端的会话保持
会话保持有两个内涵:
保存cookie,下一次请求会带上前一次的cookie
实现和服务端的长连接,加快请求速度
使用方法
session=requests.session()
response=session.get(url,headers)
session实例在请求了一个网站后,对方服务器设置在本地的cookie会保存在session中,下一次再使用session请求对方服务器的时候,会带上前一次的cookie
小结:
cookie字符串可以放在headers字典中,键为Cookie,值为cookie字符串
可以把cookie字符串转化为字典,使用请求方法的cookies参数接收
使用requests提供的session模块,能够自动实现cookie的处理,包括请求的时候携带cookie,获取响应的时候保存cookie
requests中的cookirJar的处理方法
requests处理证书错误
使用requests获取的response对象,具有cookies属性,能够获取对方服务器设置在本地的cookie,但是如何使用这些cookie呢?
方法介绍:
response.cookies时CookieJar类型
使用requests.utils.dict_from_cookiejar,能够实现吧cookiejar对象转化为字典
为了在代码中能够正常的请求,我们修改添加一个参数
import requests
url='https://www.12306.cn/mormhweb/'
response=requests.get(url,verify=Fasle)
超时参数的使用
超时参数使用方法如下:
response=requests.get(url,timeout=3)
通过添加timeout参数,能够保证在3秒钟内返回响应,否则会报错
注意:
这个方法还能够拿来检测代理ip的质量,如果一个代理ip在很长时间没有响应,那么添加超时之后也会报错,对应的这个ip就可以从代理ip池中删除
使用超时参数能够加快我们整体的请求速度,但是在正常的网页浏览过成功,如果发生速度很慢的情况,我们会做的选择是刷新页面,那么在代码中,我们是否也可以刷新请求呢?
对应的,retrying模块就可以帮助我们解决
使用retrying模块提供的retry模块
通过装饰器的方式使用,让被装饰的函数反复执行
retry中可以传入参数stop_max_attemp_number,让函数报错后继续重新执行,达到最大执行次数的上限,如果每次都报错,整个函数报错,如果中间有一个成功,程序继续往后执行
retrying和requests的简单封装
实现一个发送请求的函数,每次爬虫中直接调用该函数即可实现发送请求,在其中
使用timeout实现超时报错
使用retrying模块实现重试
代码参考:
import requests
from retrying import retry
#最大重试3次,3次全部报错,才会报错
@retry(stop_max_attempt_number=3)
def _parse_url(url):
#超时的时候会报错并重试
response=requests.get(url,headers=headers,timeout=3)
#状态码不是200,也会报错并重试
assert response.status_code==200
return response
def parse_url(url):
try:#进行异常捕获
response=_parse_url(url)
except Exception as e:
print(e)
#报错返回None
response=None
return response
小结
requests.utils.dict_from_cookiejar能够实现cookiejar转化为字典
请求方法中添加verify=False能够实现请求过程中不验证证书
请求方法中添加timeout能够实现强制程序返回结果,否则会报错
retrying模块能够实现捕获函数的异常,反复执行函数的效果,和timeout配合使用,能够解决网络波动带来的请求不成功的问题
@retry(stop_max_attempt_number=3)
def getHTML(url):
在函数内出错误后才执行第二次、第三次 如果函数内没有错误 就只执行一次 报错后后面的代码不执行