【学习笔记】web自动化测试----selenium

来自b站白月黑羽教学视频

selenium

Selenium 是一个 Web 应用自动化框架
自动化架构:
在这里插入图片描述

通过http协议进行交互

Selenium环境的安装主要就是安装两样东西: 客户端库 和 浏览器 驱动

如何定位元素:

  1. 根据元素的id定位元素
  2. 根据 class属性、tag名 选择元素
    在这里插入图片描述

图中<后的是元素标签,如input,span,后面跟的是元素属性,如type,name,class,id等。
find_elements_by_class_name 方法返回的是找到的符合条件的 所有 元素 (这里有3个元素), 放在一个列表中返回。而如果我们使用find_element_by_class_name(注意少了一个s)方法, 就只会返回第一个元素。
find_element 和 find_elements 的区别:

  • 使用 find_elements 选择的是符合条件的 所有 元素, 如果没有符合条件的元素, 返回空列表
  • 使用 find_element 选择的是符合条件的 第一个 元素, 如果没有符合条件的元素, 抛出 NoSuchElementException 异常
  1. 通过WebElement对象选择元素
    WebElement对象 也可以调用 find_elements_by_xxx, find_element_by_xxx 之类的方法。
    WebDriver 对象 选择元素的范围是 整个 web页面, 而WebElement 对象 选择元素的范围是 该元素的内部。

隐式等待

因为我们的代码执行的速度比 百度服务器响应的速度 快。百度还没有来得及 返回搜索结果,我们就执行了如下代码。
Selenium提供了一个更合理的解决方案,是这样的:后续所有选择元素的操作时,当发现元素没有找到的时候, 并不 立即返回 找不到元素的错误。而是周期性(每隔半秒钟)重新寻找该元素,直到该元素找到,或者超出指定最大等待时长,这时才 抛出异常(如果是 find_elements 之类的方法, 则是返回空列表)。

操控元素的基本方法:

  • 点击元素
  • 在元素中输入字符串,通常是对输入框这样的元素
  • 获取元素包含的信息,比如文本内容,元素的属性

1. 点击元素
点击元素 非常简单,就是调用元素WebElement对象的 click方法,点击的是该元素的 中心点 位置

2. 输入框
输入字符串 也非常简单,就是调用元素WebElement对象的send_keys方法。
如果我们要 把输入框中已经有的内容清除掉,可以使用WebElement对象的clear方法。
eg:我们要写一个自动化程序:要求在输入框中填入姓名:白月黑羽。

from selenium import webdriver

wd = webdriver.Chrome()
wd.implicitly_wait(10)

wd.get('http://cdn1.python3.vip/files/selenium/test3.html')
element = wd.find_element_by_id('input1')
element.clear()
element.send_keys('白月黑羽')

3. 获取元素信息

  • 获取元素的文本内容:通过WebElement对象的 text 属性,可以获取元素 展示在界面上的 文本内容。有时候,元素的文本内容没有展示在界面上,或者没有完全完全展示在界面上。 这时,用WebElement对象的text属性,获取文本内容,就会有问题。出现这种情况,可以尝试使用 element.get_attribute(‘innerText’) ,或者 element.get_attribute(‘textContent’)
  • 获取元素属性:通过WebElement对象的 get_attribute 方法来获取元素的属性值。
    执行完自动化代码,如果想关闭浏览器窗口可以调用WebDriver对象的 quit 方法,像这样 wd.quit()
  • 获取整个元素对应的HTML:可以使用 element.get_attribute('outerHTML’)。如果,只是想获取某个元素 内部 的HTML文本内容,可以使用 element.get_attribute(‘innerHTML’)
  • 获取输入框里面的文字:对于input输入框的元素,要获取里面的输入文本,用text属性是不行的,这时可以使用 element.get_attribute(‘value’)

CSS选择器

CSS语法:
在这里插入图片描述

{}外面的部分为CSS选择器,选择某一部分元素;里面为具体的CSS样式
根据CSS表达式来定位元素:

  1. 根据 tag名、id、class 选择元素
    find_element_by_css_selector(CSS Selector参数)
    括号中,tag名不变,id前加上#,class前加上.
    如:
    wd.find_elements_by_css_selector('div')
    等价于
    wd.find_elements_by_tag_name('div')
    wd.find_elements_by_css_selector('#'searchtext')
    等价于
    wd.find_elements_by_id('searchtext')
  2. 选择子元素和后代元素
    在这里插入图片描述

其中layer1和layer2时container的子元素,inner11和inner12是layer1的子元素,inner21是layer2的子元素,inner11、inner12和inner21是container的后代元素,layer1和layer2也是container的后代元素
如果 元素2元素1直接子元素,CSS选择器语法为:
元素1 > 元素2,最终选择的是元素2
也支持多级选择:
元素1 > 元素2 > 元素3 > 元素4,最终选择元素4
如果 元素2元素1后代元素,CSS选择器语法为:
元素1 元素2,中间用1个或多个空格隔开
也支持更多层级的选择:
元素1 元素2 元素3 元素4
3. 根据元素其他属性进行选择
css 选择器支持通过任何属性来选择元素,语法是用一个方括号[]。
如选择 属性href值为 http://www.miitbeian.gov.cn 的元素,可表示为:
[href="http://www.miitbeian.gov.cn"]
(若只有一个href,后面url可省略)
还可与其他方法混用,前面可以加上标签名的限制,比如 div[class='SKnet'] 表示 选择所有 标签名为div,且class属性值为SKnet的元素。

  • 可以选择 属性值 包含 某个字符串 的元素。
    如要选择a节点,里面的href属性包含了 miitbeian 字符串,可使用:a[href*="miitbeian"]
  • 可以 选择 属性值 以某个字符串 开头 的元素。
    如要选择a节点,里面的href属性以 http 开头,可使用:a[href^="http"]
  • 可以选择 属性值 以某个字符串 结尾 的元素。
    如要选择a节点,里面的href属性以 gov.cn 结尾,可使用:a[href$="gov.cn"]
  • 如果一个元素具有多个属性,CSS 选择器 可以指定 选择的元素要 同时具有多个属性的限制,如div[class=misc][ctype=gun]

验证CSS表达式是否正确,可在开发者模式下使用ctrl+f在这里插入图片描述

同时选中具有某种特征和另一种特征的元素,中间用逗号,如要同时选择所有class 为 plant 和 class 为 animal 的元素,可表示为:
.plant , .animal
逗号两边可为不同类型,如class和tag
注意:
若要选择所有 id 为 t1 里面的 span 和 p 元素,需写成#t1 > span , #t1 > p,不能写成#t1 > span,p,这样就变成了选择所有 id 为 t1 里面的 span 和 所有的 p 元素

我们可以指定选择的元素 是父元素的第几个子节点
使用nth-child,如要选择的是 第2个子元素,并且是span类型,可写成:span:nth-child(2),倒数可加上last,即nth-last-child。
还可以指定选择的元素 是父元素的第几个 某类型的 子节点,使用nth-of-type,倒数可加上last,即nth-last-of-type。
也可选择奇数或偶数节点,如果要选择的是父元素的 偶数节点,使用 nth-child(even),如果要选择的是父元素的 奇数节点,使用 nth-child(odd)
兄弟节点选择,如可以选择 h3 后面紧跟着的兄弟节点 span,可以表示为h3 + span,或h3后面所有的span节点,可以表示为h3 ~ span

frame切换

在html语法中,frame 元素 或者iframe元素的内部 会包含一个 被嵌入的 另一份html文档。在我们使用selenium打开一个网页时, 我们的操作范围 缺省是当前的 html ,因此需要切换到frame中去,即使用:
wd.switch_to.frame(frame_reference),其中frame_reference 可以是 frame 元素的属性 name 或者 ID 。
也可以根据frame的元素位置或者属性特性,使用find系列的方法,选择到该元素,得到对应的WebElement对象。如:
wd.switch_to.frame(wd.find_element_by_tag_name("iframe"))

使用完毕后想要切换至外边主html,可使用wd.switch_to.default_content()wd.switch_to.frame(None)

窗口切换

点击一个链接或按钮后会打开一个新窗口,但即使新窗口打开了,我们的 WebDriver对象对应的还是老窗口,自动化操作也还是在老窗口进行。
如果要到新的窗口里面操作,可以使用Webdriver对象的switch_to属性的 window方法,即wd.switch_to.window(handle)。WebDriver对象有window_handles 属性,这是一个列表对象, 里面包括了当前浏览器里面所有的窗口句柄。可用如下代码来找到对应窗口的handle:

for handle in wd.window_handles:
    wd.switch_to.window(handle)
    if 'Bing' in wd.title:
        break

上述代码意义为我们依次获取 wd.window_handles 里面的所有句柄对象,并且调用wd.switch_to.window(handle) 方法,切入到每个窗口,然后检查里面该窗口对象的属性(可以是标题栏,地址栏),判断是不是我们要操作的那个窗口,如果是,就跳出循环。

若想再回到原来窗口,可以先把原来窗口的句柄保存下来,使用
mainWindow = wd.current_window_handle
切换到新窗口操作完后,再切换回原窗口:
wd.switch_to.window(mainWindow)
如:

from selenium import webdriver

wd = webdriver.Chrome()
wd.implicitly_wait(5)

wd.get('http://cdn1.python3.vip/files/selenium/sample3.html')

link = wd.find_element_by_css_selector('a')
link.click()

mainWindow = wd.current_window_handle

for handle in wd.window_handles:
    wd.switch_to.window(handle)
    if 'Bing' in wd.title:
        break

print(wd.title)

wd.find_element_by_css_selector('input#sb_form_q').send_keys('白月黑羽')
wd.find_element_by_css_selector('div#sb_go_par').click()

wd.switch_to.window(mainWindow)
wd.find_element_by_css_selector('#outerbutton').click()

选择框

选择框分为:radio框,checkbox框和select框
在这里插入图片描述

radio框
单选,click选择,点击新的选项之后就不选择之前的选项了,使用checked="checked"属性表示默认的选择。

checkbox框
可多选,click选择,选择新的选项之后,之前的选项还保持选择,使用checked="checked"属性表示默认的选择。即有要选中checkbox的一个选项,必须 先获取当前该复选框的状态 ,如果该选项已经勾选了,就不能再点击。否则反而会取消选择。
思路可以是这样:先把已经选中的选项全部点击一下,确保都是未选状态,再点击需要选择的相应选项

select框
radio框及checkbox框都是input元素,只是里面的type不同而已。select框则是一个新的select标签。
对于Select 选择框, Selenium 专门提供了一个 Select类 进行操作,有如下选择方法:

  • 根据选项的 value属性值 ,选择元素,即
    s.select_by_value('')
  • 根据选项的 次序 (从1开始),选择元素,即
    select_by_index()
  • 根据选项的 可见文本 ,选择元素,即
    select_by_visible_text
    若要去除选中文本,将上述三种select换成deselect即可。去除选中所有元素,使用:
    deselect_all
    导入select类方法如下:
# 导入Select类
from selenium.webdriver.support.ui import Select

# 创建Select对象
select = Select(wd.find_element_by_id(''))

# 通过select对象选中
select.select_by_visible_text('')

对于select多选框,要选中某几个选项,要注意去掉原来已经选中的选项。
可以用select类 的deselect_all方法,清除所有 已经选中 的选项。

更多高级动作

可以通过 Selenium 提供的 ActionChains 类来实现
ActionChains 类 里面提供了 一些特殊的动作的模拟,比如 鼠标右键点击、双击、移动鼠标到某个元素、鼠标拖拽等
在这里插入图片描述

移动鼠标到某个地方

使用move_to_element,但真正执行一定要调用perform()函数。
例:打开百度首页,移动鼠标到“更多”上
在这里插入图片描述

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains

wd = webdriver.Chrome()
wd.implicitly_wait(5)

wd.get('https://www.baidu.com/')

ac = ActionChains(wd)
ac.move_to_element(wd.find_element_by_css_selector('[name="tj_briicon"]')).perform()
冻结页面

鼠标移动到百度的“更多”就会出现更多选项,但一旦移走就会消失,若想查看html,需冻结这个页面。
开发者工具栏 console 里面执行如下js代码:
setTimeout(function(){debugger}, 5000)
表示在 5000毫秒后,执行 debugger 命令,执行该命令会 浏览器会进入debug状态。 debug状态有个特性, 界面被冻住, 不管我们怎么点击界面都不会触发事件。
然后就可以点击 开发者工具栏的 查看箭头
在这里插入图片描述

再去点击相应的页面即可

弹出对话框

弹出的对话框有三种类型,分别是 Alert(警告信息)、confirm(确认信息)和prompt(提示输入)
Alert对话框
Alert 弹出框,目的就是显示通知信息,只需用户看完信息后,点击 OK(确定) 就可以了
在这里插入图片描述

如果我们不去点击OK,页面的其它元素是不能操作的。
selenium提供如下方法使用代码模拟用户点击 OK 按钮:
switch_to.alert.accept()
如果程序要获取弹出对话框中的信息内容, 可以通过 如下代码:
switch_to.alert.text

Confirm对话框
Confirm弹出框,主要是让用户确认是否要进行某个操作。
在这里插入图片描述

Confirm对话框的点击确定按钮和获取对话框内容方法与Alert对话框相同,取消按钮可使用:
switch_to.alert.dismiss()

Prompt对话框
出现 Prompt 弹出框 是需要用户输入一些信息,提交上去。
在这里插入图片描述

Prompt对话框其他按钮操作方法与前边相同,输入框需要先send_keys,再accept(),因此需要先获取一个alert对象,即alert = wd.switch_to.alert,再对alert进行操作即可

注意:
有些弹窗并非浏览器的alert 窗口,而是html元素,这种对话框,只需要通过之前介绍的选择器选中并进行相应的操作就可以了。

Xpath选择器

Xpath 还支持如 爬虫框架 Scrapy, 手机App框架 Appium等
整个HTML文档根节点用’/‘表示,如果想选择的是根节点下面的html节点,则可以在搜索框输入/html。而/html/body/div表示选择html下面的body下面的div元素。
/ 有点像 CSS中的 > , 表示直接子节点关系。
/html/body/div可同样表示为html > body > div
使用自动化程序表示为wd.find_elements_by_xpath("//div//p")

绝对路径选择
从根节点开始的,到某个节点,每层都依次写下来,每层之间用 / 分隔的表达式,就是某元素的 绝对路径。即从/开始

相对路径选择
xpath需要前面加 // , 表示从当前节点往下寻找所有的后代元素,不管它在什么位置。
因此若要选择所有标签名为 div 的元素,需写成//div
// 符号也可以继续加在后面。如要选择所有的 div 元素里面的所有的 p 元素 ,不管div 在什么位置,也不管p元素在div下面的什么位置,则可以这样写 //div//p

通配符

  • 是一个通配符,对应任意节点名的元素。
    //div/*表示所有div节点的所有直接子节点。
Xpath根据属性选择

表示为:
[@属性名=‘属性值’]
注意:

  • 属性名注意前面有个@
  • 属性值一定要用引号, 可以是单引号,也可以是双引号

选择 id 为 west 的元素,可以这样 //*[@id='west']
其中//*表示为不管什么元素,若要表示所有tag名为p且有 id的元素,可表示为//p[@id]
选择所有 select 元素中 class为 single_choice 的元素,可以这样 //select[@class='single_choice']。其中属性值必须写完整。
同样的也可以利用其它的属性选择,如选择具有select属性的所有元素,可写为//*[@select]

同css选择器一样,也可选择属性值包含某种字符串的元素。

  • 包含关系:contains。如要选择 style属性值 包含 color 字符串的 页面元素 ,可以这样 :
    //*[contains(@style,'color')]
  • 开头关系:starts-with。如要选择 style属性值 以 color 字符串 开头 的 页面元素 ,可以这样:
    //*[starts-with(@style,'color')]
  • 结尾关系:ends-with。但这是xpath2.0的语法,目前所有浏览器均不支持。因此若要使用结尾关系还是需要用css选择。

xpath也可以根据次序选择元素,直接在方括号中使用数字表示次序,如[2]。
要选择 p类型第2个的子元素,就是//p[2]。若要选择任何类型的第2个子元素,把p换成通配符即可,即//*[2]
若要选择倒数元素,可用last()表示。

  • 倒数第一个://p[last()]
  • 倒数第二个://p[last()-1]

xpath特有功能:选择子元素的次序范围
如选取option类型第1到2个子元素:
//option[position()<=2]
或要选择option类型的倒数后两个元素:
//option[position()>=last()-1]

组选择
如要同时选择所有的option和所有的h4,用css表示为option , h4,xpath则用竖线|隔开,即表示为//option | //h4

xpath的主要功能:选择父节点
当某个元素没有特征可以直接选择,但是它有子节点有特征, 就可以采用这种方法,先选择子节点,再指定父节点。某个元素的父节点用 /… 表示
如要选择 id 为 china 的节点的父节点,可以写为//*[@id='china']/..。还可以继续寻找上层父节点,即//*[@id='china']/../../..

兄弟节点选择
css选择器用于兄弟节点选择是波浪线~,xpath则用语法following-sibling::表示。
如要选择 class 为 single_choice 的元素的所有后续兄弟节点,css表示为.single_choice ~ *,用xpath则表示为//*[@class="single_choice"]/following-sibling::*
还可以选择 前面的 兄弟节点,使用 preceding-sibling::

要在某个元素内部使用xpath选择元素, 需要 在xpath表达式最前面加个点

# 先寻找id是china的元素 
china = wd.find_element_by_id('china') 
# 再选择该元素内部的p元素 
elements = china.find_elements_by_xpath('.//p')

版权声明:本文为aaaatong原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。