Selenium 提供的另一种,能够唯一定位的方式:
find_element_by_xpath
XPath
基础知识
XPath
(XML Path Language) 是由国际标准化组织W3C
指定的,用来在 XML 和 HTML 文档中选择节点的语言。
目前主流浏览器 (Chrome,Firefox,Edge,Safari) 都支持 XPath
语法。
XPath
相对于 css
选择器的优势:
- 有些场景使用
css
定位元素很麻烦,而XPath
却比较方便 XPath
还有其他领域会使用到,比如爬虫框架Scrapy
, 手机APP
框架Appium
XPath
语法中,整个 HTML 代码的根节点,使用/
表示,这第一点跟 Linux 有相似之处。
定位根节点下的html
节点:/html
定位根节点下 body 节点下的 form 节点:
/html/body/form
通过上面两个简单的例子可发现, XPath
中的 /
与 css
选择器中的 >
功能相似,都表示直接子节点关系
根据绝对路径定位元素
表示从 XPath
根节点/
开始,一直通过查找子元素的方式,定位到指定的元素,就是绝对路径。
实际应用
在上图中,定位百度首页的搜索输入框,通过 /html/body/div/div/div/div/div/form/span/input
最终定位到2个元素,因此最后需要使用下标的方式,达到唯一定位的作用。
注意:XPath
中,下标值也是从 1 开始除最终的 input 标签,前面路径中可以不添加下标值
# find_element_by_xpath 的应用:根据 xpath 绝对路径 定位元素
from selenium import webdriver # 导入 webdriver 模块
from time import sleep # 导入 sleep 模块,可以使程序强制休眠
driver = webdriver.Chrome() # 调用 Chrome 浏览器
driver.maximize_window() # 窗口最大化
driver.get('https://www.baidu.com/') # 打开 百度
sleep(2) # 强制休眠 2 秒
element = driver.find_element_by_xpath("/html/body/div/div/div/div/div/form/span/input[1]") # 根据 绝对路径 定位元素
element.send_keys("自动化测试") # 输入内容
sleep(2) # 强制休眠 2 秒
element1 = driver.find_element_by_xpath("/html/body/div/div/div/a") # 根据 绝对路径 定位元素
element1.click() # 点击
sleep(3) # 强制休眠 3 秒
driver.quit() # 关闭浏览器
根据相对路径定位元素
使用绝对路径,会使得 XPath
语句十分冗长,为了简化 XPath
语句,可以使用 //
,表示从当前节点往下寻找所有的后代元素,不管它在什么位置。
实际应用
# find_element_by_xpath 的应用:根据 xpath 相对路径 定位元素
from selenium import webdriver # 导入 webdriver 模块
from time import sleep # 导入 sleep 模块,可以使程序强制休眠
driver = webdriver.Chrome() # 调用 Chrome 浏览器
driver.maximize_window() # 窗口最大化
driver.get('https://www.baidu.com/') # 打开 百度
sleep(2) # 强制休眠 2 秒
element = driver.find_element_by_xpath("//div/form/span/input[1]") # 根据 相对路径 定位元素
element.send_keys("自动化测试") # 输入内容
sleep(2) # 强制休眠 2 秒
element1 = driver.find_element_by_xpath("//div/div/a") # 根据 相对路径 定位元素
element1.click() # 点击
sleep(3) # 强制休眠 3 秒
driver.quit() # 关闭浏览器
通配符
使用表达式 //div/*
,可以选择页面上所有的 div
节点的所有直接子节点。
根据属性定位元素
与 css
选择器一样, XPath
也可以根据属性来定位元素,语法格式:
[@属性名='属性值']
- 属性名注意前面有
@
符号- 属性值一定要用引号, 可以是单引号,也可以是双引号
根据 id
属性定位
根据 class
属性定位
根据其他属性
实际应用
# find_element_by_xpath 的应用:根据 xpath 属性 定位元素
from selenium import webdriver # 导入 webdriver 模块
from time import sleep # 导入 sleep 模块,可以使程序强制休眠
driver = webdriver.Chrome() # 调用 Chrome 浏览器
driver.maximize_window() # 窗口最大化
driver.get('https://www.baidu.com/') # 打开 百度
sleep(2) # 强制休眠 2 秒
element = driver.find_element_by_xpath("//div/form/span/input[@id='kw']") # 根据 id 属性 定位元素
# element = driver.find_element_by_xpath("//div/form/span/input[@class='s_ipt']") # 根据 id 属性 定位元素
# element = driver.find_element_by_xpath("//div/form/span/input[@name='wd']") # 根据 id 属性 定位元素
element.send_keys("自动化测试") # 输入内容
sleep(3) # 强制休眠 3 秒
driver.quit() # 关闭浏览器
组合属性定位
XPath
支持根据多个属性同时定位元素,语法格式:
//input[@type='text' and @ id='kw']
:定位 type 属性值为 'text' 并且 id 属性值为 'kw' 的 input 元素
根据属性部分匹配
- 包含属性值:
//*[contains(@属性名,'部分属性值')]
,比如,//input[contains(@class,'_ip')]
- 匹配属性值开头:
//*[starts-with(@属性名,'属性值开头')]
,比如,//input[starts-with(@class,'s_ip')]
- 不支持匹配属性值结尾
根据次序定位
XPath
支持根据次序定位元素,而且语法比 css
选择器更简洁,语法格式:
//标签名[下标值]
某类型 第几个 子元素
//div[2]
:定位到 作为第2个子元素的 div 元素;等价于 css
选择器中的 div:nth-of-type(2)
第几个子元素
//div/*[2]
:定位到 父元素为 div 的第二个子元素,不区分类型;等价于 css
选择器中的 div:nth-child(2)
某类型 倒数第几个 子元素
//div[last()]
:定位到 div 类型的最后1个元素;等价于 css
选择器中的 div:nth-last-child(1)
//div[last()-1]
:定位到 div 类型的倒数第2个元素;等价于 css
选择器中的 div:nth-last-child(2)
//div[last()-n]
:定位到 div 类型的倒数第2个元素;等价于 css
选择器中的 div:nth-last-child(n+1)
范围选择
这种定位方式是 css
选择器所不具有的。
//ul/li[position()<=2]
:定位 ul
类型下的第1~2个 li
元素
//ul/li[position()>=last()-1]
:定位 ul
类型下的最后2个 li
元素
组选择
XPath
组选择是使用 |
隔开的,语法格式:
//input | //h3
:选择所有的input
元素与h3
元素,等价于css
选择器中的:input, h3
定位父节点
XPath
选择父节点类似于 Linux 的返回上级目录,使用 /..
,这是 css
选择器不具备的功能,语法格式:
//*[@id='kw']/..
:定位到 id 为 'kw' 的元素的父节点而且还可以继续往上层找父节点:
//*[@id='kw']/../..
定位兄弟节点
XPath
定位兄弟节点,使用 following-sibling::
与 preceding-sibling::
,语法格式:
//*[@id='kw']/following-sibling::*
:定位到 id 为 'kw' 的元素的所有后续兄弟节点,等价于css
选择器中的:#kw~ *
//*[@name='rsv_t']/preceding-sibling::*
:定位到 name 为 'rsv_t' 的元素的所有前面的节点
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。