当前位置: 首页 > 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;并…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...