selenium元素定位校验以及遇到的元素操作问题记录

页面元素定位方法及校验

使用比较多的是通过id、class和xpath来对元素进行定位。在定位前可以现在浏览器验证是否可以找到指定的元素。这样就不用每添加一个元素定位都运行代码来检查定位方式表达式是否正确。

  • 使用XPATH定位

    在浏览器F12,找到元素,在元素区域 Ctrl+F,在输入框输入XPATH表达式。如果可以找到就说明表达式没问题。

  • 通过id定位

    浏览器F12,找到控制台,在控制台输入document.getElementById('具体的元素id'),然后回车,如果可以找到,也说明没问题。

  • 通过class定位

    F12浏览器,找到控制台,在控制台输入document.getElementsByClassName('类名'),然后回车,如果可以找到,说明可以用次方法定位。

    例如,百度首页的输入框。

    通过id或class来定位,可以找到相应的元素。注意:通过getElementsByClassName()方法返回的是一个列表。

    document.getElementById('kw')

    document.getElementsByClassName('s_ipt')

    在控制台输入表达式,结果如下:

    通过xpath定位,可以使用相对路劲也可以使用绝对路径。但一般使用相对路劲,表达式会更简洁一些。

    绝对路径:/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input

    相对路径://i[@title='清空']/.../input

    分别在元素模块进行搜索,都能找到唯一一个结果:

对具有属性style="display: none;" 的元素定位

具有style="display: none;" 属性的元素,不会显示也不会占用位置,selenium直接定位的话是定位不到的。

但可以使用显式等待,判断元素是否存在于DOM树中来查找,如下:

python 复制代码
locator = (By.ID, '元素ID')
element = WebDriverWait(self.driver, timeout, 0.2).until(EC.presence_of_element_located(locator))

点击元素报错ElementClickInterceptedException的解决方法

通常情况下,是因为元素还未加载出来或者被遮挡从而导致元素不可点击。

但有时尽管使用显示等待,等元素可点击时再进行点击,也有概率报错:ElementClickInterceptedException: Message: element click intercepted。

通过在点击前强制等待 0.5秒,也还是有报错的几率。于是尝试在点击报错的情况下,换用js的方式来实现元素点击,目前没遇到报错。如下:

python 复制代码
'''此处省略了其他模块的导入'''
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class basepage:
	def find_element(self, locator):
	    by, value = locator
	    return self.driver.find_element(by=by, value=value)
	
	def wait_and_find_element(self, locator, timeout=30):
	    '''等待元素可被定位后,返回元素'''
	    try:
	        return WebDriverWait(self.driver, timeout).until(EC.visibility_of_element_located(locator))
	
	def click_byjs_if_error(self, locator, timeout=30):
	    """ 如果点击元素报错,则尝试换用js点击 """
	    try:
	        ele = WebDriverWait(self.driver, timeout).until(EC.element_to_be_clickable(locator))
	        ele.click()
	    except ElementClickInterceptedException:
	        ele = self.driver.find_element(locator)
	        self.driver.execute_script("arguments[0].click();", ele)
	    except TimeoutException:
	        ele = self.driver.wait_and_find_element(locator)
	        self.driver.execute_script("arguments[0].click();", ele)

3.5.元素定位报错find_element() argument after * must be an iterable, not method

主要是因为元素定位的命名locator和函数命名重复了。将locator换个名称就好了。如下面的代码中,既存在名为fun_name的函数,也存在名为fun_name的定位元祖。将函数或者元祖更名就好了。

python 复制代码
class page:
    def __init__(self):
        """初始化,构造函数"""

    def find_element(self, locator):
        by, value = locator
        return self.driver.find_element(by=by, value=value)

    def fun_name(self):
        """函数具体内容"""

    fun_name = (By.XPATH, "//i[@title='清空']/../input")
    def fun_2(self):
        ele = self.driver.find_element(self.fun_name)

canvas实现的签名功能,用selenium模拟签名

先模拟鼠标按下并移动事件,触发签名。

再获取canvas的上下文,通过canvas的API来实现图片的绘制。

如下:

python 复制代码
def sign_by_js(self, locator):
    """通过js实现签名,locator为canvas的定位元组"""
    element = self.wait_and_find_element(locator)

    script = """
        var mouseDownEvent = new MouseEvent('mousedown', {
            'view': window,
            'bubbles': true,
            'cancelable': true
        });
        
        var mouseMoveEvent = new MouseEvent('mousemove', {
            'view': window,
            'bubbles': true,
            'cancelable': true,
            'clientX': 100, // 移动到x坐标100的位置
            'clientY': 50  // 移动到y坐标50的位置
        });
        
        arguments[0].dispatchEvent(mouseDownEvent); # 触发鼠标按下事件
        arguments[0].dispatchEvent(mouseMoveEvent);# 触发鼠标移动事件
        """
    self.driver.execute_script(script, element)

    # 绘制路径,这里写死了,可自由调整
    script = """
                var canvas = arguments[0];
                var ctx = canvas.getContext("2d");  
                ctx.fillStyle = "black";
                ctx.beginPath();  // 创建一条路径
                ctx.moveTo(80, 80);  //起点
                ctx.lineTo(120, 80);  //终点
                ctx.stroke();  // 绘制
                
				ctx.font = "Bold 40px 幼圆"; //设置字体
				ctx.textAlign = "center";  //设置对其方式
				ctx.fillStyle = "#0000FF"; //设置字体颜色
				ctx.fillText("文字", 170, 80);  //绘制文本,第一个参数为具体的文字,第二、三个参数为需要绘制的位置
                ctx.closePath();
            """
    self.driver.execute_script(script, element)
相关推荐
惜.己11 分钟前
Jmeter中的监听器(二)
测试工具·jmeter·1024程序员节
Yan-英杰26 分钟前
利用Blackbox AI让编程更轻松
图像处理·人工智能·python·深度学习·语言模型
工业互联网专业27 分钟前
Python毕业设计选题:基于BS架构的在线学习与推荐系统的设计与实现-django
vue.js·python·django·毕业设计·源码·课程设计
CSXB991 小时前
三十八、Python(pytest框架-上)
python·功能测试·测试工具·单元测试·pytest
cdut_suye1 小时前
踏入 C++ 的深邃世界:实现 unordered_set 与 unordered_map 的优雅之旅
java·大数据·c++·人工智能·python·深度学习·机器学习
_.Switch1 小时前
高效灵活的Django URL配置与反向URL实现方案
运维·开发语言·数据库·python·django·sqlite·运维开发
股票GPT分析1 小时前
如何利用必盈接口在 C#中完成股票量化程序
运维·服务器·数据库·python·fastapi
深度学习lover1 小时前
<项目代码>YOLOv8 玉米地杂草识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·玉米地杂草识别
聪明的墨菲特i1 小时前
django博客项目实现站内搜索功能
数据库·后端·python·django
前网易架构师-高司机1 小时前
YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLOv11 推理的 C++ 和 Python 实现
c++·python·yolo