【自动化测试】Python Selenium 自动化测试元素定位专业教程

1. 引言:元素定位在 Selenium 中的核心地位

元素定位是 Selenium 自动化测试的基础,所有用户交互操作(如点击、输入、选择)都依赖于准确识别页面元素。Selenium WebDriver 提供了多种定位策略,从简单的 ID 定位到复杂的 XPath 路径,每种策略都有其适用场景和优缺点。随着 Web 应用向动态化、组件化发展(如 React、Vue 框架),元素属性可能频繁变化,掌握高效、稳定的定位方法成为自动化测试工程师的核心能力。本教程将系统讲解 Selenium 元素定位的全部方法,结合 Python 语言实现,从基础到高级,帮助读者构建完整的定位知识体系。

2. 环境准备:搭建 Selenium 测试环境

2.1 安装依赖库

首先需安装 Python 和 Selenium 库。推荐使用 Python 3.7 + 版本,通过 pip 安装 Selenium:

bash

pip install selenium==4.35.0  # 安装指定版本(与教程示例匹配)

2.2 配置浏览器驱动

Selenium 通过浏览器驱动(如 ChromeDriver)控制浏览器,需确保驱动版本与浏览器版本匹配:

  • ChromeDriver:下载地址 CNPM Binaries Mirror,选择与 Chrome 浏览器版本一致的驱动(如 Chrome 126.x 对应 ChromeDriver 126.0.6478.126)。
  • 驱动配置
    • 方法 1:将驱动文件路径添加到系统环境变量PATH
    • 方法 2:在代码中显式指定驱动路径:

      python

      from selenium import webdriver
      from selenium.webdriver.chrome.service import Service# 显式指定ChromeDriver路径
      service = Service(executable_path="C:/drivers/chromedriver.exe")
      driver = webdriver.Chrome(service=service)
      

2.3 验证环境

运行以下代码,若成功打开 Chrome 浏览器并访问百度,则环境配置正确:

python

from selenium import webdriverdriver = webdriver.Chrome()  # 若驱动已在PATH中,可直接初始化
driver.get("https://www.baidu.com")
assert "百度一下" in driver.title  # 验证页面标题
driver.quit()  # 关闭浏览器

3. 传统定位方法:8 种基础策略全解析

Selenium 提供8 种传统定位策略,通过By类调用,适用于不同场景。以下结合示例 HTML(来自 Selenium 官方文档)详细讲解:

html

<!-- 示例HTML:Contact Selenium表单 -->
<form><input type="radio" name="gender" value="m" />Male &nbsp;<input type="radio" name="gender" value="f" />Female <br><label for="fname">First name:</label><br><input class="information" type="text" id="fname" name="fname" value="Jane"><br><label for="lname">Last name:</label><br><input class="information" type="text" id="lname" name="lname" value="Doe"><br><label for="newsletter">Newsletter:</label><input type="checkbox" name="newsletter" value="1" /><br><input type="submit" value="Submit">
</form>
<p>To know more about Selenium, visit the official page <a href="https://www.selenium.dev">Selenium Official Page</a> 
</p>

3.1 ID 定位(By.ID)

  • 原理:通过元素id属性定位,HTML 规范中 id 应唯一,是最优先选择的定位方式。
  • 语法driver.find_element(By.ID, "id_value")
  • 示例:定位 "First name" 输入框(id="fname"):

    python

    from selenium.webdriver.common.by import Byfirst_name = driver.find_element(By.ID, "fname")
    assert first_name.get_attribute("value") == "Jane"  # 验证默认值
    
  • 优势:定位速度快、唯一性高;劣势:动态生成的 id(如包含随机字符串)不适用。

3.2 Name 定位(By.NAME)

  • 原理:通过元素name属性定位,常用于表单元素(如输入框、单选框)。
  • 语法driver.find_element(By.NAME, "name_value")
  • 示例:定位性别单选框(name="gender"):

    python

    # 定位所有name为gender的元素(返回列表)
    gender_radios = driver.find_elements(By.NAME, "gender")
    assert len(gender_radios) == 2  # 验证有2个单选框(男/女)
    gender_radios[1].click()  # 选择"Female"
    
  • 优势:表单元素常用;劣势:name 可能重复(如示例中的 gender),需结合索引或其他条件筛选。

3.3 Class Name 定位(By.CLASS_NAME)

  • 原理:通过元素class属性定位,不支持复合类名(即 class 值包含空格的情况)。
  • 语法driver.find_element(By.CLASS_NAME, "class_value")
  • 示例:定位 class 为 "information" 的输入框:

    python

    info_inputs = driver.find_elements(By.CLASS_NAME, "information")
    assert len(info_inputs) == 2  # 匹配fname和lname两个输入框
    
  • 注意:若 class 值为 "form-control input-lg"(复合类),直接使用会报错,需改用 CSS 选择器(.form-control.input-lg)。

3.4 Tag Name 定位(By.TAG_NAME)

  • 原理:通过 HTML 标签名定位,适用于页面中唯一标签或需批量处理同类标签的场景。
  • 语法driver.find_element(By.TAG_NAME, "tag_name")
  • 示例:定位页面中所有<input>标签:

    python

    inputs = driver.find_elements(By.TAG_NAME, "input")
    assert len(inputs) >= 5  # 表单中至少包含5个input元素(单选框、输入框、复选框、提交按钮)
    
  • 优势:简单直接;劣势:标签名重复率高,通常需结合其他条件(如父元素)使用。

3.5 Link Text 定位(By.LINK_TEXT)

  • 原理:通过超链接的完整可见文本定位,仅适用于<a>标签。
  • 语法driver.find_element(By.LINK_TEXT, "link_text")
  • 示例:定位 "Selenium Official Page" 链接:

    python

    official_link = driver.find_element(By.LINK_TEXT, "Selenium Official Page")
    assert official_link.get_attribute("href") == "https://www.selenium.dev"
    
  • 优势:直观;劣势:文本过长或包含动态内容时不适用。

3.6 Partial Link Text 定位(By.PARTIAL_LINK_TEXT)

  • 原理:通过超链接的部分可见文本定位,支持模糊匹配。
  • 语法driver.find_element(By.PARTIAL_LINK_TEXT, "partial_text")
  • 示例:通过 "Official Page" 定位链接:

    python

    partial_link = driver.find_element(By.PARTIAL_LINK_TEXT, "Official Page")
    assert partial_link.tag_name == "a"  # 验证为链接标签
    
  • 注意:若多个链接包含相同部分文本,仅返回第一个匹配元素。

3.7 CSS Selector 定位(By.CSS_SELECTOR)

  • 原理:通过 CSS 选择器语法定位,支持多种组合条件,灵活性和性能优于 XPath
  • 核心语法
    • ID 选择器:#id(如#fname
    • 类选择器:.class(如.information
    • 属性选择器:[attribute=value](如[name='newsletter']
    • 标签 + 属性:tag[attribute=value](如input[type='submit']
    • 层级选择器:parent > child(如form > input
  • 示例

    python

    # 定位id为lname的元素
    last_name = driver.find_element(By.CSS_SELECTOR, "#lname")
    # 定位name为newsletter的复选框
    newsletter = driver.find_element(By.CSS_SELECTOR, "[name='newsletter']")
    # 定位form下的第一个input子元素
    first_input = driver.find_element(By.CSS_SELECTOR, "form > input:first-child")
    
  • 优势:支持复杂组合定位,浏览器原生支持,速度快;劣势:语法较 XPath 复杂。

3.8 XPath 定位(By.XPATH)

  • 原理:通过 XML 路径表达式定位,支持从任意节点开始遍历,功能最强大但性能略低
  • 核心语法
    • 相对路径://tag[@attribute='value'](如//input[@id='fname']
    • 文本定位://tag[text()='text_value'](如//a[text()='Selenium Official Page']
    • 包含文本://tag[contains(text(), 'partial_text')](如//a[contains(text(), 'Official')]
    • 轴定位://div//input(后代)、//label/following-sibling::input(后续兄弟节点)
  • 示例

    python

    # 定位value为"f"的单选框(Female)
    female_radio = driver.find_element(By.XPATH, "//input[@value='f']")
    # 定位"Last name:"标签后的输入框(通过兄弟节点)
    last_name = driver.find_element(By.XPATH, "//label[text()='Last name:']/following-sibling::input")
    
  • 优势:支持复杂场景(如按文本、层级、属性组合定位);劣势:绝对路径(/html/body/form/input)易受页面结构变化影响,不推荐使用。

3.9 传统定位方法对比表

定位方式语法示例定位速度唯一性适用场景
By.IDBy.ID, "fname"最快最高元素 id 唯一时
By.NAMEBy.NAME, "gender"表单元素(单选框、输入框)
By.CLASS_NAMEBy.CLASS_NAME, "info"同类元素批量定位
By.TAG_NAMEBy.TAG_NAME, "input"最低唯一标签(如<title>
By.LINK_TEXTBy.LINK_TEXT, "官网"链接文本固定且完整
By.PARTIAL_LINK_TEXTBy.PARTIAL_LINK_TEXT, "官"链接文本过长或部分固定
By.CSS_SELECTORBy.CSS_SELECTOR, "#fname"复杂属性组合、性能优先场景
By.XPATHBy.XPATH, "//input[@id='fname']"最高无 id/name、需文本或层级定位

4. Selenium 4 新特性:相对定位(Relative Locators)

Selenium 4 引入相对定位(原 Friendly Locators),允许通过元素间的空间关系定位(如 “上方”“下方”“左侧”“右侧”“附近”),适用于难以通过属性定位但空间位置明确的场景。其原理是通过 JavaScript 的getBoundingClientRect()获取元素坐标,计算相对位置。

4.1 五种相对定位方法

方法名描述语法示例
above定位目标元素上方的元素locate_with(By.TAG_NAME, "input").above((By.ID, "password"))
below定位目标元素下方的元素locate_with(By.TAG_NAME, "input").below((By.ID, "email"))
to_left_of定位目标元素左侧的元素locate_with(By.TAG_NAME, "button").to_left_of((By.ID, "submit"))
to_right_of定位目标元素右侧的元素locate_with(By.TAG_NAME, "button").to_right_of((By.ID, "cancel"))
near定位目标元素附近(50px 内)的元素locate_with(By.TAG_NAME, "input").near((By.ID, "lbl-email"))

4.2 Python 实现示例

需导入relative_locator模块的locate_with函数:

python

from selenium.webdriver.support.relative_locator import locate_with# 场景:定位"Password"输入框上方的"Email"输入框(假设Password的id为"password")
email_input = driver.find_element(locate_with(By.TAG_NAME, "input").above((By.ID, "password"))
)# 场景:定位"Submit"按钮左侧的"Cancel"按钮
cancel_button = driver.find_element(locate_with(By.TAG_NAME, "button").to_left_of((By.ID, "submit"))
)# 链式定位:定位"Email"下方且"Cancel"右侧的按钮
target_button = driver.find_element(locate_with(By.TAG_NAME, "button").below((By.ID, "email")).to_right_of((By.ID, "cancel"))
)

4.3 适用场景与注意事项

  • 适用场景:元素无稳定属性(如动态 id),但空间位置固定(如表单中 “密码框在用户名框下方”)。
  • 注意事项
    • 需先定位参考元素(如示例中的 "password" 输入框);
    • 页面布局变化(如响应式设计)可能导致定位失败;
    • near方法默认范围为 50px,可通过near(locator, distance)自定义距离(如near((By.ID, "lbl-email"), 100))。

5. 定位技巧与最佳实践

5.1 定位器选择优先级

遵循 **“唯一优先、稳定次之、简洁最后”** 原则,推荐优先级:
ID > Name > CSS Selector > XPath > 其他

  • 优先使用 ID/Name:唯一性高、定位速度快;
  • 次选 CSS:性能优于 XPath,语法简洁;
  • 最后选 XPath:功能强大但尽量避免复杂表达式(如多层级轴定位)。

5.2 处理动态元素

动态元素(如 id 包含随机数、属性随页面加载变化)是定位难点,解决方案:

  1. 使用部分属性匹配

     
    • CSS:[id^='user_'](id 以 "user_" 开头)、[class*='btn-'](class 包含 "btn-");
    • XPath://div[contains(@id, 'user_')](id 包含 "user_")。

    python

    # 定位id以"btn-submit-"开头的按钮(如id="btn-submit-12345")
    dynamic_btn = driver.find_element(By.CSS_SELECTOR, "[id^='btn-submit-']")
    
  2. 结合显式等待
    使用WebDriverWait等待元素可交互,避免因加载延迟导致定位失败:

    python

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC# 等待10秒,直到id为"dynamic-element"的元素可见
    wait = WebDriverWait(driver, 10)
    dynamic_element = wait.until(EC.visibility_of_element_located((By.ID, "dynamic-element")))
    

5.3 利用浏览器开发者工具辅助定位

  1. Chrome DevTools

    • F12 打开开发者工具,切换到 "Elements" 面板,按Ctrl+F打开搜索框,输入 CSS 或 XPath 表达式实时验证;
    • 右键元素→"Copy"→"Copy selector"(复制 CSS 选择器)或 "Copy XPath"(复制 XPath)。
  2. 定位插件

    • SelectorHub:自动生成 CSS/XPath,支持可视化定位;
    • ChroPath:验证 XPath/CSS 语法,提供定位建议。

5.4 避免常见错误

  • NoSuchElementException:检查定位器是否正确、元素是否在 iframe 内(需先driver.switch_to.frame("frame_id"))、是否等待元素加载;
  • 复合类名问题By.CLASS_NAME不支持空格分隔的复合类,需改用By.CSS_SELECTOR(".class1.class2")
  • 绝对路径依赖:XPath 绝对路径(如/html/body/div[2]/input)易受页面结构变化影响,优先用相对路径。

6. 综合实例:登录页面元素定位实战

以常见的登录页面为例,综合运用多种定位方法实现自动化登录:

6.1 页面 HTML 结构(简化)

html

<div class="login-form"><label for="username">用户名:</label><input type="text" id="username" name="username" class="form-control"><br><label for="password">密码:</label><input type="password" id="password" name="password" class="form-control"><br><button type="button" id="login-btn" class="btn btn-primary">登录</button><button type="button" class="btn btn-secondary" style="margin-left: 10px;">取消</button><a href="/forgot-password">忘记密码?</a>
</div>

6.2 定位与交互代码

python

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.relative_locator import locate_with# 1. 初始化浏览器
driver = webdriver.Chrome()
driver.get("https://example.com/login")
driver.maximize_window()# 2. 定位元素并交互
try:# 定位用户名输入框(ID定位)username = driver.find_element(By.ID, "username")username.send_keys("test_user")# 定位密码输入框(XPath,通过label关联)password = driver.find_element(By.XPATH, "//label[text()='密码:']/following-sibling::input")password.send_keys("test_password")# 定位"取消"按钮(相对定位:登录按钮左侧)login_btn = driver.find_element(By.ID, "login-btn")cancel_btn = driver.find_element(locate_with(By.TAG_NAME, "button").to_left_of(login_btn))assert cancel_btn.get_attribute("class") == "btn btn-secondary"  # 验证取消按钮样式# 点击登录按钮(CSS选择器)driver.find_element(By.CSS_SELECTOR, "#login-btn").click()# 3. 验证登录成功(显式等待跳转后的欢迎信息)welcome_msg = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//h1[contains(text(), '欢迎回来')]")))print("登录成功!欢迎信息:", welcome_msg.text)finally:driver.quit()  # 无论成功与否,确保浏览器关闭

7. 总结与进阶方向

元素定位是 Selenium 自动化的基石,掌握本文介绍的方法可应对 90% 以上的定位场景。关键要点:

  • 优先选择稳定属性(ID/Name),复杂场景用 CSS/XPath;
  • Selenium 4 相对定位适用于空间关系明确的动态元素;
  • 结合显式等待和浏览器工具提升定位稳定性。

进阶学习方向:

  • Page Object Model(POM):将定位器与操作封装为页面类,提高代码复用性;
  • 动态定位策略:结合 JavaScript 执行(driver.execute_script())定位隐藏元素;
  • 跨框架定位:处理 Shadow DOM(需使用driver.execute_cdp_cmd()调用 Chrome DevTools Protocol)。

通过持续实践与优化定位策略,可构建高效、稳定的 Selenium 自动化测试脚本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/92145.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/92145.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通用代码自用

多文件上传public int save(Role role, RequestParam("nfile") MultipartFile nfile, HttpServletRequest request) {System.out.println(nfile.getOriginalFilename());String path request.getSession().getServletContext().getRealPath("/upload");Fi…

生成式AI如何颠覆我们的工作和生活

原问题&#xff1a; ​你觉得生成式AI未来会如何改变普通人的工作和生活&#xff1f;​ 做过一个对比国外和国内工业化产品制造的简单调研&#xff0c;类似一款定制化的台灯或者语音音响&#xff0c;从零到原型实物&#xff0c; 美国至少需要20万美刀&#xff0c;国内成本大概…

K8S、Docker安全漏洞靶场

1 介绍 一个脆弱基础设施自动化构建框架,主要用于快速、自动化搭建从简单到复杂的脆弱云原生靶机环境。 1.1 项目的缘起 在研究漏洞时,我们经常会发现“环境搭建”这一步骤本身就会占用大量的时间,与之相比,真正测试PoC、ExP的时间可能非常短。由于许多官方镜像在国内的…

使用Nginx部署前后端分离项目

使用Nginx部署前后端分离项目&#xff1a;用户中心系统实践指南 部署前的关键准备 在正式部署前&#xff0c;务必确保前后端在生产环境能正常运行&#xff1a; 前端&#xff1a;测试所有API请求路径和生产环境配置后端&#xff1a;验证数据库连接、环境变量和外部服务集成完整流…

当前就业形势下,软件测试工程师职业发展与自我提升的必要性

软件测试行业正处于深刻变革期&#xff0c;2025年的市场已超越400亿美元规模&#xff0c;预计2027年将增长7% 。在这个技术驱动、效率至上的时代&#xff0c;测试工程师若想保持竞争力&#xff0c;必须主动拥抱变革&#xff0c;系统性提升技能。通过深入分析行业现状与人才需求…

java 之 继承

一、继承 1.1 、什么是继承&#xff1f; 继承就是把所有的类的公共部分&#xff08;相同的成员&#xff09;提取出来&#xff0c;放到一个类中继承需要使用 extends 关键字 public class Animal{ public String name&#xff1b; } public class Dog extends Animal{}Dog 是 An…

强化应急通信生命线:遨游三防平板、卫星电话破局极端灾害救援

暴雨倾盆&#xff0c;山洪咆哮&#xff0c;城市陷入内涝。今年进入汛期以来&#xff0c;我国广东、福建、河南、陕西、京津冀等地相继遭遇暴雨、洪涝、山洪等灾害&#xff0c;道路损毁、基站断网、电力中断等次生问题为应急响应带来严峻挑战。如何保障极端场景下的通信畅通&…

【Linux系统】进程间通信:命名管道

1. 匿名管道的限制匿名管道存在以下核心限制&#xff1a;仅限亲缘关系进程&#xff1a;只能用于父子进程等有血缘关系的进程间通信&#xff08;如通过 fork() 创建的子进程&#xff09;。单向通信&#xff1a;数据只能单向流动&#xff08;一端写&#xff0c;另一端读&#xff…

Python Day24 多线程编程:核心机制、同步方法与实践案例

一、线程事件对象&#xff08;threading.Event&#xff09;threading.Event 用于实现线程间的通信&#xff0c;可让一个线程通知其他线程终止任务&#xff0c;核心是通过 “事件触发” 机制协调线程行为。核心方法&#xff1a;创建事件对象&#xff1a;event threading.Event(…

007 前端( JavaScript HTML DOM+Echarts)

一.html dom运用查找html元素的三种方式通过 id 找到 HTML 元素通过标签名找到 HTML 元素通过类名找到 HTML 元素1.通过 id 找到 HTML 元素<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>msf的网页</title> <…

实习文档背诵

实习内容:1.定时任务与数据补全:基于 XXL-JOB 实现分布式定时任务调度&#xff0c;补全近半年历史操作日志数据&#xff0c;有效解决因网络异常导致的数据缺失问题。业务场景&#xff1b;集团的4a日志半年内没有同步&#xff0c;这边需要把日志数据同步到集团上首先先评估每天的…

分布式CAP定理

CAP 定理在一个分布式系统中&#xff0c;以下三个特性不可能同时完全满足&#xff0c;最多只能满足其中两个&#xff1a;C&#xff08;Consistency&#xff0c;一致性&#xff09;&#xff1a;所有节点在同一时间看到的数据是完全一致的&#xff08;即更新操作成功并返回后&…

PHP-Casbin:现代化 PHP 应用的权限管理引擎

在当今复杂的Web应用中&#xff0c;精细化的权限管理是保障系统安全的关键环节。PHP-Casbin 作为Casbin生态的PHP实现&#xff0c;凭借其灵活的模型支持和强大的扩展能力&#xff0c;已成为PHP开发者实现访问控制的首选工具。 超越传统权限模型 PHP-Casbin 基于PERM&#xff…

FastDeploy2.0:环境变量的说明

一、执行# 设置日志目录 export FD_LOG_DIR/workspace/models/log# 指定使用的 GPU 设备 export CUDA_VISIBLE_DEVICES0,1,2,3# 创建日志目录&#xff08;如果不存在&#xff09; mkdir -p "$FD_LOG_DIR"# 定义日志文件路径 LOG_FILE"$FD_LOG_DIR/fastdeploy_se…

C语言:指针(1-2)

5. 指针运算指针的基本运算有三种&#xff0c;分别是&#xff1a;指针-整数指针-指针指针的关系运算5.1 指针运算在上面&#xff0c;我们知道&#xff0c;数组在内存中是连续存放的&#xff0c;只要知道第一个元素的地址&#xff0c;顺藤摸瓜就能找到后面的所有元素。那么&…

【多模态】DPO学习笔记

DPO学习笔记1 原理1.0 名词1.1 preference model1.2 RLHF1.3 从RLHF到DPOA.解的最优形式B. DPO下参数估计C. DPO下梯度更新D. DPO训练的稳定性2 源代码2.1 数据集构成2.2 计算log prob2.3 DPO loss1 原理 1.0 名词 preference model&#xff1a;对人类偏好进行建模&#xff0…

2025最新、UI媲美豆包、DeepSeek等AI大厂的AIGC系统 - IMYAI源码部署教程

IMYAI 系统部署与使用手册 一、系统演示 &#x1f539; 快速体验 前端演示地址&#xff1a;https://super.imyaigc.com后台演示地址&#xff1a;https://super.imyaigc.com/settings &#x1f539; 技术架构 前端&#xff1a;Vite Vue3 NaiveUI TailwindCSS Plyr后端&…

【关于Java的反射】

在 Java 编程中&#xff0c;反射&#xff08;Reflection&#xff09; 是一个非常强大的工具&#xff0c;它允许你在运行时动态地获取类的信息、创建对象、调用方法和访问字段。虽然反射功能强大&#xff0c;但它也有一些局限性和性能开销&#xff0c;因此需要谨慎使用。一、什么…

Gitee推出“移动软件工厂“解决方案 解决嵌入式与涉密场景研发困局

Gitee推出"移动软件工厂"解决方案 破解嵌入式与涉密场景研发困局 随着数字化转型浪潮的推进&#xff0c;软件开发正面临着前所未有的复杂环境挑战。特别是在嵌入式系统、FPGA开发以及涉密信息系统等特殊场景下&#xff0c;研发团队往往需要在高安全要求与有限网络环境…

低功耗16*8位四线串行8*4按键阵矩LED驱动专用电路

概述&#xff1a;PC0340是占空比可调的LED显示控制驱动电路。由16根段输出、8根位输出、数字接口、数据锁存器、显示存储器、键扫描电路及相关控制电路组成了一个高可靠性的单片机外围LED驱动电路。串行数据通过4线串行接口输入到PC0340&#xff0c;采用LQFP44L的封装形式。本产…