基于Python的selenium入门超详细教程(第1章)--WebDriver API篇
学习路线
自动化测试介绍及学习路线-CSDN博客
自动化测试之Web自动化(基于python+selenium)-CSDN博客
参照博文:selenium入门超详细教程——网页自动化操作-CSDN博客
目录
前言
一、WebDriver API介绍
1.1 什么是WebDriver?
1.2 工作原理
二、基础用法
四大操作--针对浏览器本身
★定位标签元素
定位标签元素最基础的方法和操作
针对select下拉框标签元素的select操作
切换iframe层
延时等待
显示等待
隐式等待
模拟鼠标操作ActionChains
常用操作
模拟键盘操作Keys
常用操作
三、进阶用法
XPATH和CSS_SELECTOR方法定位元素,搭配使用Chropath与Xpath helper插件
上传文件与Spy++
两大切换
切换到弹出框
切换窗体
四、JS操作
滚动条
常见问题:
找不到对象
学习过程中的问题记录
前言
前面已经对selenium有了简单的了解,Selenium 是一个用于 Web 应用程序测试的工具集,它能够模拟用户在浏览器中的操作,比如点击按钮、输入文本、切换页面等。通过 Selenium,我们可以轻松地与各种主流浏览器(如 Chrome、Firefox、Edge 等)进行交互,驱动浏览器,模拟浏览器的操作,为自动化测试提供了坚实的基础
并且已经在Python环境下搭建好了selenium环境,从这篇开始,将正式学习selenium的webdriver框架。我们平常说的selenium自动化,其实它并不是类似于QTP之类的有GUI界面的可视化工具,我们要学的是webdriver框架的API。
本篇主要讲如何用Python调用webdriver框架的API,对浏览器元素做一些常规的操作,如定位元素、基本元素的操作,下拉框选择,滚动条,不同层切换,模拟鼠标,模拟键盘,进阶的上传文件,弹出框操作,窗体切换操作。
一、WebDriver API介绍
1.1 什么是WebDriver?
WebDriver API 是 Selenium 自动化测试框架中的核心部分,它提供了一组用于自动化浏览器操作的编程接口,通过这些接口,测试人员或者开发者能够模拟用户在浏览器中的各种行为,实现对 Web 应用程序的自动化测试。
1.2 工作原理
WebDriver 通过与浏览器的驱动程序进行通信来实现对浏览器的控制。不同的浏览器需要使用相应的驱动程序,如 Chrome 浏览器需要使用 ChromeDriver,Firefox 浏览器需要使用 GeckoDriver。当你调用 WebDriver API 中的方法时,这些指令会被发送到对应的浏览器驱动程序,驱动程序再将指令转化为浏览器可以理解的操作,从而实现对浏览器的自动化控制。即:
- 客户端编写脚本--->运行浏览器驱动--->打开浏览器--->执行脚本
二、基础用法
首先,确保你已经安装了Python和Selenium库以及相应的浏览器驱动
注:本文采用的是selenium4.0版本,部分语句同其他文章可能存在不一致现象
#导入webdriver模块
from selenium import webdriver
#最新的 Selenium 4 版本中,引入了 Service 类来更好地管理浏览器驱动服务
from selenium.webdriver.chrome.service import Service#selenium4.0版本语法
#写入之前解压保存的路径,获取浏览器驱动
e=Service(executable_path=r'D:\WebDriver\MicrosoftWebDriver.exe')
#使用浏览器驱动,打开浏览器
driver=webdriver.Edge(service=e)
针对浏览器本身
- 打开网页
打开百度网址
driver.get("https://www.baidu.com/") #访问百度
- 设置窗口大小和位置
有时需要测试网站在不同屏幕尺寸下的显示效果,确保页面元素在各种分辨率和显示设备上均能正确显示和操作。
driver.set_window_size(1024, 768) #设置窗口尺寸(width,height) driver.maximize_window() #最大化窗口 driver.set_window_position(100,200) #设置窗口位置(x,y)
- 设置休眠
selenium4.0版本存在程序执行完成后自动关闭窗口的现象,此外有时页面加载过久,而又需要等待某些操作完成,此时可以通过设置休眠时间强制让程序暂停执行一段时间
from time import sleep sleep(2) #停止2s,可以是小数,以秒为单位
- 退出
退出有两种方式,一种是close;另外一种是quit
close方法用于关闭当前窗口或标签,但不会退出浏览器会话,如果只有一个标签页,close 会关闭浏览器
quit方法用于退出浏览器会话,关闭所有窗口和标签,结束webdriver进程,可以回收c盘的临时文件
driver.close() driver.quit()
以上是本文将会使用到的基本方法语句,想要再深入了解其他用法可查询:python+selenium自动化软件测试(第2章):WebDriver API - Web自动化测试 - 博客园
★定位标签元素
from selenium.webdriver.common.by import By(导入类By)driver.find_element(By.元素属性,值).操作名() #根据元素属性和值找到唯一对应元素并执行相关操作
元素定位和操作是使用selenium进行自动化测试非常核心和关键的步骤,通过元素定位可以找到Web页面上的各种元素,如文本框、按钮、链接等,从而进行后续的操作
补充:
可以前往该网页了解各HTML前端网页标签的含义,帮助更好的定位元素HTML 标签列表(字母排序) | 菜鸟教程
或查看博文:【等我写一篇啊】
元素属性 | 常用操作 |
---|---|
ID:id值 | 输入:send_keys('要输入的内容') |
NAME:name值 | 点击:click() |
CLASS_NAME:class值 | 选择:select 下拉列表操作 |
LINK_TEXT:超链接的内容 <a> 它通过匹配超链接的完整文本来找到对应的元素 | 获取元素的文本值:元素.text |
PARTIAL_LINK_TEXT:部分超链接的内容 | 获取元素的属性:el1.get_attribute("name") |
TAG_NAME:标签名 【不常用】 Tag Name是HTML标签的名称,例如<input>、<button>、<a>等 | |
XPATH:路径 在 XML 文档中对元素和属性进行遍历, 使用路径表达式来选取 XML 文档中的节点或者节点集,例如//div[@class="file"]/button | |
CSS_SELECTOR:css |
以百度为例,我们进入首页,按 【F12】 进入开发者工具。红框中显示的就是页面的代码,我们要做的就是从代码中定位获取我们需要的元素。使用途中框选出的选择工具可以快速查询某一特点标签元素的详情,例如查找这里百度一下的输入框
可以看到这个<input>y有对应的class,name以及id
定位标签元素最基础的方法和操作
driver.find_element(By.ID, 'id_value').click()
driver.find_element(By.NAME, 'name_value').send_keys('要输入的内容')
driver.find_element(By.CLASS_NAME, 'class_name')
driver.find_element(By.LINK_TEXT, 'all_link_text')
driver.find_element(By.PARTIAL_LINK_TEXT, 'partial_link_text')
driver.find_element(By.TAG_NAME, 'tag_name')
针对select下拉框标签元素的select操作
针对该<select>下拉框标签的相关操作,可以通过先定位select框,再定位select里的选项的二次定位方法,或通过XPATH遍历路径直接定位;但selenium还提供了更高级的玩法,通过导入Select模块。直接根据属性或索引定位
#下拉框的选择 标签名:<select>
##导入select模块,选择Select类
from selenium.webdriver.support.select import Select
select_elem=driver.find_element(By.ID,'role') #获取下拉框元素
# Select(select_elem).select_by_index(2) #根据select的option索引
# Select(select_elem).select_by_value('pm') #根据option的value
Select(select_elem).select_by_visible_text('项目经理') #根据显示的值
切换iframe层
有时我们会发现就算显示在了当前界面中没被遮挡,定位的方式也换了很多种但就是不能定位到想要的标签元素。这可能是由于元素处在<iframe>标签元素下
在Web页面中,有时候会存在iframe(内联框架)元素,也就是嵌套在页面中的另一个页面,通过iframe可以将多个不同的页面内容组合在一起。在自动化测试中,当页面中存在iframe时,Selenium需要切换到对应的iframe中才能操作其中的元素。
因此,Selenium提供了switch_to_frame方法来实现在不同的iframe之间进行切换,使得测试脚本可以准确地定位到需要操作的元素
不在同一层:切换层,切换到不同的iframe里面; 若存在iframe嵌套关系,需要多次切换
#切换层,切换到不同的iframe,switch_to.frame(id/name/index)
driver.switch_to.frame('appIframe-admin') #切换到对应层
driver.find_element(By.LINK_TEXT, '人员').click()switch_to.default_content() #切回默认层
延时等待
有时我们会发现,明明定位方式无误,元素也确实存在于页面中,但在执行定位元素的操作时却抛出找不到元素的异常。这可能是由于页面元素的加载需要一定时间,而代码执行速度过快,在元素还未完全加载到页面上时就尝试进行定位操作。
在 Web 页面中,元素的加载速度受到多种因素的影响,比如网络状况、服务器响应时间、页面的复杂度等。一些动态加载的元素,如通过 AJAX 技术加载的内容,可能需要在页面加载完成后额外的时间才能显示出来。在自动化测试中,如果不考虑这些因素,直接进行元素定位和操作,很容易导致测试失败。
因此,Selenium 提供了延时等待机制,让脚本在执行过程中暂停一段时间,等待元素加载完成后再进行后续操作,从而确保测试脚本能够准确地定位和操作元素
等待方式 | 用法 |
强制等待 | time模块的sleep()方法,让进程强制停止运行 |
显示等待 | 直到指定元素出现为止,结束等待;若超出指定时间则返回异常 |
隐式等待 | 浏览器在设定的时间内不断刷新页面来寻找元素,加隐式等待可显著提升测试脚本运行速度 |
显示等待
原理:显示等待,就是明确的要等到某个元素的出现或者是某个元素的可点击等条件,等不到,就一直等,除非在规定的时间之内都没找到,那么久跳出Exception。(简而言之,就是直到元素出现才去操作,如果超时则报异常)
语法:WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
driver
:WebDriver对象,即浏览器驱动对象,用于执行浏览器操作。timeout
:最长等待时间,即等待条件成立的最大时长。如果超过这个时间条件仍未成立,则抛出TimeoutException
异常。poll_frequency
:检测条件变化的时间间隔,默认为0.5秒。即每隔poll_frequency
秒检查一次条件是否成立。ignored_exceptions
:在等待过程中忽略的异常类型。如果设置了该参数,当被忽略的异常发生时,不会导致等待失败。
from selenium.webdriver.support.ui import WebDriverWait #等待方法
from selenium.webdriver.support import expected_conditions as EC #结束等待情况
# 退出禅道
if WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,'appIframe-my'))): #等待By.ID,'appIframe-my'元素出现,等待结束
until(method,message=‘’)
method: 在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是False
message: 如果超时,抛出TimeoutException,将message传入异常
until_not(method,message=‘’): 与until相反,until是当某元素出现或什么条件成立则继续执行,until_not是当某元素消失或什么条件不成立则继续执行,参数也相同。
其中until(EC.presence_of_element_located())指的是当指定元素出现是结束等待,还有如下其他几种情况:
from selenium.webdriver.support import expected_conditions as EC
# 判断标题是否和预期的一致
title_is
# 判断标题中是否包含预期的字符串
title_contains
# 判断指定元素是否加载出来
presence_of_element_located
# 判断所有元素是否加载完成
presence_of_all_elements_located
# 判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0,传入参数是元组类型的locator
visibility_of_element_located
# 判断元素是否可见,传入参数是定位后的元素WebElement
visibility_of
# 判断某个元素是否不可见,或是否不存在于DOM树
invisibility_of_element_located
# 判断元素的 text 是否包含预期字符串
text_to_be_present_in_element
# 判断元素的 value 是否包含预期字符串
text_to_be_present_in_element_value
#判断frame是否可切入,可传入locator元组或者直接传入定位方式:id、name、index或WebElement
frame_to_be_available_and_switch_to_it
#判断是否有alert出现
alert_is_present
#判断元素是否可点击
element_to_be_clickable
# 判断元素是否被选中,一般用在下拉列表,传入WebElement对象
element_to_be_selected
# 判断元素是否被选中
element_located_to_be_selected
# 判断元素的选中状态是否和预期一致,传入参数:定位后的元素,相等返回True,否则返回False
element_selection_state_to_be
# 判断元素的选中状态是否和预期一致,传入参数:元素的定位,相等返回True,否则返回False
element_located_selection_state_to_be
#判断一个元素是否仍在DOM中,传入WebElement对象,可以判断页面是否刷新了
staleness_of
隐式等待
原理:隐式等待,就是在创建driver时,为浏览器对象创建一个等待时间,这个方法是得不到某个元素就等待一段时间,直到拿到某个元素位置。
注意:在使用隐式等待的时候,实际上浏览器会在你自己设定的时间内不断的刷新页面去寻找我们需要的元素
需要特别说明的是:隐性等待对整个 driver 的周期都起作用,所以只要设置一次即可(在最开始设置一次就可以了),切不要当作固定等待使用。
###隐式等待:浏览器在设定的时间内不断刷新页面来寻找元素
# 加隐式等待可显著提升测试脚本运行速度
# implicitly_wait()设置等待时间,如果到时间有元素节点没有加载出来,就会抛出异常
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
e=Service(executable_path=r'D:\WebDriver\MicrosoftWebDriver.exe') #写入之前解压保存的路径
driver=webdriver.Edge(service=e) #获取浏览器驱动
driver.implicitly_wait(10)
模拟鼠标操作ActionChains
既然是模拟浏览器操作,自然也就需要能模拟鼠标的一些操作了,这里需要导入ActionChains 类。
from selenium.webdriver.common.action_chains import ActionChains
常用操作
操作 | 函数 |
---|---|
右击 | context_click() |
双击 | double_click() |
拖拽 | double_and_drop() |
悬停 | move_to_element() |
执行 | perform() |
#鼠标事件
from selenium.webdriver.common.action_chains import ActionChains
driver.maximize_window() #窗口最大化
driver.get(r"https://www.baidu.com/") #访问baidutarget_elem=driver.find_element(By.ID,'s-usersetting-top')
ActionChains(driver).move_to_element(target_elem).perform()
time.sleep(10)
模拟键盘操作Keys
既然是模拟浏览器操作,自然也就需要能模拟键盘的一些操作了,这里需要导入Keys类。
from selenium.webdriver.common.keys import Keys
常用操作
操作 | 函数 |
---|---|
删除键 backspace | send_keys(Keys.BACK_SPACE) |
空格键 space | send_keys(Keys.SPACE) |
制表键 tab | send_keys(Keys.TAB) |
回退键 esc | send_keys(Keys.ESCAPE) |
回车 enter | send_keys(Keys.ENTER) |
全选 ctrl+a | send_keys(Keys.CONTRL,‘a’) |
复制 ctrl+c | send_keys(Keys.CONTRL,‘c’) |
剪切 ctrl+x | send_keys(Keys.CONTRL,‘x’) |
粘贴 ctrl+v | send_keys(Keys.CONTRL,‘v’) |
键盘F1键 | send_keys(Keys.F1) |
#键盘事件
from selenium.webdriver.common.keys import Keys
driver.maximize_window() #窗口最大化
driver.get(r"https://www.baidu.com/") #访问baidu
driver.find_element(By.ID,'kw').send_keys("python学习路线")
driver.find_element(By.ID,'kw').send_keys(Keys.BACK_SPACE)
time.sleep(10)
三、进阶用法
XPATH和CSS_SELECTOR方法定位元素,搭配使用Chropath与Xpath helper插件
XPATH:
- 绝对路径查找元素
从根节点位置到目标位置
/html/body/div[2]/table/tbody/tr[1]/td[1]
- 相对路径查找元素
从指定节点位置到目标位置
//table[@class='tb']/tbody/tr[1]/td[1]
CSS_SELECTOR:
By.CSS_SELECTOR, 'div p' | 获取<div>标签内部所有的<p>标签元素 |
By.CSS_SELECTOR, ’div>p‘ | 获取所有父亲标签为<div>的<p>标签元素 |
By.CSS_SELECTOR, ’div+p‘ | 获取所有紧接在<div>标签之后的<p>标签元素 |
By.CSS_SELECTOR, '#d2' | 获取所有id属性值为d2的标签元素 |
By.CSS_SELECTOR, ‘.td’ | 获取所有class属性值为td的标签元素 |
By.CSS_SELECTOR, ’[text-align="center"]‘ | 获取其他属性,例如text-align属性值为center的所有标签元素 |
By.CSS_SELECTOR, '[type]' | 获取带有type属性的所有标签元素 |
By.CSS_SELECTOR, '[type~="text"]' | 获取带有type属性且属性值包含text的所有标签元素,模糊查询 |
By.CSS_SELECTOR, 'a[href^="https"]' | 获取所有标签<a>的href属性值以https开头的所有<a>标签元素 |
By.CSS_SELECTOR, 'a[src$=".jpg"]' | 获取所有标签<a>的src属性值以.jpg结尾的所有<a>标签元素 |
By.CSS_SELECTOR, 'a[src*="xxx"]' | 获取所有标签<a>的src属性值包含xxx的所有<a>标签元素 |
By.CSS_SELECTOR, ''.tb2 td:nth-child(n)' | 获取class属性值为tb2父标签的第n个子元素的所有<td>标签元素 |
注:多个列表值用find_elements()方法,以列表形式返回
一般来说xpath和css_selector方式定位元素较为复杂,首先考虑基础定位元素方法能否简便的定位元素然后再考虑使用该两种方法,同时可以借助Xpath_helper和Chropath插件帮助我们编写XPATH和CSS_SELETOR的定位语句
这里介绍Edge如何下载:
重启浏览器后,打开此扩展 即可使用
chropath安装地址:【免费】chropath安装包crx6.1.7下载资源-CSDN文库
使用方法参照博文:xpath-helper、chropath下载使用方式 及 selenium中如何配置浏览器插件-CSDN博客
上传文件与Spy++
搭配Spy++工具实现上传文件
下载路径:【免费】Spy++各版本安装包资源-CSDN文库
使用参照:Microsoft SPY++ 使用教程及实操-CSDN博客
步骤
- 使用Spy++来识别上传文件对话框窗口的窗口控件信息,包括窗口句柄、控件类名、控件ID等。
- 导入pywin32库,在Selenium中使用相关的命令和方法,通过窗口句柄或其他标识找到对应的控件,并进行操作。
- 通过Selenium的方法模拟点击上传文件按钮、输入文件路径等操作,实现文件上传功能。
上传文件
import win32gui
import win32con
win1=win32gui.FindWindow('#32770','打开') #查找第一层窗体
win2=win32gui.FindWindowEx(win1,None,'ComboBoxEx32',None) #查找第二层窗体
win3=win32gui.FindWindowEx(win2,None,'ComboBox',None) #查找第三层窗体
# edit=win32gui.FindWindowEx(win3,None,'Edit',None) #查找第三层窗体下的填写文件路径文本框
button=win32gui.FindWindowEx(win1,None,'Button','打开(&O)') #查找第一层窗体下的打开按
if win3: #检查是否正常获取到窗体# 查找编辑框控件edit = win32gui.FindWindowEx(win3, None, 'Edit', None) # 查找第三层窗体下的填写文件路径文本框if edit:text = r'C:\Users\92870\Desktop\Rose introduction.txt'win32gui.SendMessage(edit, win32con.WM_SETTEXT,None, text)else:print("未找到编辑框控件")
else:print("未找到主窗口")
# win32gui.SendMessage(edit,win32con.WM_SETTEXT,0,r'C:\Users\92870\Desktop\Rose introduction.txt') #填写文件路径
win32gui.SendMessage(win1,win32con.WM_COMMAND,1,button)
参照博文:Python win32gui 模块:窗口操作方法代码实例_win32gui.enumwindows-CSDN博客
两大切换
切换到弹出框
#弹出框
##法一:
alert_dialog=driver.switch_to.alert #切换到弹出框
content1=alert_dialog.text #获取弹出框内容
alert_dialog.accept() #确认
alert_dialog.dismiss() #取消
print(content1)##法二
from selenium.webdriver.common.alert import Alert
content2=Alert(driver).text
Alert(driver).accept()
print(content2)
切换窗体
在 selenium 操作页面的时候,可能会因为点击某个链接而跳转到一个新的页面(打开了一个新标签页),这时候 selenium 实际还是处于上一个页面的,需要我们进行切换才能够定位最新页面上的元素。
窗口切换需要使用 switch_to.windows() 方法。
#窗体切换
current_hanler = driver.current_window_handle #保存当前窗口编号
js='window.open("https://www.baidu.com");'
driver.execute_script(js) #新打开窗口
time.sleep(2)
driver.switch_to.window(current_hanler) #切换回保存的窗口handles = driver.window_handles #系统以列表形式存储窗体编号
driver.switch_to.window(handles[0]) #根据索引切换窗体
四、JS操作
滚动条
在进行Web页面自动化测试时,因为只能获取当前页面所显示的标签元素,有时候页面内容会很长,存在元素被挡住的问题。因此,学习滚动条操作有助于更加全面的定位标签元素
# 滚动条
## 直接设置滚动条位置
js='var q=document.body.ScrollTop=10000'
driver.execute_script(js)
## 拖动到可见的元素位置
target = driver.find_element(By.XPATH,'//div[@class="file-input-empty"]/button') #被挡住的元素
time.sleep(1) #等待拖动完成
driver.execute_script("arguments[0].scrollIntoView();", target)
可以提前判断需要定位的元素是否被遮挡了
def is_element_exist(browser,xpath):try:element=browser.find_element(by=By.XPATH,value=xpath)flag=True #未被遮挡,返回trueexcept:flag=False #被遮挡,返回falsereturn flag
若还想深入了解可查看:python+selenium自动化软件测试(第2章):WebDriver API - Web自动化测试 - 博客园
常见问题:
找不到对象
原因 | 解决方法 |
---|---|
反应时间太短,元素未生成 | sleep()、显示等待、隐式等待 |
不在同一iframe层 | 切换层,切换到不同的iframe里面;若存在iframe嵌套关系,需要多次切换 |
元素定位方式设置地不正确 | 检查元素定位方式是否正确,尝试使用不同的定位方式进行定位 |
元素被挡住,不在当前的显示页面上 | 添加滚动条,滚动到对应元素位置 |
学习过程中的问题记录
在 HTML 代码中,虽然看起来<a>
标签内的文本是 " 添加用户"
,开头有一个空格和双引号,但实际上在使用By.LINK_TEXT
定位时,不应该包含这个空格和双引号
空格原因如下:
- 渲染后的实际文本:在浏览器渲染页面时,对于标签内的文本,通常会自动忽略开头和结尾的空白字符,包括空格、换行符等。所以用户实际看到的可见文本是 “添加用户”,而不是 “ 添加用户”。
By.LINK_TEXT
是根据用户在页面上实际看到的可见文本进行定位的,所以不需要包含开头的空格。 - Selenium 定位机制:Selenium 的
By.LINK_TEXT
定位策略是基于页面渲染后的文本内容来查找元素的。它会按照浏览器呈现给用户的文本进行匹配,而不是严格按照 HTML 源代码中的文本格式。如果按照 HTML 源代码中的格式,包含了不必要的空格等空白字符,反而可能导致定位失败。
双引号原因如下:
- 渲染后的实际文本:虽然 HTML 代码中写成
<a> ... ”添加用户“ ... </a>
,但在浏览器渲染页面后,引号(”
)通常不会作为可见文本的一部分显示给用户。浏览器会将其视为普通的 HTML 文本格式标记,而不是要显示的内容。用户在页面上看到的就是 “添加用户” 这四个字,没有引号。 - Selenium 定位机制:Selenium 的
By.LINK_TEXT
定位策略是根据页面上实际可见的文本内容来匹配元素的。它会去查找页面中显示的文本与传入的value
完全一致的<a>
标签元素。所以,为了能准确匹配到目标元素,value
应该是页面上实际显示的 “添加用户”,而不是包含引号的 ““添加用户””。 - 特殊情况处理:如果引号确实是作为可见文本的一部分显示在页面上,那么在使用
By.LINK_TEXT
时,value
就需要包含引号,即'“添加用户”'
。但从常见的网页设计来看,引号一般不会作为链接文本的一部分显示,所以大多数情况下使用'添加用户'
即可。
在 HTML 代码中,虽然看起来 <a>
标签内的文本 “测试” 是写在 <span>
标签里,但实际上在使用 By.LINK_TEXT
定位时,依然可以用 “测试” 来定位 <a>
标签,原因如下:
- 渲染后的实际文本:在浏览器渲染页面时,
<a>
标签作为一个整体的链接元素,其内部包含的所有子元素(如<span>
标签)的文本内容会被整合并显示为该链接的可见文本。<span>
标签通常用于对文本进行样式或语义上的修饰,浏览器会将<span>
内的文本与<a>
标签其他部分的内容(如果有的话)组合成一个完整的可见文本呈现给用户。所以用户实际看到的<a>
标签的可见文本就是 “测试”,By.LINK_TEXT
是根据用户在页面上实际看到的可见文本进行定位的,因此可以直接使用 “测试” 来定位。 - Selenium 定位机制:Selenium 的
By.LINK_TEXT
定位策略是基于页面渲染后的文本内容来查找元素的。它关注的是用户在浏览器中实际能看到的文本信息,而不是 HTML 代码的具体结构。无论文本是直接写在<a>
标签内,还是包含在<a>
标签的子元素(如<span>
)中,只要最终呈现给用户的文本是 “测试”,就可以使用该文本进行定位。如果过于关注 HTML 结构,而不考虑渲染后的实际文本,反而可能导致定位失败。
附录代码(登录禅道--添加用户--删除用户--退出禅道)
import time
from selenium import webdriver
from selenium.webdriver.edge.service import Service #使用浏览器驱动的方法
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
import unittestclass TestCases(unittest.TestCase):def __init__(self):# selenium4.0e = Service(executable_path=r'D:\WebDriver\MicrosoftWebDriver.exe') # 写入之前解压保存的路径self.driver = webdriver.Edge(service=e)self.driver.maximize_window() # 窗口最大化self.driver.get("http://127.0.0.1:81/zentao/user-login.html") # 访问禅道登录界面def login_case(self):#登录禅道self.driver.find_element(By.ID,'account').send_keys('admin') #输入用户名self.driver.find_element(By.NAME,'password').send_keys('password123456')#输入密码self.driver.find_element(By.ID,'submit').click()time.sleep(0.5) #有时界面刷新的慢,元素还未生成,可能导致找不到对应的元素def adduse_users(self):#添加用户self.driver.find_element(By.LINK_TEXT, '后台').click()time.sleep(0.5)#切换层,切换到不同的iframe,switch_to.frame(id/name/index)self.driver.switch_to.frame('appIframe-admin') #切换到对应层self.driver.find_element(By.LINK_TEXT, '人员').click()self.driver.find_element(By.LINK_TEXT,'添加用户').click()time.sleep(0.5)self.driver.find_element(By.NAME,'account').send_keys('tester0011')self.driver.find_element(By.ID,'password1').send_keys('password001')self.driver.find_element(By.ID,'password2').send_keys('password001')self.driver.find_element(By.ID,'realname').send_keys('tester0011')#下拉框的选择 标签名:<select>##导入select模块,选择Select类from selenium.webdriver.support.select import Selectselect_elem=self.driver.find_element(By.ID,'role') #获取下拉框元素Select(select_elem).select_by_visible_text('项目经理') #根据显示的值time.sleep(0.5)#添加滚动条js='var q=document.documentElement.scrollTop=200'self.driver.execute_script(js)self.driver.find_element(By.ID,'verifyPassword').send_keys('password123456')self.driver.find_element(By.ID,'submit').click()time.sleep(0.5)def deluser_case(self):# 搜索并删除用户##搜索self.driver.find_element(By.ID, 'bysearchTab').click()self.driver.find_element(By.ID, 'value1').send_keys('tester0011')self.driver.find_element(By.ID, 'submit').click()time.sleep(0.5)##删除self.driver.find_element(By.CLASS_NAME, 'icon-trash').click()self.driver.switch_to.frame('iframe-triggerModal')self.driver.find_element(By.ID, 'verifyPassword').send_keys('password123456')self.driver.find_element(By.ID, 'submit').click() #def logout_case(self):# 退出禅道self.driver.switch_to.frame('appIframe-my')self.driver.find_element(By.LINK_TEXT, 'A').click()self.driver.find_element(By.LINK_TEXT, '退出').click()time.sleep(10)
相关文章:
基于Python的selenium入门超详细教程(第1章)--WebDriver API篇
学习路线 自动化测试介绍及学习路线-CSDN博客 自动化测试之Web自动化(基于pythonselenium)-CSDN博客 参照博文:selenium入门超详细教程——网页自动化操作-CSDN博客 目录 前言 一、WebDriver API介绍 1.1 什么是WebDriver? 1.2 工…...
IIC通信协议详解与STM32实战指南
IIC通信协议详解与STM32实战指南 引言 IIC(Inter-Integrated Circuit)是Philips公司开发的串行通信协议,广泛应用于传感器、EEPROM、RTC等低速外设的连接。本文深入解析IIC协议原理,并提供基于STM32的GPIO模拟实现方案ÿ…...
【算法】数组、链表、栈、队列、树
⭐️个人主页:小羊 ⭐️所属专栏:Linux 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 持续更新中...数组、链表点击消除环形链表环形链表 II 栈、队列树 持续更新中… 数组、链表 点击消除 AB5 点击消除 这个题很容…...
vscode 配置golang开发环境
vscode 配置golang开发环境 在go1.20环境中需要指定工具的安装版本 go install golang.org/x/tools/goplsv0.15.3 go install github.com/go-delve/delve/cmd/dlvv1.21.0使用go Install/Update tool安装工具会报错 go版本太低, 而很多时候为了项目稳定或风险太高, 我们不太希…...
uniapp APP使用web-view内嵌 h5 解决打包发版浏览器有缓存需要清除的问题
1.在当前项目根节点下的public目录下的index.html里面写入禁止缓存的 meta <!-- 解决前端发版缓存问题 start --><meta http-equiv"pragma" content"no-cache"><meta http-equiv"cache-control" content"no-cache, no-stor…...
机器学习与深度学习中模型训练时常用的四种正则化技术L1,L2,L21,ElasticNet
L1正则化和L2正则化是机器学习中常用的两种正则化方法,用于防止模型过拟合。它们的区别主要体现在数学形式、作用机制和应用效果上。以下是详细对比: 1. 数学定义 L1正则化(也叫Lasso正则化): 在损失函数中加入权重参…...
LLM自动化评测
使用的数据集:ceval-exam import requests from datasets import load_dataset, concatenate_datasets import re from tqdm import tqdm import re, time, tiktoken, ollama from ollama import ChatResponse from ollama import Optionsdef llm(model, query, te…...
Android 英文文章选词
点击文章中的一个单词,获取它。 通过点击的坐标y来获取行数,通过x坐标获取字符偏移量,向前遍历匹配,向后遍历匹配,匹配不成功则跳出循环。截取开始位置和最后位置的字符串。 主要代码 public String getSelectText…...
56.HarmonyOS NEXT 登录模块开发教程(十):总结与展望
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT 登录模块开发教程(十):总结与展望 文章目录 HarmonyOS NEXT 登录模块开发教程(十&a…...
【Go每日一练】猜数字游戏
👻创作者:丶重明 👻创作时间:2025年3月16日 👻擅长领域:运维 目录 1.😶🌫️题目:猜数字游戏2.😶🌫️代码开发3.😶🌫…...
论文分享:PL-ALF框架实现无人机低纹理环境自主飞行
在室内仓库、地下隧道等低纹理复杂场景中,无人机依赖视觉传感器进行自主飞行时,往往会遇到定位精度低、路径规划不稳定等难题。针对这一问题,重庆邮电大学计算机学院雷大江教授团队在IEEE Trans期刊上提出了一种新型自主飞行框架:…...
element-plus中Autocomplete自动补全输入框组件的使用
目录 1.基本使用 ①从官网复制如下代码 ②查看运行效果 ③代码解读 2.调用后端接口,动态获取建议数据 结语 1.基本使用 ①从官网复制如下代码 <template> <div><!-- 自动补全输入框 --><el-autocompletev-model"state":fetc…...
【医学影像 AI】大型语言模型生成 ROP 患者信息材料的能力
【医学影像 AI】大型语言模型生成 ROP 患者信息材料的能力 0. 论文简介0.1 基本信息0.2 摘要 1. 引言2. 材料与方法2.1 大语言模型的使用2.2 可读性标准2.3 统计分析 3. 结果3.1 Bezirci-Yılmaz可读性评分3.2 Ateşman可读性评分3.3 全面性评分3.4 准确性评分 4. 讨论4.1 可读…...
(性能测试)性能测试工具 2.jmeter的环境搭建 3jmeter元件和4使用实例 5jmeter元件和参数化
目录 性能测试工具 性能测试工具 jemeter环境搭建 jmeter的常用目录介绍 jmeter修改语言和主题--jmeter界面的汉化 jmeter元件 jmeter元件和组件的介绍 jmeter的作用域原则 jmeter的执行顺序 案例:执行顺序 jmeter使用案例 jmeter线程组的介绍 jmeter…...
Matlab 四分之一车体车辆半主动悬架鲁棒控制
1、内容简介 略 Matlab 173-四分之一车体车辆半主动悬架鲁棒控制 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...
Kafka可视化工具KafkaTool工具的使用
Kafka Tool工具 介绍 使用Kafka的小伙伴,有没有为无法直观地查看 Kafka 的 Topic 里的内容而发过愁呢?下面推荐给大家一款带有可视化页面的Kafka工具:Kafka Tool (目前最新版本是 3.0.2) 注意:以前叫Kafk…...
【Unity】在项目中使用VisualScripting
1. 在packagemanager添加插件 2. 在设置中进行初始化。 Edit > Project Settings > Visual Scripting Initialize Visual Scripting You must select Initialize Visual Scripting the first time you use Visual Scripting in a project. Initialize Visual Scripting …...
【Maven教程与实战案例】
文章目录 前言一、Maven是什么?二、Maven的安装与配置1. 安装前置条件2. 下载与配置 Maven3. 验证安装 三、Maven的核心概念1. POM.xml 文件2. 构建生命周期与插件机制 四、实战项目示例1. 项目目录结构2. 编写代码App.javaAppTest.java 3. 构建项目4. 运行项目 前言…...
Flask中使用with语句手动加载应用上下文
在 Flask 中,with app.app_context(): 手动加载应用上下文,使代码块可以访问 Flask 全局对象(如 current_app、g),即使代码不在请求中运行。 1. 为什么需要手动加载应用上下文? 在 Flask 中,某…...
ROS实践(五)机器人自动导航(robot_navigation)
目录 一、知识点 1. 定位 2. 路径规划 (1)全局路径规划 (2)局部路径规划 3. 避障 二、常用工具和传感器 三、相关功能包 1. move_base(决策规划) 2. amcl(定位) 3. costmap_2d(代价地图) 4. global_planner(全局规划器) 5. local_planner(局部规划器…...
【数学建模】层次分析法(AHP)详解及其应用
层次分析法(AHP)详解及其应用 引言 在现实生活和工作中,我们经常面临复杂的决策问题,这些问题通常涉及多个评价准则,且各准则之间可能存在相互影响。如何在这些复杂因素中做出合理的决策?层次分析法(Analytic Hierarchy Process…...
【大模型】Transformer、GPT1、GPT2、GPT3、BERT 的论文解析
前言 在自然语言处理(NLP)和深度学习的快速发展中,Transformer模型和 GPT系列模型扮演了至关重要的角色。本篇博客旨在对这些开创性的论文进行介绍,涵盖它们的提出时间、网络结构等关键信息,能够快速的理解这些模型的设…...
Android 手机启动过程
梳理 为了梳理思路,笔者画了一幅关于 Android 手机启动的过程图片内容纯属个人见解,如有错误,欢迎各位指正...
【redis】hash基本命令和内部编码
文章目录 表示形式命令HSET 和 HGET HEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSETNXHINCRBYHINCRBYFLOAT命令小结内部编码 表示形式 Redis 自身已经是键值对结构了 Redis 自身的键值对就是通过哈希的方式来组织的 把 key 这一层组织完成之后,到了 value 这一层&…...
统计数字字符个数(信息学奥赛一本通-1129)
【题目描述】 输入一行字符,统计出其中数字字符的个数。 【输入】 一行字符串,总长度不超过255。 【输出】 输出为1行,输出字符串里面数字字符的个数。 【输入样例】 Peking University is set up at 1898. 【输出样例】 4 【输出样例】 #in…...
基于javaweb的SSM+Maven网上选课管理系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
算法及数据结构系列 - BFS算法
文章目录 框架思路经典题型111. 二叉树的最小深度752. 打开转盘锁 框架思路 BFS 的核心思想应该不难理解的,就是把一些问题抽象成图,从一个点开始,向四周开始扩散。一般来说,我们写 BFS 算法都是用队列这种数据结构,每…...
深入剖析 MetaSpace OOM 问题:根因分析与高效解决策略
目录 一、MetaSpace 区 OOM:概述 (一) MetaSpace的变革与挑战 (二)MetaSpace OOM的影响 (三) 为什么要关注MetaSpace OOM 二、MetaSpace 区 OOM的根本原因 (一)Met…...
java自带日志系统介绍(JUL)以及和Log4j 2、Logback、SLF4J不同日志工具的对比
Java 日志系统是开发中用于记录应用程序运行时信息的重要工具。以下是 Java 日志系统的核心组件及其使用场景、配置参数的详细介绍,以及不同日志系统的对比分析。 Java 日志系统核心组件 1. 日志记录器(Logger) 作用:负责生成日…...
Kubernetes 中metrics-server的采集周期,采集链路是什么样的?
0. 运维干货分享 软考高级系统架构设计师备考学习资料软考高级网络规划设计师备考学习资料Kubernetes CKA认证学习资料分享信息安全管理体系(ISMS)制度模板分享免费文档翻译工具(支持word、pdf、ppt、excel)PuTTY中文版安装包MobaXterm中文版安装包ping…...
一分钟了解深度学习
一分钟了解深度学习 A Minute to Know About Deep Learning By JacksonML 1. 什么是深度学习? 深度学习(Deep Learning) 是机器学习的一个子集,都属于人工智能的范畴;它使用多层神经网络(称为深度神经网络)来模拟人…...
Git LFS (Large File Storage) 简介
目录 Git LFS (Large File Storage) 简介 1. 什么是 Git LFS? 2. 为什么需要 Git LFS? 3. Git LFS 的工作原理 4. 如何使用 Git LFS? 4.1 安装 Git LFS 4.2 配置 Git LFS 5. Git LFS 的优缺点 优点 缺点 6. 适用场景 7. 结论 1. …...
前端权限系统
前端权限系统是为了确保用户只能访问他们有权限查看的资源而设计的。在现代前端开发中,权限控制不仅仅是简单的显示或隐藏元素,还涉及到对路由、组件、数据和操作权限的细致控制。下面是前端权限系统的常见设计方案和实现步骤。 前端权限系统的组成部分 …...
【蓝桥杯速成】| 4.递归
递归 题目一:最大公约数 问题描述 1979. 找出数组的最大公约数 - 力扣(LeetCode) 给你一个整数数组 nums ,返回数组中最大数和最小数的 最大公约数 。 两个数的 最大公约数 是能够被两个数整除的最大正整数。 解题步骤 需要…...
QEMU源码全解析 —— 块设备虚拟化(4)
接前一篇文章:QEMU源码全解析 —— 块设备虚拟化(3) 本文内容参考: 《趣谈Linux操作系统》 —— 刘超,极客时间 《QEMU/KVM源码解析与应用》 —— 李强,机械工业出版社 类模板是创建类的模式_创建类是的模版-CSDN博客<...
92.HarmonyOS NEXT开发学习路径与最佳实践总结:构建高质量应用
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT开发学习路径与最佳实践总结:构建高质量应用 文章目录 HarmonyOS NEXT开发学习路径与最佳实践总结:构建高质…...
【004】deepseek本地化部署后,python的调用方式_#py
python调用本地deepseek 1 本地化部署deepseek2 python调用方式 1 本地化部署deepseek 已经有很多大佬们说了不少部署本地化部署deepseek的工作了,我就不过多重复了。 先安装Ollama软件,再通过Ollama获取deepseek的模型文件,大家根据电脑的配…...
基于Python+Flask+MySQL+HTML的爬取豆瓣电影top-250数据并进行可视化的数据可视化平台
FlaskMySQLHTML 项目采用前后端分离技术,包含完整的前端,以flask作为后端 Pyecharts、jieba进行前端图表展示 通过MySQL收集格列数据 通过Pyecharts制作数据图表 这是博主b站发布的详细讲解,感兴趣的可以去观看:【Python爬虫可…...
【Prometheus01】可观测性系统之Prometheus简介、优缺点对比、组件介绍、数据采集流程、TSDB简介
监控工具对比、黑盒监控与盒白盒监控、Kubernetes监控简介 监控简介: 监控的价值: 长期趋势分析:通过对监控样本数据的持续收集和统计,对监控指标进行长期趋势分析。例如,通过对磁盘空间增长率的判断,我们…...
Postman下载安装及简单入门
一.Postman简介 Postman是一款API测试工具,可以帮助开发、测试人员发送HTTP请求,与各种API进行交互,并分析响应 二.下载与安装 访问Postman官网(https://www.postman.com/),下载适…...
记第一次跟踪seatunnel的任务运行过程三——解析配置的具体方法getLogicalDag
前绪 记第一次跟踪seatunnel的任务运行过程二——ClientJobExecutionEnvironment的execture方法 从这里开始,就是使用seatunnel-2.3.9的源码了。前面部分没有变化,2.3.X版本都是通用的。 建议打开源码,边读文章,边阅读源码 正文…...
Maven 的核心包
由于前端项目不是核心,阅读 nexus-public 源代码似乎绕远路了。nexus-oss 社区版主要就是集成 maven 的上传包、认证、包解析、包存储这几个核心功能,前端实现重新可以使用新的现代前端工具来提高生产力。故重新疏理一下 maven 的核心机制,即…...
上位机数据可视化:使用QtCharts绘制波形图
工程配置 CMake文件 find_package(Qt5 COMPONENTS Charts REQUIRED)target_link_libraries(zhd-desktop PRIVATE Qt5::Charts)包含头文件以及名称空间(这个很重要,没有包含名称空间编译器会提示找不到相关的类型) #include <QtCharts&g…...
制造业数字化转型,汽车装备制造企业数字化转型案例,智能制造数字化传统制造业数字化制造业数字化转型案例
《某制造业企业信息化整体解决方案》PPT展示了一个汽车装备企业的整体信息化解决方案,阐述了该企业的业务特点和现状,主要包括按订单生产、多级计划和产品跟踪等,分析了信息化建设的主要困难,如信息管理手工化、过程数据追溯困难、…...
网络安全常识科普(百问百答)
汪乙己一到店,所有喝酒的人便都看着他笑,有的叫道,“汪乙己,你又监控员工隐私了!”他不回答,对柜里说,“来两个fofa。”便排出三个比特币。他们又故意的高声嚷道,“你一定又在电报群…...
P2512糖果传递 P4447分组 P1080国王游戏 P4053建筑抢修
P2512 [HAOI2008] 糖果传递 题目描述 有 n n n 个小朋友坐成一圈,每人有 a i a_i ai 个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为 1 1 1。 输入格式 小朋友个数 n n n,下面 n n n 行 a i a_i ai。 输出格式 求使所…...
SpringMVC(七)数据校验+VO++脱敏
目录 一 基础原理 1 先将数据校验的依赖导入 2 在JavaBean中编写校验注解 3 使用Valid告诉SpringMVC进行校验(校验不通过,方法通知执行) 4 在Valid参数后面加上一个BindingResult参数,获取校验结果。 二 改进方案 1 没写全…...
使用OpenResty(基于Nginx和Lua)优化Web服务性能
引言 1.1 OpenResty简介 OpenResty 是一个基于 Nginx 和 Lua 的高性能 Web 应用平台。它通过将 Lua 脚本嵌入到 Nginx 中,提供了强大的动态处理能力,适用于构建高性能的 Web 服务、API 网关、动态内容生成等场景。 1.2 Nginx与Lua结合的优势 高性能:Nginx 本身就是一个高…...
32、构造函数
1、用构造函数反复创建多个相同结果的对象 问题 如果想反复创建多个相同结构,但是内容不同的对象时,用{}创建会代码重复,及其不便于维护! 解决 今后只要想反复创建同一类型的多个相同结构不同内容的对象时,都用构造函…...
蓝桥与力扣刷题(蓝桥 星期计算)
题目:已知今天是星期六,请问 20^22 天后是星期几? 注意用数字 1 到 7 表示星期一到星期日。 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 解题思路+代码: 代码࿱…...