封装selenium的常用方法(python)

本章内容为大家分享使用selenium时一些好用但官方未明确制定的接口方法

功能列表:

  • 启动chrome时的参数
  • 对页面元素的增删改查
  • 灵活切换标签页
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import TimeoutException
from selenium.common.exceptions import NoAlertPresentException


class BaseChrome(object):
    """将selenium的Chrome的常用方法进行封装"""

    click_type = ['element_click', 'js_click']
    find_types = [getattr(By, key) for key in By.__dict__.keys() if not key.startswith("__")]

    def __init__(self, executable_path="chromedriver", port=0, service_args=None,
                 desired_capabilities=None, service_log_path=None,
                 chrome_options=None, keep_alive=True):

        """ --- 创建chrome驱动程序的新实例 ---
        :param executable_path: 可执行文件的路径,如果使用默认值,则假定可执行文件位于$PATH中
        :param port: 希望服务运行的端口,如果保留为0,将使用一个空闲随机端口
        :param service_args: 要传递给驱动程序服务的参数列表
        :param desired_capabilities: 具有非特定于浏览器的字典对象,仅限功能,如“代理”或“loggingPref”
        :param service_log_path: 记录驱动程序信息的位置
        :param chrome_options: 不推荐的选项参数
        :param keep_alive: 是否将ChromeRemoteConnection配置为使用HTTP keep alive
        """
        self.options = webdriver.ChromeOptions()
        self.driver = webdriver.Chrome(executable_path=executable_path, port=port,
                                       options=self.chrome_options(),
                                       service_args=service_args,
                                       desired_capabilities=desired_capabilities,
                                       service_log_path=service_log_path,
                                       chrome_options=chrome_options,
                                       keep_alive=keep_alive)

    def chrome_options(self):
        """
        ChromeOptions:
            # 禁用弹出保存弹窗
            self.options.add_experimental_option("profile.default_content_settings.popups", 0)
            # 修改默认下载路径
            self.options.add_experimental_option("download.default_directory", "C:/Users")
            # 允许多文件下载
            self.options.add_experimental_option("profile.default_content_setting_values.automatic_downloads", 1)
        """
        # self.options.add_experimental_option("profile.default_content_settings.popups", 0)
        # self.options.add_experimental_option("download.default_directory", "C:/Users")
        # self.options.add_experimental_option("profile.default_content_setting_values.automatic_downloads", 1)
        return self.options

    def quit_browser(self):
        self.driver.quit()

    def find_element(self, by="xpath", value=None, timeout=5):
        """查找页面中Element元素
        :param by: 获取页面元素的类型: self.find_types
        :param value: 获取元素所需的值
        :param timeout: 超时时间
        :return: WebElement
        """
        if by not in self.__class__.find_types:
            raise ValueError(f"Parameter is out of range: {by}")
        start = time.time()
        while (time.time() - start) < timeout:
            try:
                return self.driver.find_element(by=by, value=value)
            except NoSuchElementException:
                time.sleep(0.2)
        return None

    def find_elements(self, by="xpath", value=None, timeout=5):
        """查找页面中Element元素
        :param by: 获取页面元素的类型: self.find_types
        :param value: 获取元素所需的值
        :param timeout: 超时时间
        :return: WebElement List
        """
        if by not in self.__class__.find_types:
            raise ValueError(f"Parameter is out of range: {by}")
        start = time.time()
        while (time.time() - start) < timeout:
            try:
                return self.driver.find_elements(by=by, value=value)
            except NoSuchElementException:
                time.sleep(0.2)
        return None

    def remove_attribute(self, element: WebElement, name: str):
        """删除Element中某个属性
        :param element: WebElement Object
        :param name: Attribute Name
        :return: None
        """
        self.driver.execute_script("arguments[0].removeAttribute(arguments[1])", element, name)

    def set_attribute(self, element: WebElement, name: str, value=None):
        """在Element中修改属性值, 如果属性不存在则增加
        :param element: WebElement Object
        :param name: Attribute Name
        :param value: Attribute Value
        :return: Attribute Value
        """
        # 如果value为空则将value设置为当前"时分秒"
        if not value:
            value = time.strftime("%H%M%S")
        self.driver.execute_script(f"arguments[0].setAttribute('{name}', arguments[1]);", element, value)
        return value

    def element_click(self, element: WebElement, click_type="element_click"):
        """页面中Element元素点击
        注意: JS点击后WebElement对象会被释放,如再用到需再次捕获
        :param element: WebElement Object
        :param click_type: -> ['element_click', 'js_click']
        :return: None
        """
        if click_type not in self.__class__.click_type:
            raise ValueError(f"Parameter is out of range: {click_type}")
        if click_type == "element_click":
            return element.click()
        """setInterval(function() {document.getElementById("ID").click();}, 500)"""
        self.driver.execute_script("arguments[0].click();", element)

    def get_text(self, element: WebElement):
        """利用JavaScript获取WebElement中的文本
        :param element: WebElement Object
        :return: Text
        """
        return self.driver.execute_script('return arguments[0].innerText', element)

    def scroll_to(self, x=None, y=None):
        """利用JavaScript滚动当前页面, 坐标如为空则滚动到最底部
        :param x: 页面横坐标
        :param y: 页面纵坐标
        :return: None
        """
        if x is None and y in None:
            return self.driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")
        self.driver.execute_script(f"window.scrollTo({x},{y})")

    def catch_by_title(self, title: str):
        """切换到指定窗口标题的窗口,如果没找到则返回默认窗口
        :param title: 窗口标题名: 完整标题或全部标题名中的一部分
        :return: Bool
        """
        handles = self.driver.window_handles
        if len(handles) == 1:
            if title in self.driver.title:
                return True
            return False
        original_window = self.driver.current_window_handle
        handles.remove(original_window)
        for handle in handles:
            self.driver.switch_to.window(handle)
            if title in self.driver.title:
                return True
        self.driver.switch_to.window(original_window)
        return False

    def catch(self, url: str):
        """切换到指定URL的窗口,如果没找到则返回默认窗口
        :param url: url链接: 完整url或url中的一部分
        :return: Bool
        """
        handles = self.driver.window_handles
        if len(handles) == 1:
            if url in self.driver.current_url:
                return True
            return False
        original_window = self.driver.current_window_handle
        handles.remove(original_window)
        for handle in handles:
            self.driver.switch_to.window(handle)
            if url in self.driver.current_url:
                return True
        self.driver.switch_to.window(original_window)
        return False

    def wait_title_change(self, title: str, timeout=5):
        """等待当前标签页的标题发生改变
        :param title: 标签页标题(完整标题或实际标题中的一部分)
        :param timeout: 等待超时时间
        :return: Bool
        """
        # 构建一个超时实例
        wait = WebDriverWait(self.driver, timeout)
        try:
            # 使用expected_conditions中的功能类来判断某一项任务是否发生改变
            return wait.until(expected_conditions.title_contains(title))
        except TimeoutException:
            return False

    def switch_to_frame(self, value, by="WebElement"):
        """页面中切换frame
        by可分为: frame元素对象, frame元素id属性值, frame索引数字(第几个frame)
        use:
        -   frame = driver.find_element(by=By.XPATH, value="//iframe[@class="mainframe"]")
            driver.switch_to_frame(value=frame, by="id")
        -   driver.switch_to_frame(value="mainframe", by="id")
        -   driver.switch_to_frame(value=0, by="index")
        :param value: 指定by参数的frame值
        :param by: -> ["WebElement", "id", "index"]
        :return: None
        """
        if by in ['element', 'id']:
            self.driver.switch_to.frame(value)
        elif by == 'index':
            iframe = self.driver.find_elements(by=By.TAG_NAME, value="iframe")[value]
            self.driver.switch_to.frame(iframe)
        else:
            raise ValueError(f"Parameter is out of range: {by}")

    def frame_to_available_and_switch(self, value, timeout=5):
        """等待frame框架可用并切换到它
        :param value: frame值: id属性值 or WebElement
        :param timeout: 等待超时时间
        :return: 切换成功返回True,否则报错: exceptions.TimeoutException
        """
        wait = WebDriverWait(self.driver, timeout)
        return wait.until(expected_conditions.frame_to_be_available_and_switch_to_it(value))

    def new_window(self, url: str):
        """利用JavaScript创建新的标签页
        :param url: 目标URL
        :return: None
        """
        self.driver.execute_script(f'window.open("{url}")')

    def is_alert_loaded(self, timeout=5):
        """检测当前页面中是否弹出alert弹窗
        :param timeout: 等待超时时间
        :return: Bool
        """
        start = time.time()
        while (time.time() - start) < timeout:
            try:
                return self.driver.switch_to.alert
            except NoAlertPresentException:
                time.sleep(0.2)
        return False

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值