当前位置:   article > 正文

Python使用selenium访问网页完成登录——装饰器重试机制汇总_python selenium登录

python selenium登录

示例一:常见装饰器编写重试机制

示例代码

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 err
                except 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 err
                    if i >= num:
                        logger.error(f'已执行 {num} 次,抛出异常')
                        raise err
                    logger.error('开始重试')
                    exr(*args, **kwargs)

        return dec

    return 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 True

def main():
    # 设置WebDriver
    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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

代码解释

  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 = num
        self.exr = exr
        self.catch = catch
        self.exclude = exclude
        self.out_error = out_error

    def __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 err
                except 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 err
                    if i >= self.num:
                        logger.error(f'已执行 {self.num} 次,抛出异常')
                        raise err
                    logger.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 True

def 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90

示例三:使用函数装饰器并返回闭包

使用闭包使代码更简洁。

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': 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 err
                except 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 err
                    if i >= num:
                        logger.error(f'已执行 {num} 次,抛出异常')
                        raise err
                    logger.error('开始重试')
                    exr(*args, **kwargs)
        return wrapped_func
    return 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 True

def 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

示例四:使用 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 EC

logging.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.decorator
    def wrapper(wrapped, instance, args, kwargs):
        for i in range(1, num + 1):
            try:
                return wrapped(*args, **kwargs)
            except exclude as err:
                raise err
            except 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 err
                if i >= num:
                    logger.error(f'已执行 {num} 次,抛出异常')
                    raise err
                logger.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 True

def 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/910027
推荐阅读
相关标签
  

闽ICP备14008679号