当前位置: 首页 > news >正文

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

代码解释

  1. 日志配置: 设置日志记录配置,用于输出错误信息。
  2. exr_func 函数: 定义了在每次重试前执行的操作,例如刷新页面。
  3. dec_retry 装饰器: 实现了重试机制,捕获指定异常,在重试次数用尽前会执行 exr_func 函数。
  4. login 函数: 实现具体的登录操作,并被 dec_retry 装饰器装饰。
  5. 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相关依赖&#xff1a; <dependencies><!-- websocket --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>…...

掌控授权的艺术:Laravel自定义策略模式深度解析

掌控授权的艺术&#xff1a;Laravel自定义策略模式深度解析 在现代Web应用开发中&#xff0c;权限管理是核心功能之一。Laravel框架通过其策略模式提供了一种优雅的方式来处理授权问题。然而&#xff0c;随着应用的复杂性增加&#xff0c;内置的策略可能不足以满足所有需求。这…...

Git操作指令(随时更新)

Git操作指令 一、安装git 1、设置配置信息&#xff1a; # global全局配置 git config --global user.name "Your username" git config --global user.email "Your email"# 显示颜色 git config --global color.ui true# 配置别名&#xff0c;各种指令都…...

SpringSecurity自定义登录方式

自定义登录&#xff1a; 定义Token定义Filter定义Provider配置类中定义登录的接口 自定义AuthenticationToken public class EmailAuthenticationToken extends UsernamePasswordAuthenticationToken{public EmailAuthenticationToken(Object principal, Object credentials) …...

黑神话悟空是什么游戏 黑神话悟空配置要求 黑神话悟空好玩吗值得买吗 黑神话悟空苹果电脑可以玩吗

《黑神话&#xff1a;悟空》的类型定义是一款单机动作角色扮演游戏&#xff0c;但实际体验后会发现&#xff0c;游戏在很多设计上采用了「魂like」作品的常见元素。根据个人上手试玩&#xff0c;《黑神话&#xff1a;悟空》的推进节奏比较接近魂类游戏&#xff0c;Boss战也更像…...

深入浅出消息队列----【延迟消息的实现原理】

深入浅出消息队列----【延迟消息的实现原理】 粗说 RocketMQ 的设计细说 RocketMQ 的设计这样实现是否有什么问题&#xff1f; 本文仅是文章笔记&#xff0c;整理了原文章中重要的知识点、记录了个人的看法 文章来源&#xff1a;编程导航-鱼皮【yes哥深入浅出消息队列专栏】 粗…...

npm提示 certificate has expired 证书已过期 已解决

在用npm新建项目时&#xff0c;突然发现报错提示 : certificate has expired 证书已过期 了解一下&#xff0c;在网络通信中&#xff0c;HTTPS 是一种通过 SSL/TLS 加密的安全 HTTP 通信协议。证书在 HTTPS 中扮演着至关重要的角色&#xff0c;用于验证服务器身份并加密数据传输…...

KEIL如何封装文件成lib

一、为什么要封装文件成LIB 提高编译效率 如果一份文件已经在整个工程中发挥出了我们期待的作用&#xff0c;现在想要将其封装成库&#xff0c;则可以在已经成型的工程文件中将不需要编译的文件从工程全部移出掉&#xff0c;只留下我们需要封装的文件&#xff0c;这样就可以提…...

【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 速率提高 &#xff01; 我们的目标是将…...

JavaScript变量的类型转换

类型转换分为两种:显示类型转换、隐式类型转换 1.显示类型转换 String()Number()Boolean()toString()parseInt(string)parseFloat(string)2.隐式类型转换 (1)isNaN () 判断指定的参数是否为 NaN(非数字类型),返回结果为 Boolean 类型。也就是说:任何不能被转换为数值的…...

如何申请免费SSL证书以消除访问网站显示连接不安全提醒

在当今互联网时代&#xff0c;网络安全已成为一个不可忽视的问题。当用户浏览一些网站时&#xff0c;有时会看到浏览器地址栏出现“不安全”的提示&#xff0c;这意味着该网站没有安装SSL证书&#xff0c;数据传输可能存在风险。那么&#xff0c;如何消除这种不安全提醒&#x…...

关于P2P(点对点)

P2P 是一种客户端与客户端之间&#xff0c;点对点连接的技术&#xff0c;在早前的客户端都是公网IP&#xff0c;没有NAT的情况下&#xff0c;P2P是较为容易实现的。 但现在的P2P&#xff0c;实现上面会略微有一些复杂&#xff1a;需要采取UDP打洞的技术&#xff0c;但UDP打出来…...

前端怎么本地起一个服务查看本地文件

1.安装拓展 安装 Live Server拓展 2.创建一个html文件 3.在html文件中右键选择 Open with Live Server 4.浏览器打开运行的地址&#xff0c;并去除路径&#xff0c;例如:http://127.0.0.1:5500/...

建造者模式(Builder Pattern)

建造者模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它主要用于将一个复杂对象的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。这种设计模式的核心思想是将一个复杂对象的构建分解成多个相对简单的步骤&#xff0c;并…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...