前言

前面已经介绍了requests和selenium这两种方式的基础知识和模拟登录,但是我们需要每次都进行登录,这明显是很麻烦并且不合理的,所以这次我分享一下怎么可以让我们的程序进行一次登录之后,和普通浏览器一样下次不进行登录直接进行对网站数据的爬取

下面的我分享的内容需要前置知识,如果同志有知识不理解,可以查看我以前写的文章

Python爬虫request三方库实战-CSDN博客

Python爬虫 XPath 三方库lxml-CSDN博客

Python爬虫 模拟登录 requests版-CSDN博客

selenium基础知识 和 模拟登录selenium版本-CSDN博客

目录

保持登录的核心原理

保持登录request版本

保持登录selenium版本


保持登录的核心原理

市面上基本上所有的网站都把登录的信息存储到浏览器的Cookie里面了。

无论他使用什么方式进行登录,基本上都要先拿到浏览器的请求头Cookie信息作为依据给出登录状态的响应。

当然也有极少数的网站选择请求头Authorization信息作为依据给出登录状态的响应。

如果Cookie不可以,可以往这方面排查。

所以我们的核心操作就是在第一次模拟登录的时候对Cookie进行存储,然后以后对这个网站进行请求的时候带上我们在第一次模拟登录的时候获取的请求头。

请求头Authorization信息也是同样的思路,只是存储和获取的请求头不一样,原理是相通的。

我下面把Cookie存储到redis为例,给出代码示例和详细操作流程。

保持登录request版本

在没有反爬机制的情况下,我们直接拿到请求登录接口返回的Cookie值,把它保存到一个地方

然后在我们请求这个网站的网址的时候带上这个Cookie值就保证了登录状态了

因为请求登录接口返回的Cookie值是一个对象,所以我们要进行二进制的序列化进行存储

我存储到Redis中为例

对redis数据库进行链接

import redis#链接redis
redis_client = redis.StrictRedis(host='redis数据库的IP',port=端口号,db=0,password='redis密码',  # 添加密码参数decode_responses=False  # 禁止自动解码返回值为字符串,因为存储是pickle序列化之后的二进制数据
)

将请求接口返回的Cookie值存储到Redis中

import pickle# loginResponse是requests请求登录接口的响应对象
# 因为loginResponse.cookie一个RequestsCookieJar类型,需要使用pickle进行序列化存储到redis
# 存储的时候使用pickle做一个序列化转化为二进制进行存储
redis_client.setex("Cookie", 86400, pickle.dumps(loginResponse.cookies))

从Redis中取出Cookie,请求网站网址的时候请求头加上Cookie保持登录

import pickle#尝试从redis进行获取Cookie
Cookie = redis_client.get("Cookie")#redis存储的cookie是序列化的,所以要进行反序列化才能使用
Cookie = pickle.loads(Cookie)

完整示例

对某车市网站进行爬取

import requests
from lxml import etree
import pickle
import redis#链接redis
redis_client = redis.StrictRedis(host='redis数据库的IP',port=redis数据库端口号,db=0,password='redis数据库密码',  # 添加密码参数decode_responses=False  # 禁止自动解码返回值为字符串,因为存储是pickle序列化之后的二进制数据
)url = "目标请求网址"headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
}#尝试从redis进行获取cheshiCookie
cheshiCookie = redis_client.get("cheshiCookie")if cheshiCookie:#redis存储的cookie是序列化的,所以要进行反序列化才能使用cheshiCookie = pickle.loads(cheshiCookie)#redis存储的cookie是序列化的,所以要进行反序列化才能使用cheshiCookie = pickle.loads(cheshiCookie)res1 = requests.get(url, headers=headers, cookies=cheshiCookie)
else:res1 = requests.get(url, headers=headers)datas = etree.HTML(res1.text)
#获取页面是否有登录页面的特征,我这里使用XPath定位《账号登录》这个文本是否可以获取到来判断这个页面是不是登录页面
loginName = datas.xpath('//div[@class="userlogin"]//span[2]/text()')#这个页面可以获取账号登录这个文本,说明是登录页面,需要进行登录
if loginName and loginName[0] == "账号登录":loginUrl = "登录接口"loginData = {"key1": "value1","key2": "value2","key3": "value3"}loginResponse = requests.post(loginUrl, data=loginData, headers=headers)# 因为loginResponse.cookie一个RequestsCookieJar类型,需要使用pickle进行序列化存储到redisredis_client.setex("cheshiCookie", 86400, pickle.dumps(loginResponse.cookies))#再次请求需要登录的请求地址,加上Cookie,此时就是登录状态了res2 = requests.get(url, headers=headers,cookies=loginResponse.cookies)print(res2.text)
else:print(res1.text)

如果网址的Cookie不是从登录接口响应的时候直接给你的,给一些原材料进行加密处理,这个时候要进行自行探索了,原理就是得到Cookie存储起来,下次请求网址的时候带上,保持登录状态进行请求 

保持登录selenium版本

因为Requests方式进行保持登录,网站登录接口稍微有点加密就基本上搞不了了。

所以我们还有一种简单粗暴的方式,控制浏览器,进行登录,登录完成之后会跳转登录之后的页面,把登录之后的页面上的Cookie直接存储到Redis中。

就跟真人取浏览器上面登录状态网站的Cookie是一样的

因为是直接从浏览器的网址上面拿到的Cookie,所以是一个JSON字符串,需要序列化成JSON字符串进行存储到Redis

对Redis数据库进行链接

import redis#链接redis
redis_client = redis.StrictRedis(host='redis数据库的IP',port=端口号,db=0,password='redis密码',  # 添加密码参数decode_responses=True  # 禁止自动解码返回值为字符串,因为存储是pickle序列化之后的二进制数据
)

将拿到的Cookie序列化成JSON字符串存储到Redis中

# 序列化成 JSON 字符串并存入 Redis
redis_client.set("Cookie", json.dumps(cookies))

从Redis中取Cookie并还原成JSON字符串,并注入到当前selenium浏览器驱动driver中

一定要先打开请求网址再注入Cookie,注入的Cookie是指对当前页面进行Cookie注入

import json#获取redis里面存储cookie的json字符串
Cookie = redis_client.get("Cookie")
cookies = json.loads(Cookie)
# 逐个注入 Cookie
for cookie in cookies:driver.add_cookie(cookie)

完整示例

 对某淘网站的商品信息进行爬取

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support import expected_conditions as EC
import redis
import json#链接redis
redis_client = redis.StrictRedis(host='redis数据库IP',port=redis数据库端口,db=0,password='redis数据库密码',  # 添加密码参数decode_responses=True  # 自动解码返回值为字符串
)
#获取redis里面存储cookie的json字符串
taobaoCookie = redis_client.get("taobaoCookie")# selenium 4的写法
options = Options()
options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36")
options.add_argument("--window-size=1920,1080")  # 设置窗口大小
options.add_argument("--disable-blink-features=AutomationControlled")  # 禁用自动化控制特征
options.add_argument("--disable-infobars")  # 禁用提示条
options.add_argument("--no-sandbox")  # 解决DevToolsActivePort文件不存在的报错
options.add_argument("--disable-dev-shm-usage")  # 禁用共享内存
options.add_argument("--disable-extensions")  # 禁用扩展
options.add_argument("--disable-gpu")  # 禁用GPU加速
options.add_argument("--disable-javascript")  # 禁用JavaScript(根据需求调整)
options.add_argument("--incognito")  # 隐身模式
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager(driver_version="谷歌浏览器版本号").install()),options=options)
driver.get("目标请求网址")
#如果redis获取到taobaoCookie就加上,没有后面登录获取
if taobaoCookie:cookies = json.loads(taobaoCookie)# 逐个注入 Cookiefor cookie in cookies:driver.add_cookie(cookie)#看是否可以获得网站标签来确定网站是否加载完毕
title = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH,'//h1[@class="xM6AVLCbLn--mainTitle--_90838ca f-els-2"]')))#获取一键登录的标签,这里使用了返回集合标签的方法,因为有可能获取不到,返回空集合,不至于报错
loginHTML = driver.find_elements(By.XPATH,'//span[@class="xM6AVLCbLn--loginBtn--_3aec1d3"]')if not loginHTML:#发现没有一键登录标签说明已经登录了pass
else:#有一键登录标签需要登录,并把登录的Cookie信息存储到redis用来下次使用#这一步也可以防止Cookie登录失效,失效了和没有Cookie是一样的也会到这一步actions = ActionChains(driver).click(loginHTML[0]).perform()usern = driver.find_element(By.XPATH,'//input[@id="fm-login-id"]')pwd = driver.find_element(By.XPATH,'//input[@id="fm-login-password"]')loginHb = driver.find_element(By.XPATH,'//button[@class="fm-button fm-submit password-login  button-low-light"]')ActionChains(driver).click(usern).pause(1).send_keys('用户名').pause(0.5).perform()ActionChains(driver).click(pwd).pause(1).send_keys('密码').pause(0.5).perform()ActionChains(driver).click(loginHb).perform()resFlag = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.XPATH,'//div[@class="xM6AVLCbLn--tabDetailWrap--_3622a08"]')))# 获取 Cookies(列表形式)cookies = driver.get_cookies()# 序列化成 JSON 字符串并存入 Redisredis_client.set("taobaoCookie", json.dumps(cookies))#把这个商品的所有颜色和大小搭配全部获取下来
skuColorHTMLList = driver.find_elements(By.XPATH,'//div[@class="xM6AVLCbLn--skuWrapper--e63a4df5"]//div[@class="xM6AVLCbLn--skuItem--_68c0cae"][1]//div[contains(@class,"xM6AVLCbLn--valueItem--ee898cc0")]')
skuSizeHTMLList = driver.find_elements(By.XPATH,'//div[@class="xM6AVLCbLn--skuWrapper--e63a4df5"]//div[@class="xM6AVLCbLn--skuItem--_68c0cae"][2]//div[contains(@class,"xM6AVLCbLn--valueItem--ee898cc0")]')for skuColorHTML in skuColorHTMLList:#先点击颜色分类actions = ActionChains(driver).click(skuColorHTML).perform()for skuSizeHTML in skuSizeHTMLList:#后点击大小分类actions = ActionChains(driver).click(skuSizeHTML).perform()#过滤获取值存储,这里省略#最后关闭浏览器
driver.quit()

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

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

相关文章

leetcode:474. 一和零[01背包][动态规划]

学习要点 给定背包容量&#xff0c;装满背包最多有多少个物品深入理解01背包深入理解动态规划 题目链接 474. 一和零 - 力扣&#xff08;LeetCode&#xff09; 题目描述 解法:01背包 class Solution { public:int findMaxForm(vector<string>& strs, int m, int …

UE5 使用过程遇到的问题

切换缓存位置 进入界面&#xff0c;选择-编辑-编辑器偏好设置搜索缓存&#xff0c;找到通用全局&#xff0c;修改本地DCC路径到要切换的位置 闪退报错 Fatal: Failed to get dll export function: cuvidGetDecoderCaps [NVDEC] 因为NVIDIA驱动没有卸载干净&#xff0c;使用D…

2025 BSidesMumbaiCTF re 部分wp

XORyy 附件拖入ida。明文 idkwhattonamethis 附件拖入ida 前三个函数都是检查环境&#xff0c;跳过即可 长度为5&#xff0c;可以根据flag格式求解。脚本。尽管多解但是可能的结果很少 Diff_EQ 附件拖入ida z3求解等式&#xff0c;脚本。无反调试的情况下本地可以验证&#xff…

图灵完备之路(数电学习三分钟)----逻辑与计算架构

经过前面几节的学习&#xff0c;我们已经有了简单的数电知识&#xff0c;下面&#xff0c;我们将正式进入设计简单图灵完备机的工作&#xff0c;首先&#xff0c;我们要设计出具有逻辑运算与计算功能的简单结构&#xff1a; 1.逻辑架构 首先&#xff0c;该架构能实现多种逻辑…

【C++笔记】AVL树的深度剖析

【C笔记】AVL树的深度剖析 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C笔记 文章目录【C笔记】AVL树的深度剖析前言一. AVL树的概念二.AVL树的实现2.1 AVL树的结构2.2 AVL树的插入2.3 平衡因子更新三.旋转3.1旋转的原则3.2右单旋3.3左单…

支持向量机(SVM)在肝脏CT/MRI图像分类(肝癌检测)中的应用及实现

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;10年以上C/C, C#, Java等多种编程语言开发经验&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开…

DeepSeek扫雷游戏网页版HTML5(附源码)

用DeepSeek帮忙生成一个网页版的扫雷游戏&#xff0c;效果非常棒&#xff0c;基于HTML5实现&#xff0c;方便运行。 提示词prompt 帮我做一个网页版的 html5 扫雷游戏游戏功能说明 游戏难度&#xff1a; 1 简单&#xff1a;1010 格子&#xff0c;10个地雷 2 中等&#xff1a;16…

Day53GAN对抗生成网络思想

生成对抗网络&#xff08;GAN&#xff09;是深度学习领域的一种革命性模型&#xff0c;由Ian Goodfellow等人于2014年提出。其核心思想源于博弈论中的零和博弈&#xff0c;通过两个神经网络&#xff08;生成器和判别器&#xff09;的对抗性训练&#xff0c;实现数据的高质量生成…

meilisearch-轻量级搜索引擎

meilisearch是一款开源的轻量级搜索引擎&#xff0c;相比于elasticsearch等重量级搜索引擎&#xff0c;meilisearch注重数据搜索&#xff0c;从而而省去了其它不必要的功能&#xff08;如支持聚合分析、分布式搜索等特性&#xff09;&#xff0c;以便于快速上手开发和构建应用。…

51c大模型~合集150

我自己的原文哦~ https://blog.51cto.com/whaosoft/14034001 #原来Scaling Law还能被优化 Meta这招省token又提效 2017 年&#xff0c;一篇《Attention Is All You Need》论文成为 AI 发展的一个重要分水岭&#xff0c;其中提出的 Transformer 依然是现今主流语言模型…

每天一个前端小知识 Day 23 - PWA 渐进式 Web 应用开发

PWA 渐进式 Web 应用开发&#xff08;离线缓存、桌面安装等&#xff09; &#x1f9e0; 一、什么是 PWA&#xff1f; PWA&#xff08;Progressive Web App&#xff09;是一种让 Web 应用具有类似原生 App 用户体验的技术体系。 PWA 不是一个框架&#xff0c;而是由一组浏览器 A…

音视频会议服务搭建(设计方案-两种集成方案对比)-03

前言在开始计划之前&#xff0c;查阅了不少资料。一种方案是 Go层做信令业务&#xff0c;nodejs层来管理和mediasoup的底层交互&#xff0c;通过客户端去调用Go层&#xff1b;第二种方案是 客户端直接调用nodejs层来跟mediasoup去交互&#xff1b; 最终&#xff0c;当然不出意料…

【小白】linux安装ffmpeg | java转码 【超详细】

前言 最近在开发过程中&#xff0c;发现当我们上传除了mp4以外的其他少见的格式&#xff0c;如 .flv .rmvb 格式的视频时&#xff0c;在前端在线播放的时候会播放不出来画面&#xff0c;所以 接下来&#xff0c;将要进行一个非常完美的工程&#xff0c;将视频格式转为.mp4 1.安…

一个简单的脚本,让pdf开启夜间模式

因为平常我比较喜欢晚上看面试题。 市面上很多的面试题pdf都是白色的晚上看的话非常的刺眼。 所以我本能的去互联网搜索看看有没有pdf转换为夜间模式的。 搜索了一段时间后发现并没有这种东西。于是我自己做了一个转换的python脚本。 import os import fitz # PyMuPDF from P…

Flink OceanBase CDC 环境配置与验证

一、OceanBase 数据库核心配置 1. 环境准备与版本要求 版本要求&#xff1a;OceanBase CE 4.0 或 OceanBase EE 2.2组件依赖&#xff1a;需部署 LogProxy 服务&#xff08;社区版/企业版部署方式不同&#xff09;兼容模式&#xff1a;支持 MySQL 模式&#xff08;默认&#x…

c++对象池

【设计模式】其它经典模式-对象池模式&#xff08;Object Pool Pattern&#xff09;-CSDN博客 在C中&#xff0c;对象池&#xff08;Object Pool&#xff09;是一种管理对象生命周期的技术&#xff0c;旨在减少对象创建和销毁的开销&#xff0c;提高性能。对象池预先分配一定数…

JavaFX:Scene(场景)

简介 Scene对象是JavaFX场景图的根(root)。JavaFX 场景中包含所有可视的 JavaFX GUI 组件。JavaFX 场景由javafx.scene.Scene类表示。必须在 Stage(舞台)上设置 Scene 对象才能使其可见。在本 JavaFX Scene 教程中,将向您展示如何创建 Scene 对象并向其添加 GUI 组件。 创…

vue3.4中的v-model的用法~

1.首先以前我们针对父子组件传参是不是通过defineProps与defineEmits来实现的&#xff0c;但是这么比较繁琐&#xff0c;因为他是单向传参&#xff0c;而不是双向的&#xff0c;这里我们要介绍的是vue3.4的v-model来实现双向数据传递。 2、代码示例&#xff1a; //父组件 <…

nvm常用指令汇总

nvm是用来管理nodejs的&#xff0c;可以方便安装、切换、卸载当前环境的node版本。 以下是常用指令汇总&#xff1a;nvm list 查看本机已经安装的node版本。*表示当前系统正在使用的node版本nvm install xx.xx.x 后边加版本号&#xff0c;表示安装指定的版本nvm use xx.xx.x当前…

洛谷P5021 [NOIP 2018 提高组] 赛道修建【题解】【二分答案+树上贪心】

P5021 [NOIP 2018 提高组] 赛道修建 题意简述 给定一棵含 n n n 个点的无向带权树&#xff0c;求将其分裂为 m m m 条链后&#xff0c;最短的一条链的最大长度是多少&#xff1f; 点可以重复使用&#xff0c;边不可以重复使用。 思路 二分答案贪心判定貌似可以&#xff…