selenium的基本使用之同级元素属性条件查找

使用selenium操作页面时有时需根据同级元素的属性来定位某元素,并进行操作。

如一个列表,内多个表项,第一列为名称,最后一列为一个按钮,需根据该行第一列内容判断是否点击后面的按钮。

以下以一个具体场景为例展示如何实现:

#!/usr/bin/python
# -*- coding:utf-8 -*-
# @author  : lxy
# @time    : 2024/8/3

"""selenium中的元素查找

本脚本实现批量分离和重连openstack中实例的网络接口(未完成)。
批量操作流程:
    1. 创建webdriver
    2. 进入登录界面,输入登录信息
    3. 进入需要操作的界面
经验:
    1. webdriver和webelements都有find_elements()等方法
    2. 通过直接复制元素的Xpath或full Xpath来定位元素
    3. 通过先定位父元素,来解决同级元素属性作为判断条件的问题

  Typical usage example:

    horizon = OpenStackHorizon(login_url, instance_url, username, password)
    horizon.login()
    horizon.reconnect_port()
"""

import time

from selenium import webdriver
from selenium.common import ElementClickInterceptedException
from selenium.common.exceptions import NoSuchElementException, TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


class OpenStackHorizon:
    def __init__(self, login_url, instance_url, username, password, domain="default"):
        # 初始化webdriver
        options = webdriver.ChromeOptions()
        # options.add_argument('--headless')  # 无头模式,不打开实际的浏览器窗口
        options.add_argument('--ignore-certificate-errors')  # 忽略证书错误
        self.driver = webdriver.Chrome(options=options)

        self.login_url = login_url
        self.instance_url = instance_url
        self.username = username
        self.password = password
        self.domain = domain

    def login(self):
        try:
            # 打开登录页面
            self.driver.get(self.login_url)
            # 等待并找到用户名输入框
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.NAME, "username"))
            )

            # 输入用户名和密码
            self.driver.find_element(By.NAME, "domain").send_keys(self.domain)
            self.driver.find_element(By.NAME, "username").send_keys(self.username)
            self.driver.find_element(By.NAME, "password").send_keys(self.password)

            # 提交表单
            self.driver.find_element(By.XPATH, '//button[@type="submit"]').click()

            # 确认登录成功,等待某个已知会出现在登录成功后的元素,例如导航栏中的一个元素
            WebDriverWait(self.driver, 10).until(
                EC.presence_of_element_located((By.ID, "main_content"))
            )
            print("登录成功")

        except (ElementClickInterceptedException, TimeoutException) as e:
            print(f"登录失败: {e}")

    def reconnect_port(self):
        try:
            # 访问实例页面
            self.driver.get(self.instance_url)

            # 等待页面加载,并确保特定数据行存在
            WebDriverWait(self.driver, 20).until(
                EC.presence_of_element_located((By.TAG_NAME, "tbody"))
            )

            for i in range(1, 61):

                # 确保表格内容已加载,等待特定行内容出现
                while True:
                    rows = self.driver.find_elements(By.XPATH, "//tbody/tr")
                    if len(rows) >= 3:
                        break
                    time.sleep(1)

                # 过滤实例列表
                self.driver.find_element(By.XPATH, '//*[@id="instances"]/caption/div/div[1]/div/button').click()
                # 对于固定的元素,直接在浏览器中复制其Xpath即可。
                WebDriverWait(self.driver, 20).until(
                    EC.presence_of_element_located((By.XPATH, '//*[@id="instances"]/caption/div/div[1]/div/ul/li[2]/a'))
                )
                self.driver.find_element(By.XPATH, '//*[@id="instances"]/caption/div/div[1]/div/ul/li[2]/a').click()
                self.driver.find_element(By.XPATH, '//*[@id="instances"]/caption/div/div[1]/input').send_keys(
                    "scada-{}".format(i))
                self.driver.find_element(By.XPATH, '//*[@id="instances__action_filter"]').click()

                # 等待筛选结果
                WebDriverWait(self.driver, 10).until(
                    EC.presence_of_element_located((By.XPATH, "//tbody/tr"))
                )

                # 查找匹配的行
                # 这种不固定的元素,可以复制其full Xpath,观察需要的内容。
                # 在此例情况中,按条件筛选后获得一个列表,列表第一列中包含实例名,最后一列中包括一个可互动的按钮(链接)
                # 现要根据实例名选取对应行,点击对应按钮
                # 可先根据列表Xpath,find_elements获取所有表项,然后逐行处理
                rows = self.driver.find_elements(By.XPATH, "//tbody/tr")
                for row in rows:
                    try:
                        # 找到第一列的链接内容
                        instance_name = row.find_element(By.XPATH, "./td[1]/a").text
                        if instance_name == "scada-{}".format(i):
                            # 找到并点击目标元素
                            target_element = row.find_element(By.XPATH, "./td[13]/div/a[2]")
                            target_element.click()
                            """
                            未完待续,继续需要的操作即可
                            """
                            break
                    except NoSuchElementException:
                        continue

        except (ElementClickInterceptedException, TimeoutException) as e:
            print(f"操作失败: {e}")

    def __del__(self):
        # 退出webdriver
        self.driver.quit()


def main():
    # 使用示例
    login_url = "http://10.254.0.100/horizon/auth/login/"
    instance_url = "http://10.254.0.100/horizon/project/instances/"
    username = "admin"
    password = "adminpasswd"

    horizon = OpenStackHorizon(login_url, instance_url, username, password)
    horizon.login()
    horizon.reconnect_port()


if __name__ == "__main__":
    main()
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值