web自动化-元素定位

0811-web自动化-元素定位

1、什么是自动化测试?为什么要做?

将人为驱动的测试行为,转化为机器自动执行的过程。

解决“人”的局限。具体来说,是解决大量重复性测试(如冒烟测试)和频繁的回归测试带来的效率低下、人力成本高、易出错等问题。

2、什么时机适合做自动化?(前提条件)

需求稳定、项目周期长、脚本复用率高、系统相对稳定(Bug率低)

3、什么是selenium?

它是一个Web自动化测试框架,提供了一组API(应用程序编程接口),让我们可以用编程语言(如Python)来控制浏览器。

你的Python代码 -> Selenium API -> 浏览器驱动(如ChromeDriver) -> 真实的浏览器(Chrome)

元素定位--自动化脚本的“眼睛”

1、定位的八种武器

定位方式 方法(By) 特点 适用场景
ID By.ID 最优先,理论上页面唯一 绝大多数有明显ID元素
NAME By.NAME 次选,表单元素常用 输入框、复选框
CLASS_NAME By.CLASS_NAME 通过样式类名定位, 具有特定class的一组元素
TAG_NAME By.TAG_NAME 通过HTML标签名 获取所有同类型标签
LINK_TEXT By.LINK_TEXT 精准匹配超链接的文本 文本内容明确的链接
PARTIAL_link_text By.PARTIAL_LINK_TEXT 模糊匹配超链接文本 文本很长
CSS_SELECTOR By.CSS_SELECTOR 强大、灵活、高效 当ID不唯一或动态时,推荐作为首选
XPATH By.XPATH 几乎可定位任何元素 其他方式都搞不定时的最终方案

2、详解:

<input id="kw" name="wd" class="s_ipt" maxlength="255" autocomplete="off">
1️⃣ ID定位(最优先,最常用)
# 原理:通过元素的 id 属性值定位,理论上页面唯一
# 场景:大多数元素都有id,优先使用
search_input = driver.find_element(By.ID, "kw")
search_input.send_keys("Selenium自动化测试")
2️⃣ NAME定位
# 原理:通过元素的 name 属性值定位
# 注意:name不一定是唯一的,百度搜索框恰好唯一
search_input = driver.find_element(By.NAME, "wd")
search_input.send_keys("Selenium自动化测试")
3️⃣ CLASS_NAME定位
# 原理:通过元素的 class 属性值定位
# 注意:一个元素可能有多个class,且class常用于样式,容易变化
search_input = driver.find_element(By.CLASS_NAME, "s_ipt")
search_input.send_keys("Selenium自动化测试")
4️⃣ TAG_NAME定位(极少单独使用
# 原理:通过HTML标签名定位
# 问题:页面上同一个标签(如input)可能有几十个,定位极不准确
# 示例:百度页面有多个input,下面这行会定位到第一个,不一定是搜索框
first_input = driver.find_element(By.TAG_NAME, "input")
first_input.send_keys("这可能会定位到错误的地方")
# 原理:精确匹配 <a> 标签内的完整文本
# 场景:定位顶部导航链接,如“新闻”、“地图”等
news_link = driver.find_element(By.LINK_TEXT, "新闻")
news_link.click()  # 点击跳转到新闻页面
# 原理:匹配 <a> 标签内包含指定子串的文本
# 场景:链接文本较长,只记得部分关键字
# 示例:匹配所有包含“地图”的链接(实际上会匹配到“地图”这个链接)
map_link = driver.find_element(By.PARTIAL_LINK_TEXT, "图")
map_link.click()
7️⃣ CSS_SELECTOR(推荐首选,强大高效)
# ====== CSS 定位的几种常见写法 ======

# ① 通过ID:使用 # 号
search_input = driver.find_element(By.CSS_SELECTOR, "#kw")

# ② 通过Class:使用 . 号
search_input = driver.find_element(By.CSS_SELECTOR, ".s_ipt")

# ③ 通过标签+属性:使用 [属性='值']
search_input = driver.find_element(By.CSS_SELECTOR, "input[autocomplete='off']")

# ④ 层级定位:父级 > 子级(或 父级 子级)
#    定位搜索按钮:它的父级是 span[class='bgs_btn_wr']
search_btn = driver.find_element(By.CSS_SELECTOR, "span[class='bgs_btn_wr'] > input")
search_btn.click()

# ⑤ 多属性组合:多个 [条件] 写在一起
search_input = driver.find_element(By.CSS_SELECTOR, "input[id='kw'][name='wd']")

# ⑥ 模糊匹配(CSS的独特写法)
#    ^= 表示以某值开头    $= 表示以某值结尾    *= 表示包含某值
# 示例:定位 id 以 'k' 开头的 input
search_input = driver.find_element(By.CSS_SELECTOR, "input[id^='k']")
8️⃣ XPATH(万能方案,最后的选择)
# ====== XPath 定位的几种常见写法 ======

# ① 绝对路径(从根节点/html开始,非常脆弱,不推荐)
#    格式:/html/body/div[...]/div[...]/...
# 危险:页面结构稍微变化,路径就失效
driver.find_element(By.XPATH, "/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input")

# ② 相对路径 + 属性定位(推荐)
#    格式://标签名[@属性='值']
search_input = driver.find_element(By.XPATH, "//input[@id='kw']")

# ③ 相对路径 + 层级定位
#    使用 / 表示直接子级,// 表示任意层级的后代
search_input = driver.find_element(By.XPATH, "//form[@id='form']/span[1]/input")

# ④ 模糊匹配 contains() —— 处理动态ID/Class(★★★★★ 必会)
#    场景:id=search_12345,其中数字动态变化
#    定位 id 包含 'search' 的元素
search_input = driver.find_element(By.XPATH, "//input[contains(@id, 'k')]")  # 'kw' 包含 'k'

# ⑤ 以某值开头 starts-with()
search_input = driver.find_element(By.XPATH, "//input[starts-with(@id, 'k')]")

# ⑥ 文本定位 —— 通过链接文本定位(★★★★★ 必会)
#    定位文本为"新闻"的链接
news_link = driver.find_element(By.XPATH, "//a[text()='新闻']")
#    定位文本中包含"新"的链接
news_link = driver.find_element(By.XPATH, "//a[contains(text(), '新')]")

# ⑦ 逻辑运算 and / or(多条件组合)
#    定位同时满足 id='kw' 且 type='text' 的 input
search_input = driver.find_element(By.XPATH, "//input[@id='kw' and @type='text']")

# ⑧ 选取最后一个元素 last()
#    定位页面中最后一个 input 标签(不一定是搜索框,仅作演示)
last_input = driver.find_element(By.XPATH, "//input[last()]")

三大等待--让脚本学会“耐心等待”

1、三大等待

等待方式 实现方式 特点 优缺点
强制等待 time.sleep(秒) 死等,无论元素是否出现,都必须等够时间 优:简单粗暴,百分百有效。 缺:浪费大量时间,执行效率低
隐式等待 driver.implicitly_wait(秒) 全局设置,在driver的整个生命周期有效。等待元素存在于DOM 优:一次设置,全局生效 缺:不够灵活,无法针对特定条件
显示等待 WebDriverWait+expected_confition 针对特定元素和特定条件进行智能等待 优:最灵活、最精准、效率最高 缺:代码相对复杂

2、详解:

1️⃣ 强制等待 —— time.sleep()
# 特点:不管元素是否已加载,固定等待N秒
# 缺点:浪费时间,降低执行效率
# 场景:仅用于快速调试,或极少数必须等待固定时间的场景

time.sleep(3)  # 不管发生什么,死等3秒
2️⃣ 隐式等待 —— driver.implicitly_wait()
# 特点:全局设置一次,整个driver生命周期有效
# 原理:查找元素时,如果没找到,会每隔0.5秒轮询一次,直到超时
# 缺点:只关心元素是否存在于DOM树,不关心是否可见、可点击

# 设置:在创建driver之后立即设置
driver = webdriver.Chrome()
driver.implicitly_wait(10)  # 设置全局超时时间为10秒

# 之后的所有 find_element 调用都会受此影响
driver.get("https://www.baidu.com")
# 即使网络慢,最多等待10秒,元素出现后立即继续
search_input = driver.find_element(By.ID, "kw")  # 等待元素出现在DOM中
3️⃣ 显式等待 —— WebDriverWait + expected_conditions(★★★★★ 推荐)
# 特点:针对特定元素、特定条件进行智能等待
# 优点:精准、高效,是编写稳定脚本的最佳实践

# ====== 常用等待条件(expected_conditions)详解 ======

# ① 等待元素出现在DOM中(不一定可见)
WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "kw"))
)

# ② 等待元素可见(存在且宽高>0)—— 最常用
search_input = WebDriverWait(driver, 10).until(
    EC.visibility_of_element_located((By.ID, "kw"))
)
search_input.send_keys("Selenium")

# ③ 等待元素可点击(可见且启用)—— 点击前必用
search_btn = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, "su"))
)
search_btn.click()  # 安全点击

# ④ 等待页面标题包含某文字
WebDriverWait(driver, 10).until(
    EC.title_contains("百度")
)

# ⑤ 等待指定元素的文本包含某内容
WebDriverWait(driver, 10).until(
    EC.text_to_be_present_in_element((By.LINK_TEXT, "新闻"), "新闻")
)

# ⑥ 等待元素从DOM中移除(如加载动画消失)
WebDriverWait(driver, 10).until(
    EC.invisibility_of_element_located((By.CLASS_NAME, "loading-spinner"))
)

# ⑦ 等待alert弹窗出现并切换到它
alert = WebDriverWait(driver, 10).until(
    EC.alert_is_present()
)
alert.accept()  # 点击确认
# alert.dismiss()  # 点击取消

# ⑧ 等待frame可切换
WebDriverWait(driver, 10).until(
    EC.frame_to_be_available_and_switch_to_it("frame_name")
)

完整实战示例(百度搜索+结果验证)

# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

# ====== 1. 启动浏览器 ======
driver = webdriver.Chrome()
driver.maximize_window()

# ====== 2. 设置隐式等待(全局保底) ======
driver.implicitly_wait(5)

# ====== 3. 访问百度 ======
driver.get("https://www.baidu.com")

# ====== 4. 显式等待:等待搜索框可见 ======
search_box = WebDriverWait(driver, 10).until(
    EC.visibility_of_element_located((By.ID, "kw"))
)

# ====== 5. 输入搜索内容(多种方式演示) ======
# 方式一:使用 send_keys 输入
search_box.send_keys("Python 自动化测试")

# 方式二:模拟键盘回车键(替代点击搜索按钮)
# search_box.send_keys(Keys.RETURN)

# ====== 6. 显式等待:等待搜索按钮可点击 ======
search_btn = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.ID, "su"))
)

# ====== 7. 点击搜索按钮 ======
search_btn.click()

# ====== 8. 等待搜索结果加载完成(等待第一个结果标题出现) ======
first_result = WebDriverWait(driver, 10).until(
    EC.visibility_of_element_located((By.CSS_SELECTOR, "h3.t a"))
)

# ====== 9. 提取并打印第一个搜索结果的标题文本 ======
print("第一个搜索结果是:", first_result.text)

# ====== 10. 打印当前页面标题 ======
print("页面标题:", driver.title)

# ====== 11. 等待3秒,观察结果 ======
time.sleep(3)

# ====== 12. 关闭浏览器 ======
driver.quit()
对比维度 强制等待 time.sleep() 隐式等待 implicitly_wait() 显式等待 WebDriverWait
生效范围 仅当前行 全局,整个driver生命周期 仅针对特定代码块
等待条件 固定时间 元素存在于DOM树 灵活多样(可见、可点击、文本等)
灵活性 最差 一般 最好
执行效率 最差(浪费大量时间) 中等 最好(条件满足立即继续)
代码复杂度 最简单 简单 稍复杂
推荐程度 ❌ 不推荐 ✅ 建议作为保底 ✅✅✅ 强烈推荐
最佳实践 仅在调试时使用 设置一个较短的全局超时 在关键操作(点击、获取文本)前使用
posted @ 2026-08-15 09:45  珉好好  阅读(2)  评论(0)    收藏  举报