软件测试——自动化测试常见函数

在上一篇文章软件测试——自动化测试概念篇-CSDN博客中,给大家演示了一下自动化程序,而本篇文章会带大家详细学习selenium库。

selenium库是python官方的库,里面包含了很多操控浏览器的函数。

本节重点

  • 元素定位
  • 操作测试对象
  • 窗口
  • 等待
  • 导航
  • 弹窗
  • 文件上传
  • 浏览器参数

0.自动化程序

上篇文章中的自动化程序代码如下:

#编写自动化脚本,具体步骤
import time
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.microsoft import EdgeChromiumDriverManager

# #1.打开浏览器---驱动管理
#下载和安装Edge浏览器对应的驱动
EdgeIns=EdgeChromiumDriverManager().install()
#创建浏览器驱动对象,打开浏览器
driver=webdriver.Edge(service=Service(EdgeIns))
time.sleep(2)
#2.输入百度网址:https://www.baidu.com(网址一定要写完整,不要写成www.baidu.com)
driver.get("https://www.baidu.com")
time.sleep(2)
#3.找到百度输入框,输入关键词“迪丽热巴”
driver.find_element(By.CSS_SELECTOR, "#kw").send_keys("迪丽热巴")
time.sleep(2)
#4.点击“百度一下”
driver.find_element(By.CSS_SELECTOR, "#su").click()
time.sleep(2)
#5.关闭浏览器
driver.quit()

1.元素定位

首先,我们要了解在一个web网页中包含很多的元素(以edge浏览器做演示)

我们可以点击键盘上的F12或者按shift+ctrl+i进入开发者工具,如下图所示(如果第一次打开不是这样的,就点击右上角的元素按钮)

然后我们需要点击开发者模式左上角的小箭头,让他变成黄色。

当打开这个后,我们鼠标放在左边的百度界面时,对应的区域就会变成蓝色,此时这个小区域就称之为元素。

对应web自动化测试的操作核心是能够找到页面的元素,然后才能对元素进行具体的操作。常见的元素定位方式非常多,如id,classname,tagname,xpath,cssSelector。常用的主要有cssSelector和xpath。

比如上一篇文章中,我们写的web自动化程序会在百度的输入框内输入“迪丽热巴”,就是因为能成功定位到输入框元素;能自动点击“百度一下”,也是因为可以定位到对应的元素。

代码中的#kw和#se分别代表的是输入框和“百度一下”按钮。

怎么证明呢?

点击百度的输入框后,开发者工具会自动跳转到其对应的代码。

然后鼠标右击黄色代码部分,点击复制,然后选择复制方式,这里选择复制selector。

而复制的内容就是:#kw,也就是搜索框对应的选择器定位方式,我们再回过头来看这个代码就很好理解了,后面的send_keys的意思就是输入文本,即“迪丽热巴”。

而“百度一下”按钮也是同理,click的意思是点击按钮。

1.1 cssSelector

cssSelector是一个选择器,选择器的功能:选中页面中指定的标签元素

选择器的种类分为基础选择器和复合选择器,常见的元素定位方式可以通过id选择器和子类选择器来进行定位。

在前面也介绍过了,可以通过cssSelector选择器来定位页面元素,我们使用的函数是find_element,而selenium库中还有一个find_elements函数,这个函数和find_element的区别在于他可以查找多个元素。

假如我们使用ctrl+f查找红框内的让元素,可以发现最终在整个页面中查找到了10个。

使用find_element只能查找其中一个,而使用find_elements则可以全部查找。

我们在最后打印以下查找的每个元素的文本信息,可以发现他可以对应到百度页面中的文本

而在这十条文本中,我们随便打开一条看一下他的元素定位,步骤还是和前面一样,选中文本,然后跳转到对应代码,鼠标右键选择复制,然后复制到selector。

  • 最终复制出来的就是:#hotsearch-content-wrapper > li:nth-child(1) > a。
  • 而我们刚刚搜索的是:#hotsearch-content-wrapper > li。

所以使用find_elements函数可以帮我们找到多个元素。

实际上刚刚的那十个文本处于同一个列表中,在前端中ul表示列表,而li标签表示的是列表中的每一个内容。

我们可以发现在第一行ul标签中有一个id="hostsearch-content-wrapper",其中的id表示他是一个id选择器,再来看我们刚刚查找的其中一个的元素定位:#hotsearch-content-wrapper > li:nth-child(1) > a。其中的li:表示的是子类选择器,他要找的是第一个li标签。

1.2 xpath

XML路径语言,不仅可以在XML文件中查找信息,还可以在HTML中选取节点。xpath使用路径表达式来选择xml文档中的节点。

在xpath语法中:

  • 1.获取HTML页面所有的节点: //*   
  • 2.获取HTML页面指定结点://[指定结点]   (如://ul表示获取HTML页面所有的ul节点)
  • 3.获取一个结点中的子节点:/   (如://span/input表示input是span的子节点)
  • 4.获取一个结点的父结点:..   (如://input/...表示获取input结点的父结点)
  • 5.实现结点属性的匹配:[@.....]   (如://*[@id='kw']表示匹配HTML页面中id属性为kw的结点)
  • 6.使用索引的方式获取对应内容,索引从1开始。   (如百度首页://div/ul/li[3]表示定位到第三个百度热搜标签)

我们再以百度的输入框为例,选择复制方式为复制XPath。

百度输入框Xpath元素信息为://*[@id="kw"]

  • 其中的//*表示获取HTML页面所有的结点
  • [@id="kw"]表示获取id属性为kw的结点

“百度一下”按钮的id属性为su,能否通过//*[@id='su']找到“百度一下”呢?

我们打开开发者工具,使用ctrl+f进行搜索,输入//*[@id='su']。

按下回车后,可以发现,左边的“百度一下”按钮变成蓝色了,说明我们的搜索成功找到了。

通过这种方式,我们可以查找到页面中的所有元素。

如何理解//*[@id="hotsearch-content-wrapper"]/li[1]/a/span[2]这个xpath

这个xpath其实是前面提到过的li标签,在cssSelector中我们说他是一个子类选择器。

那么在xpath中如何理解他的元素信息://*[@id="hotsearch-content-wrapper"]/li[1]/a/span[2]

其中//*[@id="hotsearch-content-wrapper"]表示的是ul标签。

2.操作测试对象

获取到了页面的元素之后,接下来就是要对元素进行操作了。常见的操作有点击、提交、输入、清除、获取文本。


2.1 点击/提交对象

click()

我们在前一篇文章中写过的自动化程序中就有click函数,如下:

其中先找到百度的输入框然后输入"迪丽热巴",然后再找到"百度一下"按钮,并点击该对象成功查找目标信息。

这里的逻辑非常简单,我们找到"百度一下"按钮,并点击该对象的代码写成了一行,也可以写成两步,先查找再点击。

最终的效果是一样的。

点击是模拟鼠标的动作,也就是说页面中的任何一个元素都可以点击。

比如说我们现在要点击该新闻链接:

我们通过cssSelecor的方式查找该条新闻,代码如下:

运行程序,在打开百度页面的2秒后,果然跳转到了对应的链接中

所以说click的功能是非常强大的。

2.2 模拟按键输入

send_keys("")

还是以前面写的自动化程序为例,我们找到了百度的输入框,并调用了send_keys在该输入框内输入了文本。

同样的,这一行代码也可以写成两行,先查找输入框再输入文本。

输入是模拟键盘的动作,也就是说键盘可以输入的内容都可以填写上去。​​​​​​

比如键盘输入以下内容:

最终可以成功搜索

2.3 清楚文本信息

连续的send_keys会将多次输入的内容拼接在一起,要想重新输入,需要使用clear()

比如说我们想搜索"Linux"和"Python"这两个内容,如果按照下面的这种写法,那么第二次搜索的不是Python而是LinuxPython,第二次的内容直接拼接到第一次。

要想解决这个办法,就要在搜索玩之后使用clear进行清除。

运行后,首先会输入Linux

过了2秒后,会清除文本。

又过了2秒后,输入Python。

2.4 获取文本信息

如果判断获取到的元素对应的文本是否符合预期呢?获取元素对应的文本并打印一下。

获取文本信息: text,会返回一个字符串

就以下面的例子为例,我们想获得该新闻的文本信息。

代码如下:

运行后:

成功获取到了文本。

为什么我们肉眼能观察到文本是否有问题,还需要通过代码来判断呢?

别忘了我们介绍的内容是什么:自动化,自动化的目的就是为了代替人的工作,实际工作中,我们可以通过断言的方式判断目标文本和实际读到的文本是否一样,如果不一样就会出现错误。

比如我们输入的时候少了一个汉字“费”

最终可以通过断言找出来

如何获得“百度一下”按钮的文本信息?

我们还是按之前的步骤来试一下,编写如下代码:

但是最终运行的结果却是报错,并且我们的print也没有打印出任何信息。

这就说明了text为空,没有返回任何文本信息。

我们要了解一个概念:元素属性值 != 文本信息

这里的"百度一下"其实是元素的属性值,有属性值肯定就有属性。

那么到底什么是属性和属性值呢,我们再来查看“百度一下”按钮对应的代码,其中有type,id,vale和class这些就是该元素对应的属性,等号后面的就是属性值(key-value形式的键值对)

所以我们想获取“百度一下”就不能通过获取文本的方式了,需要通过获取属性值。

get_attribute(属性)

使用get_attribute()函数就能获取对应属性的属性值。

最终运行没有报错,并且成功打印了“百度一下”。

如何区分属性值和文本

  • 文本是直接写在标签内部的,如上图的<span>和</span>中间。
  • 属性值以键值对的方式,如上图vale=“百度一下”。

2.5 获取当前页面标题

页面的标题就在页面的左上角,如百度的标题就是“百度一下,你就知道”

通过title = driver.title获取

 title = driver.title

代码如下:

成功获取页面标题

2.6 获取当前页面URL

和获取页面标题的使用方法几乎是一样的,使用url = driver.current_url

url = driver.current_url

代码如下:

运行结果:

获取页面标题和获取页面的url的使用场景

页面元素可点击跳转的情况下,用来检测跳转的结果是否是正确的。

比如说,我想点击视频,我不知道点击后能否成功跳转到目标地址。

那么就可以获取点击后的url和标题与目标地址和标题进行对比,如果是一致的说明跳转就是正确的。

3.窗口

在讲解窗口之前,我们先来做一个练习,点击百度首页的图片,跳转到目标页面

代码如下:

运行结果:

最终能跳转到新的页面,并且跳转后的页面的url和原url是不一样的,但是打印的结果为什么还是和页面跳转之前的结果一样。

我们查找一个新页面中有的元素,但旧页面没有的来观察一下,以查找“热门搜索”为例

代码:

运行结果:

可以看到报错了,并且报错信息是:NoSuchElementException: Message: no such element: Unable to locate element,说明我们要查找的元素不存在。

也就是说虽然显示跳转到了新页面,但是我们的驱动对象driver还停留在旧的页面中

我们一开始创建的驱动对象在https://baidu.com这个标签页中,但是当跳转到新页面时,会出现多个标签页,而我们的driver还是指向的第一个标签页。

打开⼀个新的页面之后获取到的title和URL仍然还是前一个页面的?

当我们手工测试的时候,我们可以通过眼睛来判断当前的窗口是什么,但对于程序来说它是不知道当前最新的窗口应该是哪⼀个。对于程序来说它怎么来识别每⼀个窗口呢?每个浏览器窗口都有⼀个唯一的属性句柄(handle)来表示,我们就可以通过句柄来切换不同的窗口。

3.1 切换窗口

1)获取当前页面句柄:

driver.current_window_handle

3)获取所有页面句柄:

driver.window_handles

3)切换当前句柄为最新页面:

curWindow = driver.current_window_handle
allWindows = driver.window_handles

for window in allWindows:
    if window != curWindow:
        driver.switch_to.window(window)

注意:执行了 driver.close() 之前需要切换到未被关闭的窗口

也就是说遍历所有的句柄,如果发现不是当前页的句柄就切换,这样就能保证可以切换成最新页的句柄了。

我们更新一下代码。

运行结果:

成功显示了新窗口的地址,并且find_element也查找成功。

如果有多个标签页怎么切换

我们切换标签页时的代码如下:

curWindow = driver.current_window_handle
allWindows = driver.window_handles

for window in allWindows:
    if window != curWindow:
        driver.switch_to.window(window)

如果我们打开了3个标签页,这种方法就没法很好定位到第二个标签页或者是第三个标签页了。

  • 实际上打开多个标签页的情况不常见,通常情况下只会打开两个标签页,实现标签页的切换测试
  • 更多的情况下,我们可以直接输入对应页面的url在当前标签下进行测试。(直接将当前页面切换成目标页面通过driver.get()实现)

例如在百度首页搜索图片页面,则直接输入目标url

搜索后不会出现新的窗口

需要切换窗口的前提是:页面跳转产生了新的标签页

我们来看下面这种场景

我们点击百度首页的“文库”

然后就能看到该页面,注意此时页面的标题和url

我们再点击左边的智能助手

可以看到页面发生了跳转,但是没有产生新的标签页,新页面直接覆盖掉了原页面,我们通过编写代码来测试一下。

运行结果:

在页面切换后,我们没有切换窗口,而是直接测试跳转结果,结果表明跳转成功,并且find_element也查找成功。

总结:页面跳转产生了新的标签页时才需要进行窗口切换

3.2 窗口设置大小

1)窗口最大化

driver.maximize_window()

2)窗口最小化

driver.minimize_window()

3)窗口全屏

driver.fullscreen_window()

4)手动设置窗口大小

driver.set_window_size(1024,768)


我们在使用浏览器时,经常会用到窗口最大化以及窗口最小化,这个按钮通常在浏览器右上角位置。窗口全屏可以按F11进入。

接下来我们通过代码的方式来实现上面功能。

运行代码后

第一个2秒会运行窗口最大化

第二个2秒会进入最小化,但是我们无法观察到

第三个2秒会进入全屏

第四个2秒会进入手动设置的大小

3.3 屏幕截图

我们的自动化脚本⼀般部署在机器上自动的去运行,如果出现了报错,仅仅通过终端的错误提示给到的有用信息是一定的,可以通过抓拍来记录当时的错误场景,能更好的定位问题并解决问题

driver.save_screenshot('图片名称')

save_screenshot的参数是屏幕截屏保存下来的图片名称(路径+名字)

  • 比如('test.png')表示:保存在脚本文件所在路径下,图片名称为test.png
  • ('C:/images/image.png')表示:保存在C盘的images目录下,图片名称为image.png

我们在运行下列代码后

可以看到项目中多了一个文件

该文件就是我们刚刚打开的百度首页

如果我们不想创建在当前路径下,我们可以创建一个文件夹images,然后将所有的截屏保存在该文件夹中。

sava_screenshot的参数就可以修改成指定路径。

最终也是成功显示出来了


指定文件名后,多次截屏会覆盖掉旧图,如何保证每次生成的都是唯一的

当我们指定好了文件名为test.png后,第一次截图没有问题,但是在后面的截图中,会覆盖掉上一次的图,所以我们需要修改一下代码使每次生成的图片名字都不一样。

最好的名称是以当前时间来命名,这样每个名称都不一样,并且还能帮助我们定位错误的时间,去查看对应的错误日志。

python中有一个datetime.now()函数可以打印当前的时间,但是这个函数打印出来的结果中包含空格,而文件名中是不能有空格的。

所以我们让他以指定形式打印。

再给文件名添加一下前缀和后缀。

最终代码如下:

此时我们运行三次程序,就会生成3个不同名称的图片。

3.4 关闭窗口

  • driver.close()表示:退出一个窗口
  • driver.quit()表示:退出浏览器,会关闭所有的标签页

注意:driver.close()退出的是driver指向的标签页。

比如下面代码:

代码的逻辑就是,打开百度首页面,点击"图片"跳转到新的标签页并切换句柄,然后退出当前窗口,最后退出整个浏览器。

在退出窗口后

如果在代码中没有切换句柄,那么关闭的就是百度首页面了。

4.弹窗

弹窗我们并不模式,比如当我们在网页中登陆时,会出现一个弹窗

此时弹窗中的元素都是可以定位到的。

我们今天要学的弹窗是在页面中找不到任何元素的,这种情况如何处理。

假如说有当前这个页面,点击左边的See_an_example_alert后会出现一个弹窗

我们页面右上角的小箭头打开后,可以定位左边的元素

但是当出现弹窗后,我们将鼠标放在弹窗位置,此时无法定位到左边的元素了。

既然无法定位到弹窗,我们就无法通过代码去关闭他。

我们将上面问题写成代码,如下:

启动程序后,出现如下页面:

也就是说运行到find_element时会出现一个弹窗,如果此时我们不去管他,再次点击See_an_example_alert会发生什么

最后出现了报错,错误原因是UnexpectedAlertPresentException,表示未期望的弹窗出现了。

如果我们不解决这个弹窗,我们就不能定位其他元素。

具体步骤:

  • 1.切换到弹窗
  • 2.关闭弹窗(点击确认/取消)

不同的弹窗类型,具体的操作方法不同,但是他们都有共同特点:

  • 1.页面上定位不到弹窗元素
  • 2.出现了弹窗后,页面其他元素都无法定位了

4.1 警告弹窗

  • 警告弹窗中只有一个确认按钮
//切换到弹窗(返回一个弹窗对象)
alert = driver.switchTo.alert
//确认
alert.accept()
//取消
alert.dismiss()

注意:

  • 对于警告弹窗,accept()和dismiss()都可以使用,这两个函数都是作用在同一个按钮上的

下面我们编写代码,将上面的弹窗关闭。

程序运行后,会出现一个警告弹窗,但是2秒过后就会关闭该弹窗。

我们将accept()切换成dismiss(),最终的结果一模一样,验证了警告弹窗中accept()和dismiss()作用于同一个按钮的结论。

4.2 确认弹窗

确认弹窗和警告弹窗比较像。

  • 确认弹窗中包含一个确认键和一个取消键
//切换到弹窗(返回一个弹窗对象)
alert = driver.switchTo.alert
//确认
alert.accept()
//取消
alert.dismiss()

注意:

  • 对于确认弹窗,accept()作用于确认键,dismiss()作用于取消键

假设现在有这样一个页面,点击"Display a confirm box"就会出现一个确认弹窗

点击“确定”会显示“You pressed OK!”

点击“取消”会显示“You pressed Cancel!”

现在我们编写代码,分别使用accept()和dismiss()观察现象:

运行程序:

调用accept()时,指向了“确定”按钮,最终显示出了“You pressed OK!”

现在我们修改一下代码,改成dismiss()

运行程序:

结果和我们预期的一模一样。

总结:

  • 警告弹窗只包含一个确认键,而确认弹窗包含一个确认键一个取消键
  • 对于警告弹窗,accept()和dismiss()作用在同一个按钮(确认键)
  • 对于确认弹窗,accept()和dismiss()作用在不同按钮上(accept()作用于确认键,dismiss()作用于取消键)

4.3 提示弹窗

提示弹窗比确认弹窗多了一个文本框。

#切换弹窗(返回一个弹窗对象)
alert = driver.switchTo.alert
#向文本框中输入文本
alert.send_keys("hello")
#确认
alert.accept()
#取消
alert.dismiss()

注意:

  • send_keys()用于向提示弹窗中的文本框输入内容
  • accept()用于点击提示弹窗中的“确定”键
  • dismiss()用于点击提示弹窗中的“取消”键

现在有这样一个网页,点击左边的“请点击”按钮后,就会出现一个提示弹窗。

当向文本框输入内容并点击确定时,就会将输入的内容显示出来。

而点击取消,或者文本框为空时点击确认都会直接关闭提示弹窗。

现在我们编写代码来测试一下

先测试输入文本+确认

运行结果:

再测试一下输入文本+取消

两次的运行结果都是符合预期的。

5. 等待

通常代码执行的速度比页面渲染的速度要快,可能会出现因为渲染过慢出现的自动化误报问题。

例如,我们前面写过这样的代码:

如果我们在第四步之后添加一个查找新页面中的某个元素的代码,就以搜索“早年经历”为例。

代码如下:

运行程序后:

直接报了下面这个错误,这个错误我们在前面也遇到过,他的意思是没找到对应的资源。

我们在这个代码之前添加一个sleep函数再次测试。

运行程序:

此时程序正常退出。

  • 之所以出现上面的原因,就是因为代码的速度非常快,而页面需要加载的资源较多,因此当脚本执行到该代码处时页面还没有渲染完成,因此无法找到该元素。
  • 当添加了time sleep(3)之后,页面已经在3秒内加载完成,此时就可以找到该元素了。

5.1 强制等待

强制等待就是我们上面使用的方法:

#单位为秒
time.sleep()
  • 优点:使用简单,调试的时候比较有效
  • 缺点:影响运行效率,浪费大量的时间

当测试脚本数量较少时,添加强制等待消耗的时间较少,但是实际工作中的业务复杂,添加的自动化脚本非常多,则会浪费大量时间。

强制等待大多数情况下只适用于测试脚本时,当测试完毕之后会更换为隐式等待或者显示等待。

5.2 隐式等待

隐式等待是一种智能等待,他可以规定在查找元素时,在指定时间内不断查找元素。如果找到则代码继续执行,直到超时没找到元素才会报错。

#参数为秒
implicitly_wait()

我们将time.sleep()修改成implicitly_wait()

运行代码,可正常执行。

为什么implicitly_wait()放到了创建driver对象之后,而不是步骤5之前?

首先,我们要了解一些隐式转换的生命周期。

隐式等待作用域是整个脚本的所有元素。即只要driver对象没有被释放掉( driver.quit() ),隐式等待就⼀直生效。

也就是说只要有implicitly_wait()的代码,后面的所有查找都会等待指定秒数,如果指定秒数内能等到则继续执行代码,等不到才会报错

  • 优点:智能等待,作用于全局

5.3 显示等待

显示等待也是一种智能等待,在指定超时时间范围内只要满足操作的条件就会继续执行后续代码

WebDriverWait(driver,sec).until(functions)
  • driver:浏览器驱动对象
  • sec:需要等待的秒数
  • functions:涉及到selenium.support.ui.ExpectedConditions包下的ExpectedConditions类

示例:

from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver,2)
wait.until(EC.invisibility_of_element((By.XPATH,'//[@id="2"]/div/div/div[3]/div[1]/div[1]/div')))

其中的invisibility_of_element(locator)函数用于检查元素的不可见性,同样也可以使用visibility_of_element(locator)来检查元素的可见性。

接下来我们将自动化程序的代码修改成显示等待

使用显示等待时,我们就不需要再调用find_element()了,直接使用visibility_of_element()来帮我们查找即可。

ExpectedConditions 预定义方法的一些示例:

  • 优点:显示等待是智能等待,可以自定义显示等待的条件,操作灵活,相较于隐式等待速度快(隐式等待中每一个查找元素都会等待)
  • 缺点:写法复杂

比如我们在前面说过三类弹窗,而弹窗不是页面中的元素,所以隐式等待无法等待弹窗,那么需要等待弹窗的场景下,我们就需要使用显示等待。

注意:隐式等待和显示等待不建议一起使用

我们来看下面这个代码,隐式等待和显示等待一起使用,记录起始时间,然后去页面中查找一个不存在的元素,既然不存在查找就会抛异常,所以我们将该异常捕获,并记录抛异常的时间,两个时间之差就是本次等待的时间。

隐式等待了15秒,显示等待15秒,那么最终等待多少秒?

运行程序:

最终等待的时间既不是显示等待也不是隐式等待,也不是两者之和。

总结:不要混合隐式和显式等待,可能会导致不可预测的等待时间。

强制等待可以任意配合隐式等待或者显示等待。

6. 浏览器导航

浏览器导航就是浏览器左上角的部分,包括后退,前进,刷新,跳转页面等功能。

6.1 跳转页面

driver.get("https://tool.lu/")

这个代码我们前面用到过很多次,就是使用浏览器上面的搜索框进行搜索。

我们现在再来重新理解上面的代码,第一句就是下载并安装Edge浏览器对应的驱动,第二句是打开浏览器,此时浏览器中不包含任何内容。

第三句就是通过上面的搜索框搜索对应的url。

6.2 浏览器的前进、后退、刷新

#后退
driver.back()
#前进
driver.forward()
#刷新
driver.refresh()

我们来编写如下代码进行测试

运行结果:

1)打开迪丽热巴页面

2)后退到百度首页

3)前进到迪丽热巴页面

4)刷新页面

7. 文件上传

点击文件上传的场景下会弹窗系统窗口,进行文件的选择。

点击“选择文件”按钮后,会跳出一个window下的界面

selenium无法识别非web的控件,上传文件窗口为系统自带,无法识别窗口元素。

但是可以使用send_keys来上传指定路径的文件,达到的效果是一样的,因为在选择文件页面时,会将选中文件的路径保存起来,当点击“上传”按钮时,文件才会被真正的上传,也就是说选择文件选的是文件的路径

那么我们只要将文件的路径上传上去,就能达到一样的效果。

运行程序后成功找到对应文件。


8. 浏览器参数设置

在写自动化程序中,我们会使用webdriver.Edge函数,该函数中我们只设置了service这一个选项,这个选项的意思是打开浏览器。

先来看一下Edge函数的声明

接下来,我们介绍一下options参数。

options

在创建浏览器对象时可以传递必要的参数,如浏览器的名字,打开方式,版本,加载策略等等。

这里主要介绍两个重要参数。

8.1 设置无头模式

  • 我们肉眼能看到浏览器被打开,看到浏览器中各种元素,如:文字,图片,视频等元素的方式叫做有头模式(我们前面演示的内容都是有头模式,能看到浏览器中的内容)。
  • 而无头模式即为程序在后端运行,我们看不到任何界面的表现。

自动化打开浏览器默认为有头模式,需要设置无头模式需要手动设置。

#创建浏览器参数配置对象
options = webdriver.ChromeOptions()
#设置无头模式,不添加默认为有头模式
options.add_argument("-headless")
#创建浏览器驱动对象,传递options参数
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()),options=options)

代码:

当运行改代码时,并不会显示打开浏览器。

那浏览器到底有没有被打开?

我们用一段代码来验证一下。

运行结果:

所以浏览器是被打开了,只不过所有的操作我们都看不到了。

8.2 页面加载策略

当一个页面资源过大时,可能导致加载速度较慢,其中主要的页面框架已经加载完成了,还有一些视频/图片资源还在下载。

driver.get默认情况下等待所有资源加载完成之后才能继续往下执行代码,但是实际上主要的页面框架加载完成后我们就可以继续执行自动化代码了,若一直等待的话可能会造成页面加载超时、元素找不到的问题.......

浏览器左上角显示X就表示页面元素还没加载完。

#创建浏览器参数配置对象
options = webdriver.ChromeOptions()
#将浏览器加载方式设置为eager
options.page_load_strategy = 'eager'
#创建浏览器驱动对象,传递options参数
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()),options=options)

页面加载方式主要有三种:

编写代码进行测试,以访问csdn主页面为例:

1)normal,即等待页面加载完毕

运行结果:

页面中所有元素都加载完毕之后,才会执行下一步代码(退出)

2)eager,页面主体框架出来后就执行下一步

运行结果:

当出现到该页面时(页面还没有完全加载完)就执行下一步代码了

 

3)none,完全不阻塞

运行结果:

甚至都没有看到他打开csdn就退出了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921107.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32F103C8T6实时时钟RTC

目录 前言 一、RTC基本硬件结构 二、Unix时间戳 2.1 unix时间戳定义 2.2 时间戳与日历日期时间的转换 2.3 指针函数使用注意事项 ​三、RTC和BKP硬件结构 四、驱动代码解析 前言 STM32F103C8T6外部低速时钟LSE&#xff08;一般为32.768KHz&#xff09;用的引脚是PC14和PC…

AI社媒引流工具:解锁智能化营销的新未来

在数字化浪潮的推动下&#xff0c;社交媒体成为品牌营销的主战场。然而&#xff0c;面对海量的用户数据和日益复杂的运营需求&#xff0c;传统营销方法显得力不从心。AI社媒引流王应运而生&#xff0c;帮助企业在多平台中精准触达目标用户&#xff0c;提升营销效率和效果。 1.…

知识中台:提升企业知识管理的智能化水平

在数字化转型的浪潮中&#xff0c;企业知识管理的智能化水平成为提升竞争力的关键。HelpLook知识中台通过集成先进的AI技术&#xff0c;为企业提供了一个智能化的知识管理平台。 一、知识管理智能化的重要性 智能化的知识管理不仅能够提高信息检索的效率&#xff0c;还能通过…

Unreal5从入门到精通之EnhancedInput增强输入系统详解

前言 从Unreal5开始,老版的输入系统,正式替换为EnhancedInput增强型输入系统,他们之间有什么区别呢? 如果有使用过Unity的同学,大概也知道,Unity也在2020版本之后逐渐把输入系统也升级成了新版输入系统,为什么Unreal和Unity都热衷于升级输入系统呢?这之间又有什么联系…

C语言数据结构与算法--简单实现队列的入队和出队

&#xff08;一&#xff09;队列的基本概念 和栈相反&#xff0c;队列(Queue)是一种先进先出&#xff08;First In First Out&#xff09;的线性表。只 允许在表的一端进行插入&#xff0c;而在另一端删除元素&#xff0c;如日常生活中的排队现象。队列中 允许插入的一端叫队尾…

docker搭建私有仓库,实现镜像的推送和拉取

1.拉取docker仓库镜像 docker pull registry 2.启动registry容器 docker run -d registry 3.查看当前仓库中存在的镜像&#xff08;一&#xff09; curl -XGET http://192.168.111.162: 5000/v2/_catalog 192.168.111.162 部署docker仓库宿主机的ip 5000 部署docker仓库映射到宿…

算法学习笔记(九):网格图DFS、图论算法DFS、动态规划DP、贪心

一.网格图DFS 适用于需要计算连通块个数、大小的题目 1.岛屿数量 给你一个由 1(陆地) 和 0&#xff08;水&#xff09;组成的二维网格&#xff0c;请你计算网格中岛屿的数量 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和\或竖直方向上相邻的陆地连接形成 此外&…

Cmakelist.txt之Linux-redis配置

1.cmakelist.txt cmake_minimum_required(VERSION 3.16) ​ project(redis_linux_test LANGUAGES C) ​ ​ ​ add_executable(redis_linux_test main.c) ​ # 设置hiredis库的头文件路径和库文件路径 set(Hiredis_INCLUDE_DIR /usr/local/include/hiredis) set(Hiredis_LIBRA…

【Node.js】Node.js 和浏览器之间的差异

Node.js 是一个强大的运行时环境&#xff0c;它在现代 JavaScript 开发中扮演着重要角色。然而&#xff0c;许多开发者在使用 Node.js 时常常会感到困惑&#xff0c;尤其是与浏览器环境的对比。本文将深入探讨 Node.js 和浏览器之间的差异&#xff0c;帮助你全面理解两者的设计…

【物联网原理与应用】实验二:红外传感实验

目录 一、实验目的 二、实验原理 三、实验内容及步骤 四、实验结果 五、核心代码 一、实验目的 学习试验模块上线路的连接操作理解掌握红外传感器的工作原理实现对红外传感器数据的接收和处理 二、实验原理 1、将红外辐射能转换成电能的光敏元件称为红外传感器&#…

PAL(Program-Aided Language Model)

PAL&#xff08;Program-Aided Language Model&#xff09;是一种结合生成式语言模型&#xff08;如 GPT&#xff09;和程序执行能力的技术框架。它的核心思想是通过让语言模型生成代码或程序来解决复杂任务&#xff0c;程序执行的结果反过来增强语言模型的输出准确性和逻辑性。…

java基础概念36:正则表达式1

一、正则表达式的作用 作用一&#xff1a;校验字符串是否满足规则&#xff1b;作用二&#xff1a;在一段文本中查找满足要求的内容。——爬虫 二、正则表达式 2-1、字符类 示例&#xff1a; public static void main(String[] args) {System.out.println("a".matc…

VsCode 插件推荐(个人常用)

VsCode 插件推荐&#xff08;个人常用&#xff09;

工业储能柜的大小该如何选择,工商储能系统设备哪家好?

在能源转型和可持续发展的大潮中&#xff0c;工商业储能系统因其提升清洁能源利用率、降低电能损耗、实现“双碳”目标等优势而备受青睐。它们不仅增强了电力系统的可靠性和灵活性&#xff0c;还帮助企业降低成本、提高经济效益。储能系统通过负荷管理适应电价波动&#xff0c;…

人工智能之数学基础:线性代数在人工智能中的地位

本文重点 从本文开始&#xff0c;我们将开启线性代数的学习&#xff0c;在线性代数中有向量、矩阵&#xff0c;以及各种性质&#xff0c;那么这些数学知识究竟和人工智能有什么关系呢&#xff1f; 重要性 机器学习和深度学习的本质就是训练模型&#xff0c;要想训练模型需要使…

数字IC后端实现时钟树综合系列教程 | Clock Tree,Clock Skew Group之间的区别和联系

Q: Clock&#xff0c;Clock Tree和Skew Group有何区别&#xff1f;Innovus CCOPT引擎是如何使用这些的&#xff1f; Clock是时序约束SDC中的时钟定义点。 create_clock -name clk_osc -period $period_24m [get_ports xin_osc0_func] 时钟树综合(Clock Tree Synthesis)之前应…

飞桨大模型PaddleOCR

一、新建项目PaddleOCRProject 二、查看开源 pip install paddlepaddle pip install paddleocr指定镜像源下载才快&#xff1a; pip install paddlepaddle -i https://pypi.tuna.tsinghua.edu.cn/simple pip install paddleocr -i https://pypi.tuna.tsinghua.edu.cn/simple 三…

31、js中日期操作

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>日期</title> </head> <body></body> <script>// js中日期操作 var datenew Date();document.write("日期时间&am…

【大数据学习 | Spark】Spark中的join原理

join是两个结果集之间的链接&#xff0c;需要进行数据的匹配。 演示一下join是否存在shuffle。 1. 如果两个rdd没有分区器&#xff0c;分区个数一致 &#xff0c;会发生shuffle。但分区数量不变。 scala> val arr Array(("zhangsan",300),("lisi",…

NLP论文速读(CVPR 2024)|使用DPO进行diffusion模型对齐

论文速读|Diffusion Model Alignment Using Direct Preference Optimization 论文信息&#xff1a; 简介&#xff1a; 本文探讨的背景是大型语言模型&#xff08;LLMs&#xff09;通过人类比较数据和从人类反馈中学习&#xff08;RLHF&#xff09;的方法进行微调&#xff0c;以…