Xpath

date
Jan 12, 2023
slug
xpath
status
Published
tags
Xpath
summary
xpath is xxx
type
Post

Xpath

什么是Xpath

Xpath是一门在XMLHTML文档中查找信息的语言,可用来在XMLHTML文档中对元素和属性进行遍历。我们的数据是超文本数据,想要获取超文本数据里面的内容,就要按照一定规则来进行数据的获取,这种规则就叫做Xpath语法。(根据网页结构标签超文本等数据规则对数据进行获取,根据标签规则指定与正则表达式的规则类似)
HTML是一种结构化的标记语言。HTML可以描述一个网页的结构信息,是一种树状的结构
  • 解析XML的一种语言,广泛用于解析HTML数据
HTML是XML的子级
  • 几乎所有语言都能使用Xpath
  • 除了Xpath还有其他手段用于XML解析,如:BeautifulSoup、lxxml、SAX等等
Xpath用于在HTML文档中通过元素HTML标签HTML标签的属性(规则)进行数据的定位

使用Xpath的三种方法

插件

用于测试规则能否将数据提取出来
notion image
打开百度首页并点击扩展程序,出现左边点击规则右边出现结果的区域
notion image

开发者工具Console

在开发者工具的Console中使用$x()
notion image

开发者工具Elements

在开发者工具的Elements中按Ctrl+F,在搜索框中输入Xpath。此方法会将所选中内容的标签均标黄
notion image

Xpath语法选取数据逻辑

HTML页面是由标签构成的,这些标签就像整个族谱一样排列有序。所有的HTML标签都有很强的层级关系,正式基于这种层级关系,Xpath语法能够选择出我们想要的数据。

节点选取

表达式
描述
用法
说明
nodename
选取此节点的所有子节点
div
选取div下的所有标签(标签名字)
//
从全局节点中选择节点,任意位置均可
//div
选取整个HTML页面的所有div标签
/
选取某个节点下的节点
//head/title
选取head标签下的title标签
@
选取带某个属性的节点
//div[@id]
选择带有id属性的div标签
.
当前节点下
./span
选择当前节点下的span标签(代脉中为例强大)
根据标签的特点进行选取

全局节点

//a 找出所有a标签下所有的数据
notion image

节点下的节点

找出head内容
notion image
若只想找出“百度一下,你就知道”的内容,可以选取head标签下对应的title属性内容
notion image

某个属性节点

[]括号内添加@,将标签属性填入进去,将含有该标签属性的部分提取出来
若想取出class="text-color",可根据a标签中的class属性获取,使用contains匹配规定class属性包含的字符串。将a下的所有text-color标签内容提取出来,标签之间为内容
notion image
结构图
notion image
为了快速进行筛选,我们也可以通过a标签的父级div进行规则判定,此方法获取的结果是整个内容为一串字符串。它将所有div下id="bottom_layer"的内容提取,因此只有一个结果。若我们想筛选里边的内容数据则需再逐层找出属性值。
notion image
将所有的id="bottom_layer"的内容中所有dic标签下的p标签提取,因此有12个结果
notion image
notion image
若只取出“关于百度”一个内容,我们需要观察页面的构造,在div下有若干个p标签,而“关于百度”在p标签下的a标签里,由此我们可以通过数组索引取出元素
notion image
若我们想只获取一个特定值还可以通过id属性的唯一性来进行获取,如获取带有id="s-top-loginbtn"属性的a标签
notion image

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"的内容取出。若标签下没有标签属性,则不会被提取出来,会以空格返回
notion image

选取多个路径

使用|来表示选择多个路径等价于或者的效果
//meta|title   ->>   选择所有的meta和title,将meta或title标签显示出来
meta标签无内容返回五个空格
notion image
notion image
@也可以将属性对应的值获取下来,利用[/@属性]来提取标签中的属性的内容
notion image
element-plus标签特征
notion image

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')
时间等待方法
  1. 强制等待
  • time.sleep(2) 启动2秒后关闭,较为死板写多少秒等多少秒
  1. 隐式等待
  • driver.implicitly_wait(10) 不是等待10秒而是元素启动完成后停止,10可换成任意大于0的数
    • 只能判断元素是否存在不能判断元素是否出现,具体等待多少秒由elenium决定无法人工决定
  1. 显示等待
  • 实例化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
notion image

相对路径+索引定位

标签[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()获取元素内文本,点击百度首页的”新闻“连接并实现页面跳转
notion image
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在运行结果中输出类名
notion image
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设计模式

针对单个系统来执行全方位自动化测试的设计模式
  1. 写出元素定位表达式
  1. 写出合适等待方式
  1. 维护各个元素的定位表达
Page Objects Model页面对象模型(一个页面对应一个类,一个类就是一个模型)
  • 类表示页面
  • 类属性表示页面中的元素
  • 类的方法表示对页面的操作
当我们想对不同页面不同元素进行测试时,需要进行封装
from webdeiver_helper.pom import *
class BeiFanPage(BasePage):
    pass
 

© shallrise 2025