[TOC]

selenium webdriver简介

本文是学习了《Selenium自动化测试完全指南》和其他网络上的教程写出的学习笔记

介绍

WebDriver是一种API和协议,它定义了一种不依赖于编程语言、用于控制Web浏览器行为的接口

Selenium通过WebDriver来支持各种浏览器的自动化。

每种浏览器还需要有一个特定的基于WebDriver的实现来负责控制浏览器,这种实现称为驱动程序。驱动程序通常为可执行文件(.exe),一般由浏览器厂商开发并提供。

安装

查看自己的浏览器版本,然后搜索对应浏览器驱动版本进行下载,解压出压缩包内的Chormedriver.exe文件,配置该文件所在目录到环境变量Path(可选).

测试使用

1
2
3
4
5
6
7
8
9
10
from selenium import webdriver
from selenium.webdriver.chrome.service import Service

#option = webdriver.ChromeOptions()

# 创建 WebDriver 对象,指明使用chrome浏览器驱动
wd = webdriver.Chrome(service=Service(r'D:\ChromeDriver\chromedriver.exe'))

# 调用WebDriver 对象的get方法 可以让浏览器打开指定网址
wd.get('https://www.baidu.com')

下面都以Chrome浏览器为例

浏览器窗口的基本操作

浏览器导航操作

打开get、后退back、前进forward、刷新refresh

1
2
3
4
wd.get('https://www.baidu.com')
wd.back()
wd.forward()
wd.refresh()

浏览器窗口操作

调整浏览器窗口的位置和大小,以及关闭浏览器窗口

1
2
3
4
5
6
7
8
wd.minimize_window()	# 最小化窗口
wd.maximize_window() # 最大化窗口
wd.close() # 关闭窗口

# 控制浏览器窗口的位置与大小
wd.set_window_position(坐标X, 坐标Y) # 将浏览器窗口移动到指定位置
wd.set_window_size(宽度像素, 高度像素) # 将浏览器窗口设置为指定大小
wd.set_window_rect(坐标X, 坐标Y, 宽度像素, 高度像素) # 将浏览器窗口移动到指定位置,同时设置窗口大小

获取浏览器信息

标题和网址、窗口位置和大小

1
2
3
4
5
6
7
8
9
10
11
wd.title	#获取浏览器窗口当前的标题
wd.current_url #获取浏览器窗口当前的网址
wd.name #浏览器名称
wd.page_source #当前页面源码


# 返回值是dict类型的对象
wd.get_window_position() #获取位置对象
wd.get_window_size() #获取大小对象
wd.get_window_rect() #获取位置及大小对象

查找页面元素

按id、name、class属性查找

按照HTML元素的id属性查找元素

1
2
3
4
5
6
7
8
wd.find_element_by_id("id属性值")
find_element(By.ID,"id属性值")

wd.find_element_by_name("name属性值")
find_element(By.NAME,"name属性值")

wd.find_element_by_class("class属性值")
find_element(By.CLASS,"class属性值")

ps: 一般情况下请尽量使用id或name属性进行查找,因为这两个属性通常用作元素的唯一标识,但class属性可能会被多个元素引用。

按链接文本查找

按链接的文本查找元素

1
2
3
4
5
wd.find_element_by_link_test("链接的文本")
find_element(By.LINK_TEST,"链接的文本")

# 按链接文本进行模糊查找
wd.find_element_by_partial_link_text("链接的一部分文本")

按标签类型查找

按照HTML标签类型查找元素

1
2
3
4
5
wd.find_element_by_tag_name("HTML标签名称")

driver.find_element_by_tag_name("input") #查找首个<input/>元素
driver.find_element_by_tag_name("a") #查找首个<a/>元素
driver.find_element_by_tag_name("span") #查找首个<span/>元素

ps: 一个页面中可能会有多个HTML标签相同的元素,除非页面上只有一个该类型的标签,否则可能会查找到其他元素而非目标元素。请尽量使用其他类型的查找方式。

按XPath查找

XPath是一种综合性的查找方式,不仅支持前几种查找方式,而且还能通过XPath表达式进行更加丰富的高级查找。

XPath的全称为XML路径语言(XML Path Language),使用路径表达式来选取XML文档中的节点或者节点集,类似文件系统

1
wd.find_element_by_xpath("XPath表达式")

基于绝对路径或相对路径定位

1
2
3
4
5
6
# 路径以斜线(/)开始,那么该路径就表示到一个元素的绝对路径。
wd.find_element_by_xpath("/html/body/div/div/div/div/div/form/span/input")

# 相对路径定位以双斜线(//)开头
# 表示选择文档中所有满足双斜线(//)后面的规则的元素(无论层级关系)
wd.find_element_by_xpath("//span/input") #选择所有父元素是span的input元素

基于索引或属性定位

1
2
3
4
5
6
7
8
# 索引定位非常简单,使用中括号[]并填入索引即可
wd.find_element_by_xpath("//span/input[1]") #选取第1个与表达式//span/input匹配的元素
wd.find_element_by_xpath("//span/input[last()]") #选取最后1个与表达式匹配的元素

# 属性定位通过前缀@来指定属性名称,然后指定期望的属性值来进行定位
wd.find_element_by_xpath("//input[@id='kw']")
wd.find_element_by_xpath("//input[@name='wd']")
wd.find_element_by_xpath("//input[@class='s_ipt']")

基于轴定位

基于相对关系的定位

1
2
3
4
5
6
7
8
9
wd.find_element_by_xpath("//span[@class='soutu-btn']/following::input[1]")  
#先找到class属性为soutu-btn的span标签,然后通过/following::input[1]找到在它之后的首个input元素

wd.find_element_by_xpath("//a[@id='quickdelete']/preceding::input[1]")
# 先找到id属性为quickdelete的a标签,然后通过/preceding::input[1]找到在它之前的首个input元素

wd.find_element_by_xpath("//input[@id='su']/parent::span/parent::form//input[@id
='kw']")
# 先找到"百度一下"按钮,然后找到它的父级span元素,再找到它的父级form元素,然后找到form元素内id为wd的input元素

基于函数或表达式定位

1
2
3
4
5
6
7
8
9
10
11
wd.find_element_by_xpath("//a[text()='hao123']")  #查找文本为hao123的a元素
wd.find_element_by_xpath("//a[contains(@href,'www.hao123.com')]") #查找href属性包含www.hao123.com的a元素
wd.find_element_by_xpath("//a[contains(text(),'ao12')]") #查找文本包含ao12的a元素
wd.find_element_by_xpath("//a[starts-with(@href,'https://www.hao')]") #查找href属性以https://www.hao开始的a元素

# 通过一些逻辑表达式来查找元素,例如and或or
wd.find_element_by_xpath("//a[@name='errorname' or text()='hao123']")
# 查找name属性为errorname或者文本等于hao123的元素,虽然第一个条件无法匹配到元素,但由于两个条件是或的关系,因此第二个条件能顺利定位目标

wd.find_element_by_xpath("//a[contains(@href,'hao123') and text()='hao123']")
# 查找href属性包含hao123并且文本等于hao123的元素

按CSS选择器查找

CSS选择器也是一种综合性的查找方式,它不但支持前3种查找方式,而且能通过CSS选择器进行更加丰富的高级查找。

1
2
wd.find_element_by_css_selector("CSS选择器")
find_element(By.CSS_SELECTOR,"CSS选择器")

通过层级关系定位

1
2
wd.find_element_by_css_selector("html > body > div > div > div > div > div > form > span > input")
wd.find_element_by_css_selector("span > input")

基于关键属性定位

1
2
3
wd.find_element_by_css_selector("#kw")  #符号"#"代表使用id匹配,即匹配id为kw的元素
wd.find_element_by_css_selector(".s_ipt") #符号"."代表使用class名称匹配,即匹配class名称为s_ipt的元素
wd.find_element_by_css_selector("[name=wd]") #表达式"[属性名称=属性值]"表示按照属性匹配,这里匹配name属性为wd的元素

基于属性进行模糊定位

1
2
3
wd.find_element_by_css_selector("[href^='https://www.hao']")  #查找href属性值以https://www.hao开头的元素
wd.find_element_by_css_selector("[href$='123.com']") #查找href属性值以123.com结尾的元素
wd.find_element_by_css_selector("[href*=hao123]") #查找href属性值包含hao123的元素

相对来说,更推荐使用XPath表达式

通过By对象按动态条件查找

在之前的查找中,都直接使用对应的查找函数来查找元素,但这样做并不利于代码的维护。在分层较好的测试框架中,查找动作与查找条件互相隔离,查找元素时并不知道是按什么方式查找的,只是依赖于动态传入的条件,因此这种条件并不能完全确定,可能是按id查找,也可能是按其他方式查找。

1
2
3
from selenium.webdriver.common.by import By

wd.find_element(By.查找条件, "条件值")

查找元素集合

1
2
wd.find_elements_...()
# 把之前的函数以find_element开头,改为以find_elements开头

嵌套查找

已有元素嵌套查找元素,查找在已有元素之下符合条件的子元素

1
2
baiduSearchForm = wd.find_element(By.ID, "form")
baiduSearchTextbox = baiduSearchForm.find_element(By.ID, "kw")

页面元素的基本操作

1
2
3
4
5
6
7
8
9
10
11
12
# 单击元素
webElement.click()

# 向元素输入内容或上传附件,input
webElement.send_keys("要输入的内容")

# 清空元素的内容
webElement.clear()
# 和send_keys函数类似,clear函数多用于输入框元素

# 提交表单元素
webElement.submit()

下拉框元素的选项操作

之前的操作都用WebElement对象的函数来进行操作,但下拉框使用Select对象的函数,因此需要先将WebElement对象转换成Select对象才能进行下拉框的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
from selenium.webdriver.support.select import Select

selectWebElement = Select(webElement)
# 下拉框分为单选下拉框(<Select/>)和多选列表框(<Select multiple= "multiple"/>),但这两种下拉框的操作方式差不多,这里只介绍单选下拉框。
selectWebElement.select_by_visible_text("选项的文本") #按文本选择
selectWebElement.select_by_value("选项的值") #按选项值选择
selectWebElement.select_by_index(选项的索引) #按选项索引选择,索引从0开始

# 多选框
selectWebElement.deselect_all() #取消所有选择
selectWebElement.deselect_by_visible_text("选项的文本") #按文本取消选择
selectWebElement.deselect_by_value("选项的值") #按选项值取消选择
selectWebElement.deselect_by_index(选项的索引) #按选项索引取消选择,索引从0开始

获取页面元素的内容

获取元素的基本属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
webElement.id	# 标示
webElement.size
webElement.rect #宽高和坐标

# 文本值
webElement.text

# 标签类型
webElement.tag_name

# 是否选中
webElement.is_selected()

# 是否可编辑
webElement.is_enabled()

# 是否已显示
# 有时,即使元素已经在页面上看不到了,这个元素也仍然在HTML代码当中,只是没有显示出来。
webElement.is_displayed()

获取元素的HTML属性、DOM属性及CSS属性

1
2
# HTML属性
webElement.get_attribute("属性名称")

当浏览器加载页面时,它会解析HTML并从中生成DOM对象。对于元素节点,大多数标准HTML属性会自动成为DOM对象的属性。DOM对象是一个继承自Object的普通JavaScript对象,这里所说的DOM属性,正是指该JavaScript对象的属性。自定义属性不会映射到DOM属性上。

1
2
3
4
5
# DOM属性
webElement.get_property("属性名称")

# CSS属性
webElement.value_of_css_property("CSS属性名称")

获取元素的位置与大小

1
2
3
webElement.location		#获取位置对象
webElement.size #获取大小对象
webElement.rect #获取位置及大小对象

获取下拉框元素的选项

1
2
3
4
5
6
7
8
from selenium.webdriver.support.select import Select

SelectWebElement.first_selected_option #获取首个已选中项(类型为WebElement)
SelectWebElement.all_selected_options #获取全部已选中项(类型为WebElement数组)
SelectWebElement.options #获取下拉框提供的所有选项(无论是否已选中,类型为WebElement数组)

# 举例
SelectWebElement.first_selected_option.text

处理浏览器弹出框

在浏览器中,弹出框分为3种——Alert、Confirmation以及Prompt。

Alert:提示框,只有一个“确定”按钮(对应的JavaScript代码为alert(‘这是Alert’);)

Confirmation:确认框,需要选择(对应的JavaScript代码为confirm(‘这是Confirmation’);)

Prompt:输入框,需要输入内容(对应的JavaScript代码为prompt(‘这就是prompt’,”);)

在WebDriver中,以上弹出框统一视为Alert对象,只需调用Alert对象的方法即可。

1
2
3
4
5
6
7
8
9
10
11
12
# 获取Alert对象
wd.switch_to.alert

# 弹出框的确认与取消
Alert.accept() #单击"确认"按钮
Alert.dismiss() #单击"取消"按钮

# 文本
Alert.text

# 向弹出框中输入内容
Alert.send_keys("要输入的内容")

多网页切换操作

多浏览器窗口的切换主要依赖于浏览器窗口句柄,只要得到了WebDriver拥有的全部句柄,就可以切换到指定句柄的浏览器窗口。

1
2
3
4
5
6
# 获取句柄
driver.current_window_handle #获得WebDriver当前正在操作的浏览器窗口句柄
driver.window_handles #获得该WebDriver实例下的全部句柄

# 切换
driver.switch_to.window(窗口句柄)

IFrame切换

IFrame在比较早的年代使用较多,但Ajax开始流行后,IFrame的使用场景越来越少

1
2
3
driver.switch_to.frame(IFrame元素)  #切换到当前页面(或IFrame)的下一级指定IFrame中
driver.switch_to.parent_frame() #切换到当前IFrame的上一级页面(或IFrame)中
driver.switch_to.default_content() #切换会默认的HTML文档

结束WebDriver会话

1
2
driver.close()		# 关闭WebDriver当前所在的窗口
driver.quit() # 关闭所有相关窗口并结束会话