Python使用selenium访问网页完成登录——装饰器重试机制汇总
文章目录
- 示例一:常见装饰器编写重试机制
- 示例二:使用类实现装饰器
- 示例三:使用函数装饰器并返回闭包
- 示例四:使用 `wrapt` 模块
示例一:常见装饰器编写重试机制
示例代码
import time
import traceback
import logging
from typing import Callable
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException, WebDriverException, TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC# 设置日志配置
logging.basicConfig(level=logging.ERROR)
logger = logging.getLogger(__name__)# 假设 DOME 是一个配置字典,用于控制 DEBUG 模式
DOME = {'DEBUG': False,'debug': False
}def exr_func(*args, **kwargs):# 在每次重试前执行的操作,可以在此添加刷新页面等逻辑driver = kwargs.get('driver')if driver:driver.refresh()time.sleep(2) # 等待页面刷新完成def dec_retry(num=1, exr: Callable = lambda *_, **__: None, catch=Exception, exclude=Exception, out_error=True):"""装饰器,重复执行func并忽略异常,超过次数抛出异常或返回空,此函数默认输出异常信息"""def decorator(func):def dec(*args, **kwargs):for i in range(1, num + 1):try:return func(*args, **kwargs)except exclude as err:raise errexcept catch as err:logger.error(f'第 {i} 次执行失败')if out_error:logger.error(err, traceback.format_exc(), sep='\n')if DOME.get('DEBUG') or DOME.get('debug'):logger.error('已开启 DEBUG 模式,直接抛出异常')raise errif i >= num:logger.error(f'已执行 {num} 次,抛出异常')raise errlogger.error('开始重试')exr(*args, **kwargs)return decreturn decorator@dec_retry(num=3, exr=exr_func, catch=(NoSuchElementException, WebDriverException, TimeoutException))
def login(driver, username, password):# 访问登录页面driver.get("https://example.com/login")# 等待页面加载完成WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "username")))# 输入用户名username_field = driver.find_element(By.ID, "username")username_field.send_keys(username)# 输入密码password_field = driver.find_element(By.ID, "password")password_field.send_keys(password)# 点击登录按钮login_button = driver.find_element(By.ID, "loginButton")login_button.click()# 等待页面加载完成并检查是否登录成功WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "logoutButton")))print("登录成功")return Truedef main():# 设置WebDriverdriver = webdriver.Chrome()username = "your_username"password = "your_password"try:login(driver, username, password, driver=driver)except Exception as e:logger.error(f"最终登录失败,异常: {e}")driver.quit()if __name__ == "__main__":main()
代码解释
- 日志配置: 设置日志记录配置,用于输出错误信息。
exr_func函数: 定义了在每次重试前执行的操作,例如刷新页面。dec_retry装饰器: 实现了重试机制,捕获指定异常,在重试次数用尽前会执行exr_func函数。login函数: 实现具体的登录操作,并被dec_retry装饰器装饰。main函数: 设置 WebDriver,尝试登录,并在失败时输出日志信息。
示例二:使用类实现装饰器
类装饰器可以更灵活地管理状态,并且可以更好地组织复杂的逻辑。
import time
import traceback
import logging
from typing import Callable
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException, WebDriverException, TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC# 设置日志配置
logging.basicConfig(level=logging.ERROR)
logger = logging.getLogger(__name__)# 假设 DOME 是一个配置字典,用于控制 DEBUG 模式
DOME = {'DEBUG': False,'debug': False
}def exr_func(*args, **kwargs):driver = kwargs.get('driver')if driver:driver.refresh()time.sleep(2) # 等待页面刷新完成class RetryDecorator:def __init__(self, num=1, exr: Callable = lambda *_, **__: None, catch=Exception, exclude=Exception, out_error=True):self.num = numself.exr = exrself.catch = catchself.exclude = excludeself.out_error = out_errordef __call__(self, func):def wrapped_func(*args, **kwargs):for i in range(1, self.num + 1):try:return func(*args, **kwargs)except self.exclude as err:raise errexcept self.catch as err:logger.error(f'第 {i} 次执行失败')if self.out_error:logger.error(err, traceback.format_exc(), sep='\n')if DOME.get('DEBUG') or DOME.get('debug'):logger.error('已开启 DEBUG 模式,直接抛出异常')raise errif i >= self.num:logger.error(f'已执行 {self.num} 次,抛出异常')raise errlogger.error('开始重试')self.exr(*args, **kwargs)return wrapped_func@RetryDecorator(num=3, exr=exr_func, catch=(NoSuchElementException, WebDriverException, TimeoutException))
def login(driver, username, password):driver.get("https://example.com/login")WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "username")))username_field = driver.find_element(By.ID, "username")username_field.send_keys(username)password_field = driver.find_element(By.ID, "password")password_field.send_keys(password)login_button = driver.find_element(By.ID, "loginButton")login_button.click()WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "logoutButton")))print("登录成功")return Truedef main():driver = webdriver.Chrome()username = "your_username"password = "your_password"try:login(driver, username, password, driver=driver)except Exception as e:logger.error(f"最终登录失败,异常: {e}")driver.quit()if __name__ == "__main__":main()
示例三:使用函数装饰器并返回闭包
使用闭包使代码更简洁。
import time
import traceback
import logging
from typing import Callable
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException, WebDriverException, TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EClogging.basicConfig(level=logging.ERROR)
logger = logging.getLogger(__name__)DOME = {'DEBUG': False,'debug': False
}def exr_func(*args, **kwargs):driver = kwargs.get('driver')if driver:driver.refresh()time.sleep(2)def dec_retry(num=1, exr: Callable = lambda *_, **__: None, catch=Exception, exclude=Exception, out_error=True):def decorator(func):def wrapped_func(*args, **kwargs):for i in range(1, num + 1):try:return func(*args, **kwargs)except exclude as err:raise errexcept catch as err:logger.error(f'第 {i} 次执行失败')if out_error:logger.error(err, traceback.format_exc(), sep='\n')if DOME.get('DEBUG') or DOME.get('debug'):logger.error('已开启 DEBUG 模式,直接抛出异常')raise errif i >= num:logger.error(f'已执行 {num} 次,抛出异常')raise errlogger.error('开始重试')exr(*args, **kwargs)return wrapped_funcreturn decorator@dec_retry(num=3, exr=exr_func, catch=(NoSuchElementException, WebDriverException, TimeoutException))
def login(driver, username, password):driver.get("https://example.com/login")WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "username")))username_field = driver.find_element(By.ID, "username")username_field.send_keys(username)password_field = driver.find_element(By.ID, "password")password_field.send_keys(password)login_button = driver.find_element(By.ID, "loginButton")login_button.click()WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "logoutButton")))print("登录成功")return Truedef main():driver = webdriver.Chrome()username = "your_username"password = "your_password"try:login(driver, username, password, driver=driver)except Exception as e:logger.error(f"最终登录失败,异常: {e}")driver.quit()if __name__ == "__main__":main()
示例四:使用 wrapt 模块
wrapt 是一个强大的装饰器库,可以更轻松地编写装饰器,特别是处理复杂逻辑时。
import time
import traceback
import logging
import wrapt
from typing import Callable
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException, WebDriverException, TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EClogging.basicConfig(level=logging.ERROR)
logger = logging.getLogger(__name__)DOME = {'DEBUG': False,'debug': False
}def exr_func(*args, **kwargs):driver = kwargs.get('driver')if driver:driver.refresh()time.sleep(2)def dec_retry(num=1, exr: Callable = lambda *_, **__: None, catch=Exception, exclude=Exception, out_error=True):@wrapt.decoratordef wrapper(wrapped, instance, args, kwargs):for i in range(1, num + 1):try:return wrapped(*args, **kwargs)except exclude as err:raise errexcept catch as err:logger.error(f'第 {i} 次执行失败')if out_error:logger.error(err, traceback.format_exc(), sep='\n')if DOME.get('DEBUG') or DOME.get('debug'):logger.error('已开启 DEBUG 模式,直接抛出异常')raise errif i >= num:logger.error(f'已执行 {num} 次,抛出异常')raise errlogger.error('开始重试')exr(*args, **kwargs)return wrapper@dec_retry(num=3, exr=exr_func, catch=(NoSuchElementException, WebDriverException, TimeoutException))
def login(driver, username, password):driver.get("https://example.com/login")WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "username")))username_field = driver.find_element(By.ID, "username")username_field.send_keys(username)password_field = driver.find_element(By.ID, "password")password_field.send_keys(password)login_button = driver.find_element(By.ID, "loginButton")login_button.click()WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "logoutButton")))print("登录成功")return Truedef main():driver = webdriver.Chrome()username = "your_username"password = "your_password"try:login(driver, username, password, driver=driver)except Exception as e:logger.error(f"最终登录失败,异常: {e}")driver.quit()if __name__ == "__main__":main()
相关文章:
Python使用selenium访问网页完成登录——装饰器重试机制汇总
文章目录 示例一:常见装饰器编写重试机制示例二:使用类实现装饰器示例三:使用函数装饰器并返回闭包示例四:使用 wrapt 模块 示例一:常见装饰器编写重试机制 示例代码 import time import traceback import logging from typing import Call…...
“微软蓝屏”事件引发的深度思考:网络安全与系统稳定性的挑战与应对
“微软蓝屏”事件暴露了网络安全哪些问题? 近日,一次由微软视窗系统软件更新引发的全球性“微软蓝屏”事件,不仅成为科技领域的热点新闻,更是一次对全球IT基础设施韧性与安全性的深刻检验。这次事件,源于美国电脑安全…...
2024.07纪念一 debezium : spring-boot结合debezium
使用前提: 一、mysql开启了logibin 在mysql的安装路径下的my.ini中 【mysqlid】下 添加 log-binmysql-bin # 开启 binlog binlog-formatROW # 选择 ROW 模式 server_id1 # 配置 MySQL replaction 需要定义,不要和 canal 的 slaveId 重复 参考gitee的项目…...
mysql怎么查询json里面的字段
mysql怎么查询json里面的字段: 要在 MySQL 数据库中查询 JSON 字段中的 city 值,你可以使用 MySQL 提供的 JSON 函数。假设表名是 your_table,包含一个名为 json_column 的 JSON 字段。 以下是一个查询示例,展示如何从 json_colu…...
C++ 右值 左值引用
一.什么是左值引用 右值引用 1.左值引用 左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址可以对它赋值。定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左…...
「JavaEE」Spring IoC 1:Bean 的存储
🎇个人主页 🎇所属专栏:Spring 🎇欢迎点赞收藏加关注哦! IoC 简介 IoC 全称 Inversion of Control,即控制反转 控制反转是指控制权反转:获得依赖对象的过程被反转了 传统开发模式中&…...
springBoot快速搭建WebSocket
添加依赖 在pom.xml中加入WebSocket相关依赖: <dependencies><!-- websocket --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>…...
掌控授权的艺术:Laravel自定义策略模式深度解析
掌控授权的艺术:Laravel自定义策略模式深度解析 在现代Web应用开发中,权限管理是核心功能之一。Laravel框架通过其策略模式提供了一种优雅的方式来处理授权问题。然而,随着应用的复杂性增加,内置的策略可能不足以满足所有需求。这…...
Git操作指令(随时更新)
Git操作指令 一、安装git 1、设置配置信息: # global全局配置 git config --global user.name "Your username" git config --global user.email "Your email"# 显示颜色 git config --global color.ui true# 配置别名,各种指令都…...
SpringSecurity自定义登录方式
自定义登录: 定义Token定义Filter定义Provider配置类中定义登录的接口 自定义AuthenticationToken public class EmailAuthenticationToken extends UsernamePasswordAuthenticationToken{public EmailAuthenticationToken(Object principal, Object credentials) …...
黑神话悟空是什么游戏 黑神话悟空配置要求 黑神话悟空好玩吗值得买吗 黑神话悟空苹果电脑可以玩吗
《黑神话:悟空》的类型定义是一款单机动作角色扮演游戏,但实际体验后会发现,游戏在很多设计上采用了「魂like」作品的常见元素。根据个人上手试玩,《黑神话:悟空》的推进节奏比较接近魂类游戏,Boss战也更像…...
深入浅出消息队列----【延迟消息的实现原理】
深入浅出消息队列----【延迟消息的实现原理】 粗说 RocketMQ 的设计细说 RocketMQ 的设计这样实现是否有什么问题? 本文仅是文章笔记,整理了原文章中重要的知识点、记录了个人的看法 文章来源:编程导航-鱼皮【yes哥深入浅出消息队列专栏】 粗…...
npm提示 certificate has expired 证书已过期 已解决
在用npm新建项目时,突然发现报错提示 : certificate has expired 证书已过期 了解一下,在网络通信中,HTTPS 是一种通过 SSL/TLS 加密的安全 HTTP 通信协议。证书在 HTTPS 中扮演着至关重要的角色,用于验证服务器身份并加密数据传输…...
KEIL如何封装文件成lib
一、为什么要封装文件成LIB 提高编译效率 如果一份文件已经在整个工程中发挥出了我们期待的作用,现在想要将其封装成库,则可以在已经成型的工程文件中将不需要编译的文件从工程全部移出掉,只留下我们需要封装的文件,这样就可以提…...
【python】OpenCV—Faster Video File FPS
文章目录 1、需求描述2、正常方法 cv2.read3、加速方法 imutils.video.FileVideoStream4、涉及到的核心库函数4.1、imutils.video.FPS4.2、imutils.video.FileVideoStream 5、参考 1、需求描述 使用线程和队列数据结构将视频文件的 FPS 速率提高 ! 我们的目标是将…...
JavaScript变量的类型转换
类型转换分为两种:显示类型转换、隐式类型转换 1.显示类型转换 String()Number()Boolean()toString()parseInt(string)parseFloat(string)2.隐式类型转换 (1)isNaN () 判断指定的参数是否为 NaN(非数字类型),返回结果为 Boolean 类型。也就是说:任何不能被转换为数值的…...
如何申请免费SSL证书以消除访问网站显示连接不安全提醒
在当今互联网时代,网络安全已成为一个不可忽视的问题。当用户浏览一些网站时,有时会看到浏览器地址栏出现“不安全”的提示,这意味着该网站没有安装SSL证书,数据传输可能存在风险。那么,如何消除这种不安全提醒&#x…...
关于P2P(点对点)
P2P 是一种客户端与客户端之间,点对点连接的技术,在早前的客户端都是公网IP,没有NAT的情况下,P2P是较为容易实现的。 但现在的P2P,实现上面会略微有一些复杂:需要采取UDP打洞的技术,但UDP打出来…...
前端怎么本地起一个服务查看本地文件
1.安装拓展 安装 Live Server拓展 2.创建一个html文件 3.在html文件中右键选择 Open with Live Server 4.浏览器打开运行的地址,并去除路径,例如:http://127.0.0.1:5500/...
建造者模式(Builder Pattern)
建造者模式(Builder Pattern)是一种创建型设计模式,它主要用于将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。这种设计模式的核心思想是将一个复杂对象的构建分解成多个相对简单的步骤,并…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
