首页 > 编程语言 >在python爬虫中如何处理cookie和session

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

时间:2024-04-08 21:33:13浏览次数:29  
标签:cookies 请求 Session python session cookie requests

使用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 traceback

import requests.utils

cookie_path = './data/cookie.txt'
request_session: requests.Session = None

def __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 None

def get_session():
    global request_session
    if request_session is not None:
        return request_session
    else:
        request_session = requests.Session()
        exist_cookies = __load_cookie()
        if exist_cookies is not None:
            request_session.cookies.update(exist_cookies)

        return request_session

def 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)

    # 清空旧的cookie
    request_session.cookies.clear_session_cookies()
    # 填充新的cookie
    request_session.cookies.update(new_cookie)

标签:cookies,请求,Session,python,session,cookie,requests
From: https://blog.csdn.net/Kingsea442/article/details/137482917

相关文章

  • python画信封 2024年3月青少年电子学会等级考试 中小学生python编程等级考试一级真题
    目录python画信封一、题目要求二、算法分析三、程序代码四、程序说明五、运行结果六、考点分析七、推荐资料1、蓝桥杯比赛2、考级资料3、其它资料python画信封2024年3月python考级一级真题一、题目要求龙年到了,我们要给远方的亲人写一封新年贺信,请用turtle......
  • Django框架之Cookie和Session
    一、cookie与session的发展史Cookie和Session是Web开发中常用的两种机制,用于在客户端和服务器之间存储和管理用户信息。1、Cookie的发展史:1994年:由Netscape公司的工程师LouMontulli发明。最初的目的是为了解决HTTP协议的状态管理问题,使网站能够在浏览器端存储和读取用户信息......
  • Python绘图
    Smiling&Weeping----如果你问我最想要什么我会很幼稚地说真爱和自由 代码一: metaData=pd.read_csv('/kaggle/input/bi......
  • 挣值分析-Python
    importmatplotlib.pyplotaspltimportmatplotlibmatplotlib.use('TkAgg')#设定函数进行计算defSV(EV,PV):returnEV-PVdefCV(EV,AC):returnEV-ACdefSPI(EV,PV):returnEV/PVdefCPI(EV,AC):returnEV/ACdefTEA......
  • Python实战:Python自动化办公
    1.引言自动化办公是一种通过计算机程序自动执行日常办公任务的技术,它可以大大提高工作效率,降低人力成本。Python作为一门强大的编程语言,提供了丰富的库和框架,使得自动化办公变得更加高效和便捷。本文将介绍Python在自动化办公中的关键技术和实现方法。2.环境准备在......
  • python函数
    一、大纲简介:二、函数初体验案例#不使用函数,实现计数功能str1="itheima"//此处定义三个待计数字符串str2="itcast"str3="python"count=0//此处定义一个变量来计数容器foriinstr1://使用for循环来遍历count+=1//遍历字符串一次,变量容器就加一......
  • Python实战:Python在物联网(IoT)设备编程中的应用
    1.引言物联网(IoT)是一个由相互连接的物理设备组成的网络,这些设备可以通过互联网进行通信和交换数据。Python作为一种功能强大的编程语言,被广泛应用于物联网设备的编程和开发中。通过Python,我们可以轻松地实现设备之间的数据通信、设备控制等功能。2.环境准备在开......
  • Python实战:利用Python进行音视频处理
    1.引言音视频处理是一种广泛应用于娱乐、教育、医疗等领域的技术,它允许我们编辑、转换和分析音视频数据。Python作为一种功能强大的编程语言,提供了丰富的库和框架,使得音视频处理变得更加高效和便捷。本文将介绍Python在音视频处理中的应用实例。2.环境准备在开始编......
  • 第十四届蓝桥杯省赛研究生组python
    目录试题A:工作时长excel处理代码试题B:分糖果试题C:填充试题D:互质数的个数题解:暴力试题E:阶乘的和题解:暴力+备忘录试题F:公因数匹配题解:暴力试题G:小蓝的旅行计划题解试题A:工作时长excel处理把数据复制到excel,并选中列右键选择设置单元格格式注意:因为求和之后总小时数可能会超过2......
  • 机器学习笔记 使用Python从头开始​​构建百万参数LLaMA
    一、LLaMA架构        LLaMA (Large Language Model Meta AI) 是一个基础语言模型的集合,参数范围从7B到65B,LLaMA并非专门为对话任务而设计的模型,而是专注于语言理解和生成。但是作为基础模型,LLaMA被设计为多功能的,可以应用于许多不同的用例,而不是为特定任务......