在python爬虫中如何处理cookie和session

使用python开发爬虫的过程中,遇到需要登录鉴权的一些页面,必不可少的会接触到cookie和session的使用。本文结合自己最近一次爬虫爬坑的经历,介绍在python爬虫中如何使用Cookie和Session
在这里插入图片描述

Cookie和Session的介绍

Cookie

Cookie 是一种用于跟踪用户会话信息的小型文本文件。它由服务器发送到用户的浏览器,然后由浏览器存储在用户的计算机上。每当用户访问同一站点时,浏览器都会将相关的 Cookie 发送回服务器,以便服务器可以使用它来识别用户并维护用户的状态信息

Session

Session 是一种用于在服务器端存储用户状态信息的机制。与 Cookie 不同,Session 数据存储在服务器上,而不是存储在用户的浏览器中。每个会话都有一个唯一的会话标识符(Session ID),通常存储在用户的 Cookie 中,用于在用户和服务器之间唯一标识会话。

为什么要用到Cookie和Session

假如我们要去访问一些需要登录的页面,爬取需要的信息,我们有以下三中方式:

  1. 人工把浏览器页面的请求header里cookie复制下来,写到python脚本里,这个方法无法保证cookie的时效性
  2. 模拟登录请求,通过代码模拟用户登录的过程,使用requests 库来发送请求,一旦登录成功,保存cookie,后续请求携带上cookie。
  3. 同样模拟登录,但是这里不用保存cookie,使用request.Session发送请求,登录成功,后续都直接使用这个session,服务器会将你视为已登录用户,进行正常的会话。
    第2种方式比较灵活,第3种方式使用起来比较方便,就像使用浏览器登录一样,不需要再考虑cookie的管理和请求添加cookie等,直接使用session发起请求就可以,这里比较推荐第3种方式

使用session保持会话的好处

在requests中,如果直接利用get()或post()等方法的确可以做到模拟网页的请求,但是这实际上是相当于不同的会话,也就是说相当于你用了两个浏览器打开了不同的页面。

设想这样一个场景,第一个请求利用post() 方法登录了某个网站,第二次想获取成功登录后的自己的个人信息, 你又用了一次get()方法去请求个人信息页面。实际上,这相当于打开了两个浏览器,这是两个完全不相关的会话,能成功获取个人信息吗?那当然不能。有小伙伴可能说了,我在两次请求时设置一样的cookies不就行了?可以,但这样做起来显 得很烦琐,我们有更简单的解决方法。

其实解决这个问题的主要方法就是维持同一个会话,也就是相当于打开一个新的浏览器选项 卡而不是新开一个浏览器。但是我又不想每次设置cookies,那该怎么办呢?这时候就有了新的利器一Session对象。利用它,我们可以方便地维护一个会话,而且不用担心 cookies 的问题,它会帮我们自动处理好。requests模块中的Session类能够自动处理发送请求获取响应过程中产生的cookie,进而达到状态保持的目的。接下来我们就来学习它。

在python中如何使用Cookie

如果你已经有了个合法的cookie,可以直接这样使用:

requests.get(url=you_rurl, cookies=your_cookie)

后续每次请求都这样带着cookie就可以,比较繁琐,下面重点介绍如何使用Session

在python中如何使用Session

reqeust.Session()

# 新建一个会话
session = requests.Session()
# 使用这个会话发起一个请求,模拟登录
session.post(url=you_url, data={'你的参数'})
# 如果上一个请求成功,这个请求就可以直接获取到数据,因为session已经把上个请求返回的cookie自动带上了
session.get(url=you_url)

所以requests.session能自动处理 cookie , 下一次发起请求时会自动带上前一次的 cookie,不需要像使用cookie的方式一样每次都手动处理,极大的方便了请求的业务逻辑。

案例:使用session维持github会话

对这个案例进行分析有以下步骤:

  1. 对 github 登陆以及访问登陆后才能访问的页面的整个完成过程进行抓包分析,比如分析登录参数是什么
  2. 确定登陆请求的 url 地址、请求方法和所需的请求参数
  3. 部分请求参数在别的 url 对应的响应内容中,可以使用 re 模块获取
  4. 确定登陆后才能访问的页面的的 url 地址和请求方法
  5. 利用 requests.session 完成代码
import requests
import re
# 构造请求头字典
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (
KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36',}
# 实例化session对象
session = requests.session()
# 访问登陆页获取登陆请求所需参数
response = session.get(https://github.com/login, headers=headers)
authenticity_token = re.search('name="authenticity_token" value="(.*?)" />',
response.text).group(1) # 使用正则获取登陆请求所需参数
# 构造登陆请求参数字典
data = {
'commit': 'Sign in', # 固定值
'utf8': ' ', # 固定值
'authenticity_token': authenticity_token, # 该参数在登陆页的响应内容中
'login':
input('输入github账号:'),
'password':
input('输入github账号:')}
# 发送登陆请求(无需关注本次请求的响应)
session.post(https://github.com/session, headers=headers, data=data)
# 打印需要登陆后才能访问的页面
response = session.get(https://github.com/settings/profile, headers=headers)
print(response.text)

最佳实践参考

使用session需要每次打开程序都登录,但是有的时候,登录信息并没有过期,如何真正像浏览器一样,及时关闭了浏览器再重新打开,只要cookie不过期,也不需要重新登录。这里就需要把cookie做持久化,然后加载cookie到session中,这样就能通过持久化的cookie构造一个session,避免重复多次登录。

cookie持久化存储和加载

登录成功后,把session中的cookie取出做持久化存储,这里存储到文件中。保存cookie的对象是RequestsCookieJar,我们需要把他转成字典,不能直接使用__dict__方法,需要使用两个特殊函数requests.utils.dict_from_cookiejar将RequestsCookieJar转成字典,然后再使用requests.utils.cookiejar_from_dict(new_cookie_jar),可以将字典转成RequestsCookieJar,参考下面代码:

####### 持久化存储
# 转成字典
cookiejar = requests.utils.dict_from_cookiejar(request_session.cookies)
# 转成json存储到文件中
# 登录成功, session里的cookie是最全的cookiejar = requests.utils.dict_from_cookiejar(request_session.cookies)with open(cookie_path, "w") as f:json.dump(cookiejar, f, indent=True)logging.info('cookies saved to ./data/cookie.txt')####### 取出cookie加载到session
session = reqeust.Session()
with open(cookie_path, "r") as f:load_cookie = json.load(f)whv_logger.info(f"load_cookie from file: {load_cookie}")exist_cookies =  requests.utils.cookiejar_from_dict(load_cookie)session.cookies.update(exist_cookies)

完整的cookie持久化方案参考

在这里顶一个模块专门处理cookie的持久和加载,定义个全局变量request_session用来管理全局的会话。登录完成之后,调用save_cookie方法更新全局session

import json
import tracebackimport requests.utilscookie_path = './data/cookie.txt'
request_session: requests.Session = Nonedef __load_cookie():'''加载本地cookie,如果存在加载,如果不存在就返回空:param session::return:'''try:with open(cookie_path, "r") as f:load_cookie = json.load(f)logging.info(f"load_cookie from file: {load_cookie}")return requests.utils.cookiejar_from_dict(load_cookie)except Exception as e:traceback.print_exc()logging.error("failed load cookie, error:%s", e)return Nonedef get_session():global request_sessionif request_session is not None:return request_sessionelse:request_session = requests.Session()exist_cookies = __load_cookie()if exist_cookies is not None:request_session.cookies.update(exist_cookies)return request_sessiondef save_cookie():# 登录成功, session里的cookie是最全的,response返回的cookie不全cookiejar = requests.utils.dict_from_cookiejar(request_session.cookies)with open(cookie_path, "w") as f:json.dump(cookiejar, f, indent=True)logging.info('cookies saved to ./data/cookie.txt')def update_cookie():'''这个方法需要具体场景具体分析,并不一定都用到。为什么需要一个新的session# 走到这一步,说明session已经过期,重新获取session,需要重新处理下session:return:'''error_cookie_jar = requests.utils.dict_from_cookiejar(request_session.cookies)# 替换自己需要处理的cookie中的参数new_cookie_jar = {'__RequestVerificationToken': error_cookie_jar['__RequestVerificationToken']}new_cookie = requests.utils.cookiejar_from_dict(new_cookie_jar)# 清空旧的cookierequest_session.cookies.clear_session_cookies()# 填充新的cookierequest_session.cookies.update(new_cookie)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/300595.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

脱单微信群|相亲脱单支招|手把手教你脱单

群里有太多优质单身男女生,你的脱单困惑,TA可能也遇到过。抬手在群里滴滴,即刻拥有一群有过相同问题的友友和运营客服帮忙。 点我进脱单群 点击 情感脱单问题,直接私信给樱桃情感老师,保护个人隐私和提升问题解决效率…

零信任安全模型:构建未来数字世界的安全基石

在数字化转型的浪潮中,云原生技术已成为推动企业创新和灵活性的关键力量💡。然而,随着技术的进步和应用的广泛,网络安全威胁也日益严峻🔓,传统的网络安全模型已经难以应对复杂多变的网络环境。在这样的背景…

【代码随想录】哈希表

文章目录 242.有效的字母异位词349. 两个数组的交集202. 快乐数1. 两数之和454. 四数相加 II383. 赎金信15. 三数之和18. 四数之和 242.有效的字母异位词 class Solution {public boolean isAnagram(String s, String t) {if(snull || tnull || s.length()!t.length()){return …

性能优化-如何爽玩多线程来开发

前言 多线程大家肯定都不陌生,理论滚瓜烂熟,八股天花乱坠,但是大家有多少在代码中实践过呢?很多人在实际开发中可能就用用Async,new Thread()。线程池也很少有人会自己去建,默认的随便用用。在工作中大家对…

什么是GIF?MP4视频如何转换成GIF动图格式?

一,什么是GIF GIF的全称是Graphics Interchange Format,可译为图形交换格式,用于以超文本标志语言(Hypertext Markup Language)方式显示索引彩色图像,在因特网和其他在线服务系统上得到广泛应用。GIF是一种…

NzN的数据结构--二叉树part1

你叉叉,让你学数据结构你不学;你叉叉,让你看二叉树你不看。 今天我们来一起学习二叉树部分,先赞后看是好习惯。 一、树的概念及结构 1. 树的概念 树是一种非线性的数据结构,它是由n(n>0)个有…

合并主分支到子分支

参考:【Git】合并分支出现 Please enter a commit message to explain why this merge is necessary.-CSDN博客 git 如何将主分支(master)合并到子分支上_git 将主分支合并到子分支-CSDN博客 1、先切换到主分支master git checkout master 2、把主分支代码拉到本地…

【Threejs进阶教程-效果篇】1.Threejs文字与css2d/css3d技术

Threejs文字与css2d/css3d技术 学习ThreeJS的捷径学习之前先搞清楚自己想要什么样的效果贴图文字准备一张带文字的png贴图使用sprite来进行贴图实现2D始终面朝相机的文字使用planeGeometry来贴图实现3D文字使用planeGeometry来贴图实现伪3D文字动态贴图文字html2Canvas 文字几何…

Java8关于Function接口

Java学习-Function接口 1 函数式接口简介和学习地址2 两种常见的函数式接口2.1 Runnable:执行接口,不接收参数,也无返回结果。2.2 Consumer:作为消费接口,接收一个参数,无返回结果。 3 初识3.1 定义Functio…

Android详细介绍POI进行Word操作(小白可进)

poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让人喜悦的特性。 一、使用poi前准备 1.导入依赖: 亲手测过下面Android导入POI依赖的方法可用 放入这个 …

OSPF实例是什么?

OSPF实例是什么? **OSPF实例指的是一个OSPF路由进程,它是在一个设备上运行的单独的OSPF路由协议实体**。 在详细解释这个概念之前,需要了解OSPF(Open Shortest Path First)是一种内部网关协议(IGP&#x…

hive图形化客户端工具

hive准备 创建测试数据 以root用户登录,使用hive命令启动hive。 创建库 create database testhivedb; 创建表 create table testhivedb.testhivetable( id int ,name string ); 插入数据 insert into testhivedb.testhivetable values (1,cc); insert into…

Vscode连接WSL2当中的jupyter

主要解决办法参考自这篇博客 1. 在WSL当中安装jupyter 这个随便找一篇博客即可,比如这篇,也可以根据现有的环境参考其它博客内容 2. 使用jupyter创建一个虚拟环境 首先激活想要添加的虚拟环境后,输入命令安装库: pip install ipykernel …

HarmonyOS实战开发-如何实现分布式帐号相关的功能。

介绍 本示例主要展示了分布式帐号相关的功能,使用ohos.account.distributedAccount、ohos.account.osAccount等接口,实现了绑定分布式帐号、解绑分布式帐号、更新分布式帐号信息和管理分布式帐号的功能; 效果预览 使用说明 1.首次进入应用会…

Text-Driven Object Detection 关于结合文本的目标检测

1、简单介绍 首先说明,本文目的主要是水一篇CSDN博客,顺便说一下和标题相关的认识。 近几年,在目标检测领域关于多模态的目标检测工作已成了主流,趋势仍在延续,未来仍有很大挖掘空间。这里说的多模态不是简单的多源数…

element-ui使用记录

element-ui的组件名就是类名 样式穿透(用来修改没有类名的子组件样式) 例如修改头部具名插槽的样式(但是无法定位该元素) 查看最后生成的html结构中对应的结构(这里的头部有类名,可以直接对该类名进行样…

【CicadaPlayer】demuxer_service的简单理解

G:\CDN\all_players\CicadaPlayer-github-0.44\mediaPlayer\SMPMessageControllerListener.cppplayer的demuxer服务类 std::unique_ptr<demuxer_service> mDemuxerService{nullptr};根据option (Cicada::options),可以决定音视频的不同操作,通过 hander可以获得具体使…

SpringCloud Alibaba Sentinel 创建流控规则

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第十四篇&#xff0c;即介绍 SpringCloud Alibaba Sentinel 创建流控规则。 二、基本介绍 我们在 senti…

UltraScale 架构 SelectIO 资源之IODELAY与IOSERDES仿真与使用

平台&#xff1a;vivado2018.3 具体内容见ug571-ultrascale-selectio IDELAYE3 在调试超高速信号的时候&#xff0c;需要使用iodelayiserdes来调试校准输入信号。例如外部某ADC采样率为5GHZ&#xff0c;外部ADC使用2.5GHZ的时钟去采集输入信号。为了实现采集&#xff0c;adc芯…

90天玩转Python—05—基础知识篇:Python基础知识扫盲,使用方法与注意事项

90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…