Xpath
date
Jan 12, 2023
slug
xpath
status
Published
tags
Xpath
summary
xpath is xxx
type
Post
Xpath
什么是Xpath
Xpath
是一门在XML
和HTML
文档中查找信息的语言,可用来在XML
和HTML
文档中对元素和属性进行遍历。我们的数据是超文本数据,想要获取超文本数据里面的内容,就要按照一定规则来进行数据的获取,这种规则就叫做Xpath语法。(根据网页结构标签超文本等数据规则对数据进行获取,根据标签规则指定与正则表达式的规则类似)HTML是一种结构化的标记语言。HTML可以描述一个网页的结构信息,是一种树状的结构
- 解析
XML
的一种语言,广泛用于解析HTML数据
HTML是XML的子级
- 几乎所有语言都能使用
Xpath
- 除了Xpath还有其他手段用于XML解析,如:BeautifulSoup、lxxml、SAX等等
Xpath
用于在HTML文档中通过元素HTML标签
和HTML标签的属性
(规则)进行数据的定位使用Xpath的三种方法
插件
用于测试规则能否将数据提取出来
打开百度首页并点击扩展程序,出现左边点击规则右边出现结果的区域
开发者工具Console
在开发者工具的Console中使用$x()
开发者工具Elements
在开发者工具的Elements中按Ctrl+F,在搜索框中输入Xpath。此方法会将所选中内容的标签均标黄
Xpath语法选取数据逻辑
HTML
页面是由标签构成的,这些标签就像整个族谱一样排列有序。所有的HTML标签都有很强的层级关系,正式基于这种层级关系,Xpath语法能够选择出我们想要的数据。节点选取
表达式 | 描述 | 用法 | 说明 |
nodename | 选取此节点的所有子节点 | div | 选取 div 下的所有标签(标签名字) |
// | 从全局节点中选择节点,任意位置均可 | //div | 选取整个 HTML 页面的所有div 标签 |
/ | 选取某个节点下的节点 | //head/title | 选取 head 标签下的title 标签 |
@ | 选取带某个属性的节点 | //div[@id] | 选择带有 id 属性的div 标签 |
. | 当前节点下 | ./span | 选择当前节点下的 span 标签(代脉中为例强大) |
根据标签的特点进行选取
全局节点
//a 找出所有
a
标签下所有的数据节点下的节点
找出
head
内容若只想找出“百度一下,你就知道”的内容,可以选取
head
标签下对应的title
属性内容某个属性节点
在
[]
括号内添加@
,将标签属性填入进去,将含有该标签属性的部分提取出来若想取出
class="text-color"
,可根据a标签中的class属性获取,使用contains
匹配规定class属性包含的字符串。将a下的所有text-color标签内容提取出来,标签之间为内容结构图
为了快速进行筛选,我们也可以通过a标签的父级div进行规则判定,此方法获取的结果是整个内容为一串字符串。它将所有div下id="bottom_layer"的内容提取,因此只有一个结果。若我们想筛选里边的内容数据则需再逐层找出属性值。
将所有的id="bottom_layer"的内容中所有dic标签下的p标签提取,因此有12个结果
若只取出
“关于百度”
一个内容,我们需要观察页面的构造,在div下有若干个p标签,而“关于百度”
在p标签下的a标签里,由此我们可以通过数组索引取出元素若我们想只获取一个特定值还可以通过id属性的唯一性来进行获取,如获取带有
id="s-top-loginbtn"
属性的a
标签Xpath谓词
表达式 | 用法说明 |
//head/meta[k] | 选择所有head下的第 k 个meta标签 |
//head/meta[last()] | 选择所有head下的 最后一个 meta标签 |
//head/meta[position()<3] | 选择所有head下的 前两个 meta标签 |
//div[@id] | 选择带有 id 属性的div标签 |
//div[@id='u1'] | 选择所有拥有 id=u1 的div标签 |
[k] 表示当前位置下的第k个标签;索引值从1开始与编程语言中数组计数不同
Xpath通配符
通配符 | 描述 | 示例 | 结果 |
* | 匹配任意节点 | //div[@id='u1']/* | 选择所有拥有 id=u1 属性的div标签下的所有节点 |
@* | 匹配节点中的任何属性 | //meta[@*] | 选择 所有 拥有属性的meta标签 |
把
div
中所有class="s-bottom-layer-content"
的内容取出。若标签下没有标签属性,则不会被提取出来,会以空格返回选取多个路径
使用
|
来表示选择多个路径等价于和
或者或
的效果//meta|title ->> 选择所有的meta和title,将meta或title标签显示出来
meta标签无内容返回五个空格
@也可以将属性对应的值获取下来,利用
[/@属性]
来提取标签中的属性的内容element-plus标签特征
Xpath表达式总结
- 标签定位
- 最左侧的
/
:必须要从根标签开始逐层的定位目标标签 - 非最左侧的
/
:表示一个层级 - 最左侧的
//
:可以从任意位置定义目标标签
元素无法定位的原因
- 元素没有加载完成
- 元素在
iframe
或者frame
框架里面
- 元素不可用(
disabled
),只读、不可编辑(readonly
),不可见(hidden,style="disable:none;"
)
- 动态属性或者动态的DIV层 即动态的显示与隐藏
style='display:none'
Xpath写出来之后,先在F12验证一下,然后放入测试代码
使用
Xpath根据属性的唯一值定位元素,在搭建自动化环境之后,使用py进行自动化测试
By模块用于定位元素
from selenium.webdriver.common.by import By
driver.find_element(By.XPATH, ‘路径’)
属性 | 内容 | 例子 |
id | 唯一标记 | 36f-6a18 |
tag_name | 标签名 | input |
location | 元素坐标 | {'x':298,'y':188} |
size | 元素大小 | {'height':44,'width':548} |
rect | 元素范围 | {'height': 23, 'width': 26, 'x': 1120, 'y': 19} |
parent | Web Driver实例 | |
screenshot_as_base64() | 截图的base64内容 | iHJVaaaaaaa |
screenshot_as_png() | 截图的二进制内容 | b'\x8976543\y\j |
get_attribute(name) | 获取元素的HTML属性 | target.get_attribute('class') |
value_of_css_property | 获取css属性 | |
click() | 点击 | target.click() |
clear() | 清空内容 | target.clear() |
send_keys(content) | 输入内容 | send_keys('Xpath') |
时间等待方法
- 强制等待
time.sleep(2)
启动2秒后关闭,较为死板写多少秒等多少秒
- 隐式等待
driver.implicitly_wait(10)
不是等待10秒而是元素启动完成后停止,10可换成任意大于0的数
只能判断元素是否存在不能判断元素是否出现,具体等待多少秒由elenium决定无法人工决定
- 显示等待
- 实例化
WebDriver
对象。10表示最长等待时间,定位成功后关闭。可以自定义等待时机判断成功或失败
target_area = WebDriverWait(driver,10).until(
lambda _:driver.find_element(By.XPATH, "//form/span/input")
)
我们以百度首页输入框为例
绝对路径
从根目录
/
开始,一级一级找到目标路径/
出现在开头表示根路径,出现在中间表示下一级找到标签右键 --> copy -->copy full Xpath即可复制标签的绝对路径。使用python语言进行测试。缺点:页面元素进行调整xpath路径失效,绝对路径从根目录开始
from selenium import webdriver
from selenium.webdriver.common.by import By
#不自动关闭浏览器
global driver
#打开浏览器
driver=webdriver.Chrome()
#加载网页
driver.get("http://www.baidu.com")
#绝对路劲定位百度搜索输入框
driver.find_element(By.XPATH, "/html/body/div[1]/div[1]/div[5]/div/div/form/span[1]/input")
driver.quit() #退出浏览器
相对路径
从
//
开始,从选择的元素集去找到目标元素。 可位于开头或中间等任意层级逐层逐级寻找。运行一下程序查找后会打开浏览器并在百度首页搜索
Xpath
缺点:匹配不唯一,所有多个兄弟元素无法具体定位
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
target_area = driver.find_element(By.XPATH, "//form/span/input")
target_area.send_keys('Xpath')
time.sleep(2)
从输入框中如何判断是否输入成功? 我们可以通过获取输入框的内容来进行检验。在上边倒数第二行代码加上
print(target_area.get_attribute("value"))
#输出 Xpath验证成功
我们还可以为此元素截图
target_area.screenshot('target_area.png')
随后文件目录会生成target_area.png
相对路径+索引定位
标签[k]
缺点:页面HTML相同元素进行变化,即下标发生变化会失效
driver.find_element(By.XPATH, "//form/span[1]/input")
相对路径+属性定位
- 通过唯一属性值定位
- 通过同时匹配多个属性值定位 多个属性值之间使用and/or
#匹配<input id="kw" name="wd">
driver.find_element(By.XPATH, "//input[@id='kw'] and @name='wd'")
这些定位可以混合使用
driver.find_element(By.XPATH."//form[@*='form' and @name='f']/span[1]/input")
通过部分属性定位的函数方法:
- contains(@属性名,属性值) 模糊匹配属性值
- substring(@属性,k) k为开始截取的下标 截取属性值以什么结尾
- starts-with(@属性名,属性值) 属性值以什么开头 半模糊匹配
#匹配<input autocomplete="off">
driver.find_element(By.XPATH,"//input[contains(@autocomplete,'ff')]")
#匹配<input class="s_ipt">
driver.find_element(By.XPATH,"//input[substring(@class,3)='ipt']")
driver.find_element(By.XPATH,"//input[starts-with(@class,'s')]")
相对路劲+文本定位
text()
获取元素内文本,点击百度首页的”新闻“连接并实现页面跳转driver.find_element(By.XPATH,"//div[@id='s-top-left']/a[text()='新闻']").click()
link_text,partail_link_text
超链接的文本和部分文本。只能应用于超链接driver.find_element(By.PARTIAL_LINK_TEXT,"新闻").click
初此之外,文本定位可以还可以定位不是超链接(a标签)的值。
如:获取
设置
的类名class
在运行结果中输出类名target_area = driver.find_element(By.XPATH, "//span[text()='设置']")
value = target_area.get_attribute('class')
print(value)
text
还可以与函数进行结合使用//a[starts-with(text(),"新")]
获取span标签名:
target_area = driver.find_element(By.XPATH, "//span[text()='设置']")
print(target_area.tag_name)
#输出span
获取元素的大小位置:
target_area = driver.find_element(By.XPATH, "//span[text()='设置']")
print(target_area.rect)
#输出{'height': 23, 'width': 26, 'x': 1120, 'y': 19}
自动化
什么是自动化
通过机器去完成手工测试的过程
Selenium 关键字驱动类实现:
提取最为常见的操作行为进行二次封装:1.访问url 2.元素定位 3.输入 4.点击 5.关闭 6.等待
from selenium import webdriver
from time import sleep
def open_browser(type_):#通过type_值考虑传入不同的对象从而实现多浏览器支持
#if type_ == 'Chrome':
#driver = webdriver.Chrome()
#elif type_ == 'ie':
#driver = webdriver.Ie()
#else:
#driver = webdriver.Firefox()
try:
driver = getattr(webdriver,type_)()
except Exception as e:
driver = webdriver.Chrome()
return driver
class Key:
#driver = webdriver.Chrome()
#实例化Key对象
def __init__(self,type_ ):
self.driver = open_browser(type_)
self.driver.implicitly_wait(10)
def open(self,url):
self.driver.get(url)
#元素定位
def locate(self,name,value):
return self.driver.find_element(name,value)
#input
def input(self,name,value,txt):
self.location(name,value).send_keys(txt)
#click
def click(self,name.value):
self.locate(name,value).click()
#sleep
def sleep(self,time_):
sleep(time_)
#quit
def quit(self):
self.driver.quit()
对函数进行封装后创建Key.py进行测试
from *** import Key #导入↑封装的函数
Key = Key('Chrome')
key.open('http://www.baidu.com')
key.input('id','kw','Xpath')
key.click('id','su')
key.sleep(3)
key.quit()
#实现效果与前文演示效果一致,但代码更简洁规范
创建Case.py进行基于unittest的测试用例
import unittest
from *** import Key
class Case(unittest.TestCase):
#用例前置
def setUp(self) -> None:
self.key = Key('Chrome')
#用例后置
def tearDown(self) -> None:
self.key.quit()
#测试用例1
def testOne(self):
self.key.open('http://www.baidu.com')
self.key.input('id','kw','Xpath')
self.key.click('id','su')
self.key.sleep(3)
#key.quit()
#测试用例2
def testTwo(self):
self.key.open('http://www.zhihu.com')
if __name__ == '__main__':
unittest.main()
pom设计模式
针对单个系统来执行全方位自动化测试的设计模式
- 写出元素定位表达式
- 写出合适等待方式
- 维护各个元素的定位表达
Page Objects Model页面对象模型(一个页面对应一个类,一个类就是一个模型)
- 类表示页面
- 类属性表示页面中的元素
- 类的方法表示对页面的操作
当我们想对不同页面不同元素进行测试时,需要进行封装
from webdeiver_helper.pom import *
class BeiFanPage(BasePage):
pass