如何避免爬虫因Cookie过期导致登录失效

1. Cookie的作用及其过期机制

1.1 什么是Cookie?

Cookie是服务器发送到用户浏览器并保存在本地的一小段数据,用于维持用户会话状态。爬虫在模拟登录后,通常需要携带Cookie访问后续页面。

1.2 Cookie为什么会过期?

  • 会话Cookie(Session Cookie):浏览器关闭后失效。
  • 持久Cookie(Persistent Cookie):设置**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Expires</font>****<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Max-Age</font>**属性,超时后失效。
  • 服务器主动失效:如用户修改密码、长时间未操作等。

如果爬虫未正确处理Cookie过期问题,会导致:

  • 请求返回**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">401/403</font>**状态码
  • 被重定向到登录页面
  • 触发网站反爬机制(如封禁IP)

2. 检测Cookie是否过期的策略

2.1 直接检测HTTP响应

  • 检查返回状态码(如**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">302</font>**重定向到登录页)。
  • 检查响应内容是否包含登录提示(如**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">"请先登录"</font>**)。
import requestsdef check_cookie_valid(session):test_url = "https://example.com/user/profile"  # 需要登录才能访问的页面response = session.get(test_url)if response.status_code == 200 and "个人中心" in response.text:return True  # Cookie有效else:return False  # Cookie失效

2.2 检查Cookie的Expires属性

如果服务器返回的Cookie带有**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Expires</font>**字段,可以解析并判断是否已过期。

from datetime import datetimedef is_cookie_expired(cookie):if "expires" in cookie:expires_time = datetime.strptime(cookie["expires"], "%a, %d-%b-%Y %H:%M:%S GMT")return expires_time < datetime.now()return False  # 无过期时间或会话Cookie

3. 自动刷新Cookie的解决方案

3.1 重新登录获取新Cookie

当检测到Cookie失效时,自动调用登录接口更新Cookie。

def login(username, password):login_url = "https://example.com/login"session = requests.Session()payload = {"username": username, "password": password}response = session.post(login_url, data=payload)if "登录成功" in response.text:return session  # 返回带新Cookie的Sessionelse:raise Exception("登录失败")

3.2 使用Session对象持久化Cookie

**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">requests.Session()</font>**可自动管理Cookie,但需结合存储机制(如文件、数据库)实现长期有效。

import pickledef save_session(session, filename="session.pkl"):with open(filename, "wb") as f:pickle.dump(session.cookies, f)def load_session(filename="session.pkl"):session = requests.Session()try:with open(filename, "rb") as f:session.cookies.update(pickle.load(f))except FileNotFoundError:pass  # 首次运行无缓存return session

3.3 结合Redis缓存Cookie(分布式爬虫适用)

import redis
import pickleredis_client = redis.StrictRedis(host="localhost", port=6379, db=0)def save_session_to_redis(session, key="example_cookie"):redis_client.set(key, pickle.dumps(session.cookies))def load_session_from_redis(key="example_cookie"):session = requests.Session()cookie_data = redis_client.get(key)if cookie_data:session.cookies.update(pickle.loads(cookie_data))return session

4. 进阶优化方案

4.1 使用Selenium处理动态Cookie

某些网站采用JavaScript动态生成Cookie,可使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">selenium</font>**模拟浏览器登录。

from selenium import webdriver
from selenium.webdriver.common.by import Bydef selenium_login(username, password):driver = webdriver.Chrome()driver.get("https://example.com/login")driver.find_element(By.NAME, "username").send_keys(username)driver.find_element(By.NAME, "password").send_keys(password)driver.find_element(By.XPATH, "//button[@type='submit']").click()# 获取Cookie并转为requests可用的格式cookies = driver.get_cookies()session = requests.Session()for cookie in cookies:session.cookies.set(cookie["name"], cookie["value"])driver.quit()return session

4.2 结合代理IP和User-Agent轮换

避免因频繁登录触发反爬。

import requests
from requests.auth import HTTPProxyAuth# 爬虫配置
LOGIN_URL = "https://example.com/login"  # 登录页面的 URL
DATA_URL = "https://example.com/data"    # 需要爬取数据的 URL
USERNAME = "your_username"               # 用户名
PASSWORD = "your_password"               # 密码# 代理配置
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"# 构造代理地址
proxies = {"http": f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}","https": f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}",
}# 请求头
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",
}# 登录函数
def login():session = requests.Session()login_data = {"username": USERNAME,"password": PASSWORD}response = session.post(LOGIN_URL, data=login_data, headers=headers, proxies=proxies, auth=HTTPProxyAuth(proxyUser, proxyPass))if response.status_code == 200:print("登录成功,获取到新的 Cookie")return sessionelse:print("登录失败")return None# 检测 Cookie 是否过期
def check_cookie(session):response = session.get(DATA_URL, headers=headers, proxies=proxies)if response.status_code == 401 or response.status_code == 403:print("Cookie 过期,需要重新登录")return Falseelif "登录已失效" in response.text:print("Cookie 过期,需要重新登录")return Falseelse:print("Cookie 仍然有效")return True# 主爬虫逻辑
def main():session = login()  # 首次登录获取 Cookieif session is None:print("无法登录,爬虫终止")returnwhile True:if check_cookie(session):  # 检测 Cookie 是否过期# 如果 Cookie 有效,继续爬取数据response = session.get(DATA_URL, headers=headers, proxies=proxies)if response.status_code == 200:print("成功获取数据")# 处理数据print(response.text)else:print("数据获取失败")else:# 如果 Cookie 过期,重新登录session = login()if session is None:print("重新登录失败,爬虫终止")breakif __name__ == "__main__":main()

5. 结论

  • Cookie过期检测:通过状态码、页面内容或**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Expires</font>**字段判断。
  • 自动刷新Cookie:重新登录或使用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">Session</font>**持久化存储。
  • 分布式爬虫:可采用Redis共享Cookie,避免重复登录。
  • 动态网站:结合**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">selenium</font>**获取动态生成的Cookie。

通过合理管理Cookie,爬虫可以长期稳定运行,避免因登录失效导致的数据抓取中断。

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

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

相关文章

matlab simulink中理想变压激磁电流容易有直流偏置的原因分析。

simulink把线性变压器模块拉出来&#xff0c;设置没有绕线电阻的变压器&#xff0c;激磁电感和Rm都有&#xff0c;然后给一个50%占空比的方波&#xff0c;幅值正负10V&#xff0c;线路中设置一个电阻&#xff0c;模拟导线阻抗。通过示波器观察激磁电流&#xff0c;发现电阻越小…

电力系统失步解列与振荡解析

一、基本概念解析 1. 失步&#xff08;Out-of-Step&#xff09; 在电力系统中&#xff0c;失步是指并列运行的同步发电机因功率失衡导致转子间相对角度超过稳定极限&#xff0c;无法维持同步运行的状态。具体表现为&#xff1a; 当系统发生短路、负荷突变或故障切除等扰动时&…

ctfhub-RCE

关于管道操作符 windows&#xff1a; 1. “|”&#xff1a;直接执行后面的语句。 2. “||”&#xff1a;如果前面的语句执行失败&#xff0c;则执行后面的语句&#xff0c;前面的语句只能为假才行。 3. “&”&#xff1a;两条命令都执行&#xff0c;如果前面的语句为假则直…

Missashe考研日记-day28

Missashe考研日记-day28 1 专业课408 学习时间&#xff1a;2h学习内容&#xff1a; 今天先是预习了OS关于虚拟内存管理的内容&#xff0c;然后听了一部分视频课&#xff0c;明天接着学。知识点回顾&#xff1a; 1.传统存储管理方式特征&#xff1a;一次性、驻留性。2.局部性原…

01 appium环境搭建

环境搭建 Java JDKNode.jsAndroidStudio(提供sdk)appiumappium Inspector 相关安装包下载 链接&#xff1a;https://pan.xunlei.com/s/VOOf3sCttAdHvlMkc7QygsoJA1# 提取码&#xff1a;x4s5 AndroidStudio下载安装sdk AndroidStudio下载 安装运行&#xff0c;配置代理及测…

指针(4)

1.回调函数 回调函数就是通过函数指针调用的函数。 将函数的指针&#xff08;地址&#xff09;作为一个参数传递给另一个函数&#xff0c;当这个指针被调用其所指向的函数时&#xff0c;被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用&#xff0c;而是在特…

Raptor码的解码成功率matlab实现

下面是使用matlab实现关于Raptor 码解码成功率的仿真代码&#xff0c;并绘制成功率随编码符号数量变化的图形示例。代码中包含了 Raptor 码的预编码&#xff08;使用稀疏矩阵乘法模拟&#xff09;、LT 编码、解码过程&#xff0c;以及解码成功率的计算和绘图。 具体代码如下&am…

域名系统DNS

DNS介绍 DNS是一个域名系统&#xff0c;在互联网环境中为域名和IP地址相互映射的一个分布式数据库 &#xff0c; 能够使用户更方便的访问互联网&#xff0c;而不用去记住能够被机器直接读取的IP数串。类似于生活中的114服务&#xff0c;可以通过人名找到电话号码&#xff0c;也…

Spark Streaming核心编程总结(四)

一、有状态转化操作&#xff1a;UpdateStateByKey 概念与作用 UpdateStateByKey 用于在流式计算中跨批次维护状态&#xff08;如累加统计词频&#xff09;。它允许基于键值对形式的DStream&#xff0c;通过自定义状态更新函数&#xff0c;将历史状态与新数据结合&#xff0c;生…

Dijkstra 算法代码步骤[leetcode.743网络延迟时间]

有 n 个网络节点&#xff0c;标记为 1 到 n。 给你一个列表 times&#xff0c;表示信号经过 有向 边的传递时间。 times[i] (ui, vi, wi)&#xff0c;其中 ui 是源节点&#xff0c;vi 是目标节点&#xff0c; wi 是一个信号从源节点传递到目标节点的时间。 现在&#xff0c;…

【java】lambda表达式总结

目录 一、面向对象的处理方法 二、函数式编程的处理方法 先使用匿名内部类&#xff1a; lambda改造&#xff1a; lambda改造规则 示例&#xff1a; 三、补充&#xff1a;函数式接口 大家好&#xff0c;我是jstart千语。今天总结一下lambda表达式。lambda表达式在后面的s…

AtCoder Beginner Contest 242 G - Range Pairing Query (莫队)

每周五篇博客&#xff1a;&#xff08;5/5&#xff09; 我做到了&#xff01; https://atcoder.jp/contests/abc242/tasks/abc242_g 这题主要是想给大家提供一份莫队的板子&#xff0c;很多莫队题基本上填空就差不多了&#xff08; 板子 void solve() {int n;std::cin >…

淘宝商品主图标题api接口

1、输入淘宝商品id或者链接&#xff0c;点查询 2、查询淘宝商品主图&#xff0c;商品标题&#xff0c;商品价格&#xff0c;卖家旺旺 3、支持api接口

文心一言开发指南06——千帆大模型平台新手指南

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 千帆大模型平台为新手用户提供了一个全面的入门指南&#xff0c;以便用户能够快速熟悉平台的操作和功能。千帆大模型平台通过提供详细的新手指南&#xff0c;确保用户能够顺…

Pacman-N-queen

文档 代码及文档&#xff1a;通过网盘分享的文件&#xff1a;code 链接: https://pan.baidu.com/s/1Rgo9ynnEqjZsSP2-6TyS8Q?pwdn99p 提取码: n99p 补充核心代码 核心代码内容&#xff1a; genetic_algorithm,py # -*- coding: utf-8 -*- """ Created on …

常用的多传感器数据融合方法

1. 概述 根据具体需求&#xff08;实时性、计算资源、噪声特性&#xff09;选择合适的方法&#xff0c;实际应用中常结合多种方法&#xff08;如UKF与神经网络结合&#xff09;。 传统方法 &#xff08;KF/EKF/UKF/PF&#xff09;依赖数学模型&#xff0c;适合动态系统&#…

简单几步,开启 Intel VT-x 让电脑“解开CPU封印”

#vmware #虚拟机 #cpu虚拟化 # Intel VT-x 前言 你是不是也遇到过这种情况&#xff1a;在尝试运行虚拟机&#xff08;VM&#xff09;、安卓模拟器&#xff0c;或者使用 Windows 沙盒、WSL2 等功能时&#xff0c;遇到了类似“此主机支持 Intel VT-x&#xff0c;但 Intel VT-x …

Go语言--语法基础4--基本数据类型--字符串类型

在 Go 语言中&#xff0c;字符串也是一种基本类型。相比之下&#xff0c; C/C 语言中并不存在原 生的字符串类型&#xff0c; 通常使用字符数组来表示&#xff0c;并以字符指针来传递。 Go 语言中字符串的声明和初始化非常简单&#xff0c;举例如下&#xff1a; var str st…

QT中的事件及其属性

Qt中的事件是对操作系统提供的事件机制进行封装&#xff0c;Qt中的信号槽就是对事件机制的进一步封装 但是特殊情况下&#xff0c;如对于没有提供信号的用户操作&#xff0c;就需要通过重写事件处理的形式&#xff0c;来手动处理事件的响应逻辑 常见的Qt事件&#xff1a; 常见事…

socket套接字-UDP(中)

socket套接字-UDP&#xff08;上&#xff09;https://blog.csdn.net/Small_entreprene/article/details/147465441?fromshareblogdetail&sharetypeblogdetail&sharerId147465441&sharereferPC&sharesourceSmall_entreprene&sharefromfrom_link UDP服务器…