Selenium 是一个强大的工具,用于自动化Web浏览器的操作。XPath(XML Path Language)是Selenium中用来定位页面元素的一种方法,它提供了一种在XML文档中查找信息的语言。以下是Selenium中XPath的一些常见用法:
常用表达式规则
用法 | 名称 | 表达式 | 示例 | 描述 |
绝对路径 | / | /html/body/input | 从根节点html逐级往下找(不跳跃) | |
相对路径 | // | //input | 所有input标签 | |
相对路径 | // | //input[1] | 每个父节点下的第一个input标签 | |
相对路径 | // | //input[last()] | 每个父节点下的最后一个input标签 | |
相对路径 | // | //input[last()-1] | 每个父节点下的倒数第二个input标签 | |
相对路径 | // | //input[position()<4] | 每个父节点下的前3个标签 | |
基础用法 | [@属性名='属性值'] | //*[@id='username'] | id是唯一的,找到id值为'username'的标签 | |
基础用法 | [@属性名='属性值'] | //input[@name='zp'] | 找到所有input标签下name值为'zp'的标签 | |
基础用法 | [@属性名='属性值'] | //button[@class='a b'] | 找到所有button标签下class值为'a b'的标签 | |
属性法 | [@属性名] | //@class | 找到所有具有class属性的标签 | |
属性法 | 运算符 | //*[@width>500] | 属性值是数字的,可以使用运算符进行比较 | |
属性法 | 函数 | starts-with(@属性名,'属性开头的值') | //*[starts-with(@id,'user')] | 找到值以'user'开头的id所在的标签 |
属性法 | 函数 | contains(@属性名,'属性包含的值') | //*[contains(@id,'sernam')] | 找到值中包含'sernam'的id所在标签 |
属性法 | text()='文本' | //*[text()='百度搜索'] | 匹配文本的值,完全匹配。可代替find_element_by_link_text方法 | |
属性法 | contains(text(),'文本包含的值') | //*[contains(text(),'度搜')] | 匹配文本包含的值,模糊匹配。可代替 |
多属性匹配运算符
运算符 | 描述 | 示例 |
and | 与 | age=19 or age=20 |
or | 或 | age>19 and age<21 |
mod | 计算除法的余数 | 5 mod 7 |
| | 计算两个节点集 | //book | //cd |
+ | 加法 | 6 + 4 |
- | 减法 | 6 - 4 |
* | 乘法 | 6 * 4 |
div | 除法 | 8 div 4 |
= | 等于 | age=19 |
!= | 不等于 | age!=19 |
< | 小于 | age<19 |
<= | 小于等于 | age<=19 |
> | 大于 | age>19 |
>= | 大于等于 | age>=19 |
案例介绍
基于chrome 浏览器的console可以进行快速定位测试。
console中调用xpath的基本格式:$x("xpath表达式")
绝对定位与相对定位
- 绝对定位:$x("/xpath表达式")
- 相对定位:$x("//xpath表达式")
1.2 通配符与不包含筛选
属性@
通配符*
不包含not()
包含contains()
selenium 中xpath 常见用法
绝对路径与相对路径
绝对路径:从根节点开始选择元素,使用单斜杠/表示。
示例:/html/body/div[1]/form/input
特点:如果网页结构变化,容易导致定位失败。
相对路径:不从根节点开始,而是从任意位置开始选择元素,使用双斜杠//表示。
示例://input[@name='username']
特点:更灵活,推荐使用。
基于属性定位
使用@符号来选择具有特定属性的元素。
示例://*[@id='loginForm'] 或 //input[@name='password']
基于文本内容定位
使用text()函数来选择包含特定文本的元素。
示例://*[text()='Submit'] 完全匹配
示例://*[contains(text(), 'Sub') 部分匹配
使用逻辑运算符
and 和 or 运算符可以组合多个条件。
示例://input[@type='text' and @name='email']
示例://button[@type='submit' or @class='btn-primary']
使用位置和索引
可以使用方括号[]指定元素的位置或索引。
示例://ul/li[1] 第一个列表项
示例://div[last()] 最后一个
示例://a[position() < 3] 前两个链接
使用通配符
* 表示任何元素。
示例://*[@class='highlight'] 匹配所有类名为highlight的元素,不论标签是什么。
多个属性值匹配
可以通过contains()函数匹配部分属性值。
示例://*[contains(@class, 'btn')] 匹配类名包含btn的所有元素。
属性值以特定字符串开头或结尾
starts-with() 函数用于匹配以特定字符串开头的属性值。
示例://*[starts-with(@id, 'user_')] 匹配ID以user_开头的所有元素。
ends-with() 函数用于匹配以特定字符串结尾的属性值。(注意:此函数仅在支持XPath 2.0及以上版本的浏览器中可用)
组合使用多种定位方式
XPath表达式可以非常复杂,可以根据需要组合多种定位方式。
示例://div[@class='container']//a[contains(@href, 'example.com')]
这些只是Selenium中使用XPath的一部分技巧。XPath的强大之处在于它的灵活性和表达能力,能够帮助测试人员准确定位复杂的HTML结构中的元素。然而,在实际应用中应该尽量保持XPath表达式的简单和可读性,同时要注意避免过于依赖DOM结构,以防页面结构调整后定位器失效。
示例代码:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
# 初始化WebDriver(这里以Chrome为例)
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()))
# 打开目标网页
driver.get('https://example.com')
try:
# 绝对路径与相对路径
absolute_path_element = driver.find_element(By.XPATH, "/html/body/div[1]/form/input")
relative_path_element = driver.find_element(By.XPATH, "//input[@name='username']")
# 基于属性定位
by_id_element = driver.find_element(By.XPATH, "//*[@id='loginForm']")
by_name_element = driver.find_element(By.XPATH, "//input[@name='password']")
# 基于文本内容定位
text_exact_match = driver.find_element(By.XPATH, "//*[text()='Submit']")
text_partial_match = driver.find_element(By.XPATH, "//*[contains(text(), 'Sub')]")
# 使用逻辑运算符
and_operator = driver.find_element(By.XPATH, "//input[@type='text' and @name='email']")
or_operator = driver.find_element(By.XPATH, "//button[@type='submit' or @class='btn-primary']")
# 使用位置和索引
first_li = driver.find_element(By.XPATH, "//ul/li[1]")
last_div = driver.find_element(By.XPATH, "//div[last()]")
first_two_links = driver.find_elements(By.XPATH, "//a[position() < 3]")
# 使用通配符
wildcard_class = driver.find_elements(By.XPATH, "//*[@class='highlight']")
# 多个属性值匹配
contains_class = driver.find_elements(By.XPATH, "//*[contains(@class, 'btn')]")
# 属性值以特定字符串开头或结尾
starts_with_id = driver.find_elements(By.XPATH, "//*[starts-with(@id, 'user_')]")
# 注意:ends-with 函数仅在支持XPath 2.0及以上版本的浏览器中可用
# ends_with_class = driver.find_elements(By.XPATH, "//*[ends-with(@class, 'end')]")
# 组合使用多种定位方式
combined_locators = driver.find_elements(By.XPATH, "//div[@class='container']//a[contains(@href, 'example.com')]")
# 输出找到的元素数量(对于find_elements方法)或者打印元素的文本(对于find_element方法)
print(f"Found {len(combined_locators)} elements using combined locators.")
finally:
# 关闭浏览器
driver.quit()