selenium study
—
—
启动浏览器的完整过程
启动
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.baidu.com/')
设置浏览器大小
driver.maximize_window() #将浏览器最大化显示
#driver.set_window_size(480, 800) #参数数字为像素点
点击页面
#selenium 元素查找find_element_by_id方法,找到元素后进行点击
driver.find_element_by_id('su').click()
填写表单
找到文本字段的<input>或<textarea>
元素,然后调用send_keys()
elem=driver.find_element_by_id('kw')#输入框标识
elem.send_keys('selenium') #输入内容
elem.submit()# 提交
发送特殊键
# 删除多输入的一个 m
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)
# 输入空格键+“教程”
driver.find_element_by_id("kw").send_keys(Keys.SPACE)
# ctrl+a 全选输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a')
# ctrl+x 剪切输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x')
# ctrl+v 粘贴内容到输入框
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'v')
# 通过回车键来代替单击操作
driver.find_element_by_id("su").send_keys(Keys.ENTER)
send_keys(Keys.TAB) # 制表键(Tab)
send_keys(Keys.ESCAPE) # 回退键(Esc)
send_keys(Keys.F1) # 键盘 F1
send_keys(Keys.F12) # 键盘 F12
点击浏览器按钮
driver.back()点击“返回”按钮。
driver.forward()点击“前进”按钮。
driver.refresh()点击“刷新”按钮。
driver.quit()点击“关闭窗口”按钮。
close() | 关闭单个窗口 |
---|---|
quit() | 关闭所有窗口 |
寻找元素/对象定位
对象的定位应该是自动化测试的核心,要想操作一个对象,首先应该识别这个对象。
定位对象的目的一般有下面几种
· 操作对象
· 获得对象的属性,如获得测试对象的class属性,name属性等等
· 获得对象的text
· 获得对象的数量
webdriver提供了一系列的对象定位方法,常用的有以下几种
-
· id
-
· name
-
· class name
-
· link text
-
· partial link text
-
· tag name
-
· xpath
-
· css selector
#coding=utf-8from selenium import webdriverimport time
browser = webdriver.Firefox()
browser.get("http://www.baidu.com")
time.sleep(2)
#########百度输入框的定位方式##########
#通过id方式定位
browser.find_element_by_id("kw").send_keys("selenium")
#通过name方式定位
browser.find_element_by_name("wd").send_keys("selenium")
#通过tag name方式定位
browser.find_element_by_tag_name("input").send_keys("selenium")
#通过class name 方式定位
browser.find_element_by_class_name("s_ipt").send_keys("selenium")
#通过CSS方式定位
browser.find_element_by_css_selector("#kw").send_keys("selenium")
#通过xphan方式定位
browser.find_element_by_xpath("//input[@id='kw']").send_keys("selenium")
############################################
browser.quit()
find_element_ by_tag_name()返回一个WebElement对象
find_elements_ 返回WebElement_对象的列表,包含所有匹配元素
find_element(By.TAG_NAME, “input”)
#selenium 元素查找find_element_by_id方法,找到元素后输入信息
driver.find_element_by_id('kw').send_keys('selenium')
#find_element(By.," ")
driver.find_element(By.ID, "kw")
driver.find_elements(By.TAG_NAME, "input")
driver.quit()#退出
-
_by_tag_name()区分大小写,如无匹配元素,就抛出NoSuchElement异常,需添加try和except语句。
from selenium import webdriver driver = webdriver.Chrome() driver.get('https://www.baidu.com/') try: elem=driver.find_element_by_class_name('kw') print('Found <%s> element with that class name.'%\ (elem.tag.name)) except: print('Was not able to find an element with that name.')
id
id 和 name 是我们最最常用的定位方式,因为大多数控件都有这两个属性
id一般情况下在当前页面中是唯一的。
username=driver.find_element_by_id("id_username")
password=driver.find_element_by_id("id_password")
#用户名输入admin,密码输入123241234
username.send_keys("admin")
password.send_keys("123241234")
通过前端工具,找到了百度输入框的属性信息,如下:
<input id="kw" class="s_ipt" type="text" maxlength="100" name="wd" autocomplete="off">
通过find_element_by_id(“kw”) 函数就是捕获到百度输入框
name
标签中要有name属性,而且name唯一,优先级低于id. 如果界面有多个name属性,那么,默认选择第一个
通过find_element_by_name(“wd”)函数同样也可以捕获百度输入框
driver.find_element(By.ID, "kw")
driver.find_elements(By.NAME, "wd")
**tag name **
input 就是一个标签的名字,可以通过find_element_by_tag_name(“input”) 函数来定位。
tag_name是通过标签名称来定位的,如<a>
:a标签。
tag name有很多重复的,造成了选择tag name来定位页面元素不准确,所以使用这个方法定位web元素的机会很少。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hWPpU5aq-1677229123326)(C:\Users\00308559\AppData\Roaming\Typora\typora-user-images\image-20210831145931634.png)]
发现上面有很多input的选项。所以我们扩大节点的参照选择,我们选择上面这个form来作为我们tag name。
try:
driver.find_element_by_tag_name("form")
print ('test pass: tag name found')
except Exception as e:
print ("Exception found", format(e))
driver.quit()
使用这个方法定位元素的机会比较少
class name
class=“s_ipt”
通过find_element_by_class_name(“s_ipt”)函数捕获百度输入框。
<span id="s_kw_wrap" class="bg s_ipt_wr quickdelete-wrap"></span>
class 属性表示一类的样式,应用在多个元素上,那么唯一性就要注意了。
看下面这个 span 元素,其中class=“bg s_ipt_wr quickdelete-wrap”,空格在这里的作用是分割多个类名的。这个 class 属性有两个空格,那么的代表这个 class 属性中包含了 3 个类名。
使用 WebDriver 中的 class_name 定位方式的话,就只能使用其中一个。
driver.find_element_by_class_name("bg") ✅
driver.find_element_by_class_name("bg s_ipt_wr quickdelete-wrap") ❌
对 class_name 的唯一性验证,同样在 console 中借助 JavaScript 代码:
document.getElementsByClassName("bg")
driver.find_element_by_class_name(“classname”)
很多并列的元素如list表单,class都是共用同一个
**driver.find_element_by_class_name(“classname”)**就可以派上用场了,该方法可以返回的是一个list列表,那么所有针对list的方法在它上面都同样适用。比如,如果我们知道想要定位的元素在页面中是第n个,则可以这样定位:
driver.find_elements_by_class_name(“classname”)[n] (注意:是elements,不是element)
CSS定位
CSS(Cascading Style Sheets)是一种语言,它被用来描述HTML和XML文档的表现。CSS使用选择器来为页面元素绑定属性。
find_element_by_css_selector(“#kw”)
通过find_element_by_css_selector( )函数,选择取百度输入框的id属性来定义
也可以取name属性
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
driver.find_element_by_css_selector("a[name=\"tj_news\"]").click()
可以取title属性
<a onclick="queryTab(this);" mon="col=502&pn=0" title="web" href="http://www.baidu.com/">网页</a>
driver.find_element_by_css_selector("a[title=\"web\"]").click()
也可以是取…:
<a class="RecycleBin xz" href="javascript:void(0);">
driver.find_element_by_css_selector("a.RecycleBin").click()
单一属性定位
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
定位输入框
1:type selector
driver.find_element_by_css_selector(‘input’)
2:id 定位
driver.find_element_by_css_selector**(‘#kw’)**
3:class 定位
driver.find_element_by_css_selector('.s_ipt’)
4:其他属性定位
driver.find_element_by_css_selector('[name=‘wd’]')
driver.find_element_by_css_selector(“[type=‘text’]”)
组合属性定位
1:id组合属性定位
driver.find_element_by_css_selector("input#kw")
2:class组合属性定位
driver.find_element_by_css_selector(“input.s_ipt”)
3:其他属性组合定位
driver.find_element_by_css_selector(“input[name=‘wd’]”)
4:仅有属性名,没有值也可以
driver.find_element_by_css_selector(“input[name]”)
5:两个其他属性组合定位
driver.find_element_by_css_selector(“[name=‘wd’][autocomplete=‘off’]”)
模糊匹配属性值
1>属性值由多个空格隔开,匹配其中一个值的方法
driver.find_element_by_css_selector(“input[class~=‘btn’]”)
2>匹配属性值为字符串开头的方法
driver.find_element_by_css_selector(“input[class^=‘btn’]”)
3>匹配属性值字符串结尾的方法
driver.find_element_by_css_selector(“input[class$=‘s_btn’]”)
4>匹配被-分割的属性值的方法,如上图的class
driver.find_element_by_css_selector(“input[class|=‘s’]”) #要求精确填写的属性值
XPath
XPath是一种在XML文档中定位元素的语言。因为HTML可以看做XML的一种实现,所以selenium用户可是使用这种强大语言在web应用中定位元素。
XPath术语
节点Node
在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
</bookstore>
<bookstore> (文档节点)
<author>J K. Rowling</author> (元素节点)
lang="en" (属性节点)
基本值(Atomic value):无父或无子的节点
J K. Rowling
"en"
项目(Item):基本值或节点
节点关系
父(parent):每个元素及属性都有一个父
在下面的例子中,book 元素是 title、author、year 以及 price 元素的父:
<book>
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
**子(Children)😗*元素节点可有零个、一个或多个子。
title、author、year 以及 price 元素都是 book 元素的子
同胞(Sibling):拥有相同的父的节点
title、author、year 以及 price 元素都是同胞
**先辈(Ancestor)😗*某节点的父,父的父
title 元素的先辈是 book 元素和 bookstore 元素:
后代(Descendant):某个节点的子,子的子,等等。
bookstore 的后代是 book、title、author、year 以及 price 元素:
语法
XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
选取节点:XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点。 |
/ | 从根节点选取。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点。 |
… | 选取当前节点的父节点。 |
@ | 选取属性。 |
路径表达式 | 结果 |
---|---|
bookstore | 选取 bookstore 元素的所有子节点。 |
/bookstore | 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
//@lang | 选取名为 lang 的所有属性。 |
谓语(Predicates):谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
路径表达式 | 结果 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()❤️] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang=‘eng’] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
选取未知节点
XPath 通配符可用来选取未知的 XML 元素。
通配符 | 描述 |
---|---|
* | 匹配任何元素节点。 |
@* | 匹配任何属性节点。 |
node() | 匹配任何类型的节点。 |
路径表达式 | 结果 |
---|---|
/bookstore/* | 选取 bookstore 元素的所有子元素。 |
//* | 选取文档中的所有元素。 |
//title[@*] | 选取所有带有属性的 title 元素。 |
选取若干路径:通过在路径表达式中使用“|”运算符,您可以选取若干个路径。
在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:
路径表达式 | 结果 |
---|---|
//book/title | //book/price | 选取 book 元素的所有 title 和 price 元素。 |
//title | //price | 选取文档中的所有 title 和 price 元素。 |
/bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
XPath Axes(轴)
XPath 轴:轴可定义相对于当前节点的节点集。
轴名称 | 结果 |
---|---|
ancestor | 选取当前节点的所有先辈(父、祖父等)。 |
ancestor-or-self | 选取当前节点的所有先辈(父、祖父等)以及当前节点本身。 |
attribute | 选取当前节点的所有属性。 |
child | 选取当前节点的所有子元素。 |
descendant | 选取当前节点的所有后代元素(子、孙等)。 |
descendant-or-self | 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 |
following | 选取文档中当前节点的结束标签之后的所有节点。 |
namespace | 选取当前节点的所有命名空间节点。 |
parent | 选取当前节点的父节点。 |
preceding | 选取文档中当前节点的开始标签之前的所有节点。 |
preceding-sibling | 选取当前节点之前的所有同级节点。 |
self | 选取当前节点。 |
位置路径表达式:位置路径可以是绝对的,也可以是相对的。
绝对路径起始于正斜杠( / ),而相对路径不会这样。在两种情况中,位置路径均包括一个或多个步,每个步均被斜杠分割:
绝对位置路径:
/step/step/...
相对位置路径:
step/step/...
每个步均根据当前节点集之中的节点来进行计算。
**步(step)**包括:
-
轴(axis)
定义所选节点与当前节点之间的树关系
-
节点测试(node-test)
识别某个轴内部的节点
-
零个或者更多谓语(predicate)
更深入地提炼所选的节点集
步的语法:
轴名称::节点测试[谓语]
例子 | 结果 |
---|---|
child::book | 选取所有属于当前节点的子元素的 book 节点。 |
attribute::lang | 选取当前节点的 lang 属性。 |
child:😗 | 选取当前节点的所有子元素。 |
attribute:😗 | 选取当前节点的所有属性。 |
child::text() | 选取当前节点的所有文本子节点。 |
child::node() | 选取当前节点的所有子节点。 |
descendant::book | 选取当前节点的所有 book 后代。 |
ancestor::book | 选择当前节点的所有 book 先辈。 |
ancestor-or-self::book | 选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点) |
child:😗/child::price | 选取当前节点的所有 price 孙节点。 |
运算符
XPath 表达式可返回节点集、字符串、逻辑值以及数字。
运算符 | 描述 | 实例 | 返回值 |
---|---|---|---|
| | 计算两个节点集 | //book | //cd | 返回所有拥有 book 和 cd 元素的节点集 |
+ | 加法 | 6 + 4 | 10 |
- | 减法 | 6 - 4 | 2 |
* | 乘法 | 6 * 4 | 24 |
div | 除法 | 8 div 4 | 2 |
= | 等于 | price=9.80 | 如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。 |
!= | 不等于 | price!=9.80 | 如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。 |
< | 小于 | price<9.80 | 如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。 |
<= | 小于或等于 | price<=9.80 | 如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。 |
> | 大于 | price>9.80 | 如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。 |
>= | 大于或等于 | price>=9.80 | 如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。 |
or | 或 | price=9.80 or price=9.70 | 如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。 |
and | 与 | price>9.00 and price<9.90 | 如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。 |
mod | 计算除法的余数 | 5 mod 2 | 1 |
dr.find_element_by_xpath("//*[@id='kw']")
dr.find_element_by_xpath("//*[@name='wd']")
dr.find_element_by_xpath("//input[@class='s_ipt']")
dr.find_element_by_xpath("/html/body/form/span/input")
dr.find_element_by_xpath("//span[@class='soutu-btn']/input")
dr.find_element_by_xpath("//form[@id='form']/span/input")
dr.find_element_by_xpath("//input[@id='kw' and @name='wd']")
link 定位
link_text、partial_link_text主要是用来定位HTML中的
<a href="url">超链接载体</a>
超链接载体文字必须是在网页中唯一存在的,不然可能会定位不到需要的元素
一个文字链接,我们可以通过link
#coding=utf-8
from selenium import webdriverimport time
browser = webdriver.Chrome()
browser.get("http://www.baidu.com")
time.sleep(2)
browser.find_element_by_link_text("贴吧").click()
time.sleep(2)
browser.quit()
Partial Link Text 定位
通过部分链接定位,这个有时候也会用到,我还没有想到很好的用处。可以只用链接的一部分文字进行匹配:
browser.find_element_by_partial_link_text("贴").click()
#通过find_element_by_partial_link_text() 函数,只用了“贴”字,脚本一样找到了"贴 吧" 的链接
层级定位
页面上有很多个属性基本相同的元素,现在需要具体定位到其中的一个。由于属性基本相当,所以在定位的时候会有些麻烦,这时候就需要用到层级定位。先定位父元素,然后再通过父元素定位子孙元素。
上面有两个文字链接,点击两个链接会弹出一模一样的的两个下拉菜单,这两个菜单的属性基本一样。那么我如何区分找到相应的菜单项呢?
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
import time
import os
dr = webdriver.Firefox()
file_path = 'file:///' + os.path.abspath('level_locate.html')
dr.get(file_path)
#点击Link1链接(弹出下拉列表)
dr.find_element_by_link_text('Link1').click()
#找到id 为dropdown1的父元素
WebDriverWait(dr, 10).until(lambda the_driver: the_driver.find_element_by_id('dropdown1').is_displayed())
#在父亲元件下找到link为Action的子元素
menu = dr.find_element_by_id('dropdown1').find_element_by_link_text('Action')
#鼠标定位到子元素上
webdriver.ActionChains(dr).move_to_element(menu).perform()
time.sleep(2)
dr.quit()
具体思路是:先点击显示出1个下拉菜单,然后再定位到该下拉菜单所在的ul,再定位这个ul下的某个具体的link。在这里,我们定位第1个下拉菜单中的Action这个选项
WebDriverWait(dr, 10)
10秒内每隔500毫秒扫描1次页面变化,当出现指定的元素后结束。
is_displayed()
该元素是否用户可以见
class ActionChains(driver)
driver: 执行用户操作实例webdriver
生成用户的行为。所有的行动都存储在actionchains对象。通过perform()存储的行为。
move_to_element(menu)
移动鼠标到一个元素中,menu上面已经定义了他所指向的哪一个元素
to_element:元件移动到
perform()
执行所有存储的行为
达到效果:下拉列表中Action选项处于被选中状态”,通过鼠标移动到选项上就达到到了这种效果,但通过程序模拟确实比较麻烦
操作对象
操作对象:
-
· click 点击对象
-
· send_keys 在对象上模拟按键输入
-
· clear 清除对象的内容,如果可以的话
send_keys(“XX”) 用于在一个输入框里输入内容。
click()用于点击一个按钮。
clear()用于清除输入框的内容,比如百度输入框里默认有个“请输入关键字”的信息,再比如我们的登陆框一般默认会有“账号”“密码”这样的默认信息。clear可以帮助我们清除这些信息。
WebElement 另一些常用方法:
- · text 获取该元素的文本
- · submit 提交表单
- · get_attribute 获得属性值
text
获取元素的文本信息
#coding=utf-8
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
time.sleep(2)
# 元素的文本信息
data=browser.find_element_by_class_name("s-bottom-layer-content").text # 元素的文本信息
print(data) #打印信息
time.sleep(3)
driver.quit()
关于百度 About Baidu 使用百度前必读 帮助中心 京公网安备11000002000001号 京ICP证030173号 ©2021 Baidu 互联网药品信息服务资格证书 (京)-经营性-2017-0020 信息网络传播视听节目许可证 0110516
问题:class_name怎么定位到具体的元素
submit
driver.find_element_by_id("kw").send_keys("selenium")
time.sleep(2)
#通过submit() 来操作
driver.find_element_by_id("su").submit()
与click区别不大?
get_attribute
获得属性值。
select = driver.find_element_by_tag_name("select")
allOptions = select.find_elements_by_tag_name("option")
for option in allOptions:
print("Value is: " + option.get_attribute("value"))
option.click()
id_#当前元素的ID
tag_name#获取元素标签名的属性
text#获取该元素的文本。
click()#单击(点击)元素
submit()#提交表单
clear()#清除一个文本输入元素的文本
get_attribute(name)#获得属性值
s_selected(self)#元素是否被选择Whether the element is selected.
is_enabled()#元素是否被启用
find_element_by_id(id_)
find_elements_by_id(id_)#查找元素的id
find_element_by_name(name)
find_elements_by_name(name)#查找元素的name
find_element_by_link_text(link_text)
find_elements_by_link_text(link_text)#查找元素的链接文本
find_element_by_partial_link_text(link_text)
find_elements_by_partial_link_text(link_text)#查找元素的链接的部分文本
find_element_by_tag_name(name)
find_elements_by_tag_name(name)#查找元素的标签名
find_element_by_xpath(xpath)#查找元素的xpath
find_elements_by_xpath(xpath)#查找元素内的子元素的xpath
find_element_by_class_name(name)#查找一个元素的类名
find_elements_by_class_name(name)#查找元素的类名
find_element_by_css_selector(css_selector)#查找并返回一个元素的CSS 选择器
find_elements_by_css_selector(css_selector)#查找并返回多个元素的CSS 选择器列表
send_keys(*value)#模拟输入元素
鼠标事件
在 WebDriver 中, 将这些关于鼠标操作的方法封装在 ActionChains 类提供。
from selenium.webdriver.common.action_chains import ActionChains
click(on_element=None) ——单击鼠标左键
click_and_hold(on_element=None) ——点击鼠标左键,不松开
context_click(on_element=None) ——点击鼠标右键
double_click(on_element=None) ——双击鼠标左键
drag_and_drop(source, target) ——拖拽到某个元素然后松开
drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某个坐标然后松开
key_down(value, element=None) ——按下某个键盘上的键
key_up(value, element=None) ——松开某个键
move_by_offset(xoffset, yoffset) ——鼠标从当前位置移动到某个坐标
move_to_element(to_element) ——鼠标移动到某个元素
move_to_element_with_offset(to_element, xoffset, yoffset) ——移动到距某个元素(左上角坐标)多少距离的位置
perform() ——执行链中的所有动作
release(on_element=None) ——在某个元素位置松开鼠标左键
send_keys(*keys_to_send) ——发送某个键到当前焦点的元素
send_keys_to_element(element, *keys_to_send) ——发送某个键到指定元素
from selenium import webdriver
#1.引入 ActionChains 类
from selenium.webdriver.common.action_chains import ActionChains
#1.创建Chrome浏览器对象,这会在电脑上在打开一个浏览器窗口
driver = webdriver.Chrome() # Get local session of firefox
driver.get("https://www.baidu.com/") # Load page
#2.定位到要悬停的元素
element= driver.find_element_by_id("s-usersetting-top")
#3.对定位到的元素执行鼠标悬停操作
ActionChains(driver).move_to_element(element).perform()
#找到链接
elem1=driver.find_element_by_link_text("高级搜索")
elem1.click()
#通过元素选择器找到id=sh_2,并点击设置
elem2=driver.find_element_by_id("q5_1")
elem2.click()
#保存设置
elem3=driver.find_element_by_class_name("prefpanelgo")
elem3.click()
键盘事件
Key模块为我们提供了模拟键盘按键的方法,那就是send_keys()方法。它不仅可以模拟键盘输入,也可以模拟键盘的操作。
要想调用键盘按键操作需要引入keys包:
from selenium.webdriver.common.keys import Keys
常用的键盘操作如下:
模拟键盘按键 说明
send_keys(Keys.BACK_SPACE) 删除键(BackSpace)
send_keys(Keys.SPACE) 空格键(Space)
send_keys(Keys.TAB) 制表键(Tab)
send_keys(Keys.ESCAPE) 回退键(Esc)
send_keys(Keys.ENTER) 回车键(Enter)
组合键的使用
模拟键盘按键 说明
send_keys(Keys.CONTROL,‘a’) 全选(Ctrl+A)
send_keys(Keys.CONTROL,‘c’) 复制(Ctrl+C)
send_keys(Keys.CONTROL,‘x’) 剪切(Ctrl+X)
send_keys(Keys.CONTROL,‘v’) 粘贴(Ctrl+V)
send_keys(Keys.F1…Fn) 键盘 F1…Fn
定位方式(selenium.webdriver.common.by)
from selenium.webdriver.common.by import By
By是selenium中内置的一个class,在这个class中有各种方法来定位元素
By所支持的定位器的分类:
CLASS_NAME = 'class name'
CSS_SELECTOR = 'css selector'
ID = 'id'
LINK_TEXT = 'link text'
NAME = 'name'
PARTIAL_LINK_TEXT = 'partial link text'
TAG_NAME = 'tag name'
XPATH = 'xpath'
主要应用于一个过滤器,而webdriver的方法是一个定位器。
例如:
#用户名输入框
username_Input = (By.ID, 'username')
#密码输入框
pwd_Input = (By.ID, 'password')
#登录按钮
login_btn = (By.TAG_NAME, 'button')
#首页的“新建投放计划”按钮
new_ads_plan = (By.XPATH, "//span[text()='新建投放计划']")
多表单切换
有时候我们定位一个元素,定位器没有问题,但一直定位不了,这时候就要检查这个元素是否在一个frame中,
在Web应用中经常会遇到frame/iframe表单嵌套页面的应用,WebDriver只能在一个页面上对元素识别与定位,对于frame/iframe表单内嵌页面上的元素无法直接定位。这时就需要通过switch_to.frame()方法将当前定位的主体切换为frame/iframe表单的内嵌页面中。
switch_to.frame() | 将当前定位的主体切换为frame/iframe表单的内嵌页面中 |
---|---|
switch_to.default_content() | 跳回最外层的页面 |
#coding=utf-8
from selenium import webdriver
import time
import os
browser = webdriver.Chrome()
file_path = 'file:///' + os.path.abspath('frame.html')
browser.get(file_path)
browser.implicitly_wait(30)
#先找到到ifrome1(id = f1)
browser.switch_to_frame("f1")
#再找到其下面的ifrome2(id =f2)
browser.switch_to_frame("f2")
#下面就可以正常的操作元素了
browser.find_element_by_id("kw").send_keys("selenium")
browser.find_element_by_id("su").click()
time.sleep(3)
browser.quit()
<html>
<body>
...
<iframe id="x-URS-iframe" ...>
<html>
<body>
...
<input name="email" >
126邮箱登录框的结构大概是这样子的,想要操作登录框必须要先切换到iframe表单
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.126.com")
driver.switch_to.frame('x-URS-iframe')
driver.find_element_by_name("email").clear()
driver.find_element_by_name("email").send_keys("username")
driver.find_element_by_name("password").clear()
driver.find_element_by_name("password").send_keys("password")
driver.find_element_by_id("dologin").click()
driver.switch_to.default_content()
driver.quit()
switch_to.frame() 默认可以直接取表单的id 或name属性。如果iframe没有可用的id和name属性,则可以通过下面的方式进行定位。
……
#先通过xpth定位到iframe
xf = driver.find_element_by_xpath('//*[@id="x-URS-iframe"]')
#再将定位对象传给switch_to.frame()方法
driver.switch_to.frame(xf)
……
driver.switch_to.parent_frame()
多窗口切换
在页面操作过程中有时候点击某个链接会弹出新的窗口,这时就需要主机切换到新打开的窗口上进行操作。WebDriver提供了switch_to.window()方法,可以实现在不同的窗口之间切换。
current_window_handle 获得当前窗口句柄
window_handles 返回所有窗口的句柄到当前会话
switch_to.window() 用于切换到相应的窗口,与上一节的switch_to.frame()类似,前者用于不同窗口的切换,后者用于不同表单之间的切换。
from selenium import webdriver
import time
driver = webdriver.Chrome("F:\Chrome\ChromeDriver\chromedriver")
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
#1.获得百度搜索窗口句柄
sreach_windows = driver.current_window_handle
driver.find_element_by_link_text('登录').click()
driver.find_element_by_link_text("立即注册").click()
#2.获得当前所有打开的窗口的句柄
all_handles = driver.window_handles
#3.进入注册窗口
for handle in all_handles:
if handle != sreach_windows:
driver.switch_to.window(handle)
print('跳转到注册窗口')
driver.find_element_by_name("userName").send_keys('123ae6789')
driver.find_element_by_name("phone").send_keys('15286642393')
driver.find_element_by_id("TANGRAM__PSP_4__password").send_keys('1ef456789')
time.sleep(2)
driver.quit()
# 获取当前全部窗口句柄集合;循环句柄并判断是否与当前打开的页面一致,不一致就关闭并切换到一致的窗口句柄
handles = driver.window_handles
for handle in handles:
if handle != driver.current_window_handle:
driver.close()
driver.switch_to.window(handle)
警告框处理
在WebDriver中处理JavaScript所生成的alert、confirm以及prompt十分简单,具体做法是使用 switch_to.alert 方法定位到 alert/confirm/prompt,然后使用text/accept/dismiss/ send_keys等方法进行操作。
text 返回 alert/confirm/prompt 中的文字信息
accept() 接受现有警告框
dismiss() 解散现有警告框
send_keys(keysToSend) 发送文本至警告框。keysToSend:将文本发送至警告框
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('http://www.baidu.com')
# 鼠标悬停至“设置”链接
link = driver.find_element_by_id('s-usersetting-top')
ActionChains(driver).move_to_element(link).perform()
# 打开搜索设置
driver.find_element_by_link_text("搜索设置").click()
#在此处设置等待2s否则可能报错
time.sleep(2)
# 保存设置
driver.find_element_by_class_name("prefpanelgo").click()
time.sleep(2)
# 接受警告框
driver.switch_to.alert.accept()
driver.quit()
下拉框选择
导入选择下拉框Select类,使用该类处理下拉框操作。
from selenium.webdriver.support.select import Select
select_by_value(“选择值”) | select标签的value属性的值 |
---|---|
select_by_index(“索引值”) | 下拉框的索引 |
select_by_visible_testx(“文本值”) | 下拉框的文本值 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K0Pe6vyM-1677229123334)(C:\Users\00308559\AppData\Roaming\Typora\typora-user-images\image-20210903113255078.png)]
来选择下拉列表里的$10.69
#-*-coding=utf-8
from selenium import webdriver
import os,time
driver= webdriver.Chrome()
file_path = 'file:///' + os.path.abspath('drop_down.html')
driver.get(file_path)
time.sleep(2)
m=driver.find_element_by_id("ShippingMethod")
m.find_element_by_xpath("//option[@value='10.69']").click()
time.sleep(3)
driver.quit()
文件上传
对于通过input标签实现的上传功能,可以将其看作是一个输入框,即通过send_keys()指定本地文件路径的方式实现文件上传。
通过send_keys()方法来实现文件上传:
from selenium import webdriver
import os
driver = webdriver.Chrome()
file_path = 'file:///' + os.path.abspath('upfile.html')
driver.get(file_path)
# 定位上传按钮,添加本地文件
driver.find_element_by_name("file").send_keys('D:\\upload_file.txt')
driver.quit()
cookie操作
有时候我们需要验证浏览器中cookie是否正确,因为基于真实cookie的测试是无法通过白盒和集成测试进行的。WebDriver提供了操作Cookie的相关方法,可以读取、添加和删除cookie信息。
WebDriver操作cookie的方法:
get_cookies() 获得所有cookie信息
get_cookie(name) 返回字典的key为“name”的cookie信息
add_cookie(cookie_dict) 添加cookie。“cookie_dict”指字典对象,必须有name 和value 值
delete_cookie(name,optionsString) 删除cookie信息。“name”是要删除的cookie的名称,“optionsString”是该cookie的选项,目前支持的选项包括“路径”,“域”
delete_all_cookies() 删除所有cookie信息
from selenium import webdriver
import time
browser = webdriver.Chrome("F:\Chrome\ChromeDriver\chromedriver")
browser.get("http://www.youdao.com")
#1.打印cookie信息
print('=====================================')
print("打印cookie信息为:")
print(browser.get_cookies)
#2.添加cookie信息
dict={'name':"name",'value':'Kaina'}
browser.add_cookie(dict)
print('=====================================')
print('添加cookie信息为:')
#3.遍历打印cookie信息
for cookie in browser.get_cookies():
print('%s----%s\n' %(cookie['name'],cookie['value']))
#4.删除一个cookie
browser.delete_cookie('name')
print('=====================================')
print('删除一个cookie')
for cookie in browser.get_cookies():
print('%s----%s\n' %(cookie['name'],cookie['value']))
print('=====================================')
print('删除所有cookie后:')
#5.删除所有cookie,无需传递参数
browser.delete_all_cookies()
for cookie in browser.get_cookies():
print('%s----%s\n' %(cookie['name'],cookie['value']))
time.sleep(3)
browser.close()
控制滚动条
有时候我们需要控制页面滚动条上的滚动条,但滚动条并非页面上的元素,这个时候就需要借助js是来进行操作。一般用到操作滚动条的会两个场景:
- 注册时的法律条文需要阅读,判断用户是否阅读的标准是:滚动条是否拉到最下方。
- 要操作的页面元素不在吸视范围,无法进行操作,需要拖动滚动条
用于标识滚动条位置的代码
<body onload= "document.body.scrollTop=0 ">
<body onload= "document.body.scrollTop=100000 ">
如果滚动条在最上方的话,scrollTop=0 ,那么要想使用滚动条在最可下方,可以scrollTop=100000 ,这样就可以使滚动条在最下方
#coding=utf-8
from selenium import webdriver
import time
#访问百度
driver=webdriver.Firefox()
driver.get("http://www.baidu.com")
#搜索
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
time.sleep(3)#休眠3s目的是获得服务器的响应内容,如果不使用休眠可能报错
#将页面滚动条拖到底部
js="var q=document.documentElement.scrollTop=10000"
driver.execute_script(js)
time.sleep(3)
#将滚动条移动到页面的顶部
js="var q=document.documentElement.scrollTop=0"
driver.execute_script(js)
time.sleep(3)
driver.quit()
#4 滚动左右滚动条---向右
js2 = "var q=document.documentElement.scrollLeft=10000"
driver.execute_script(js2)
sleep(15)
#5 滚动左右滚动条---向左
js3 = "var q=document.documentElement.scrollLeft=0"
driver.execute_script(js3)
web测试
测试类型
● 测试静态内容
静态内容测试是最简单的测试,用于验证静态的、不变化的UI元素的存在性。例如:
→ 每个页面都有其预期的页面标题?这可以用来验证链接指向一个预期的页面。
→ 应用程序的主页包含一个应该在页面顶部的图片吗?
→ 网站的每一个页面是否都包含一个页脚区域来显示公司的联系方式,隐私政策,以及商标信息?
→ 每一页的标题文本都使用的<h1>
标签吗?每个页面有正确的头部文本内吗?
● 测试链接
Web站点的一个常见错误为的失效的链接或链接指向无效页。链接测试涉及点各个链接和验证预期的页面是否存在。如果静态链接不经常更改,手动测试就足够。但是,如果你的网页设计师经常改变链接,或者文件不时被重定向,链接测试应该实现自动化。
● 功能测试
在您的应用程序中,需要测试应用的特定功能,需要一些类型的用户输入,并返回某种类型的结果。通常一个功能测试将涉及多个页面,一个基于表单的输入页面,其中包含若干输入字段、提交“和”取消“操作,以及一个或多个响应页面。用户输入可以通过文本输入域,复选框,下拉列表,或任何其他的浏览器所支持的输入。
功能测试通常是需要自动化测试的最复杂的测试类型,但也通常是最重要的。**典型的测试是登录,注册网站账户,用户帐户操作,帐户设置变化,复杂的数据检索操作等等。**功能测试通常对应着您的应用程序的描述应用特性或设计的使用场景。
● 测试动态元素
通常一个网页元素都有一个唯一的标识符,用于唯一地定位该网页中的元素。通常情况下,**唯一标识符用HTML标记的’id’属性或’name’属性来实现。**这些标识符可以是一个静态的,即不变的、字符串常量。它们也可以是动态生产值,在每个页面实例上都是变化的。例如,有些Web服务器可能在一个页面实例上命名所显示的文件为doc3861,并在其他页面实力上显示为doc6148,这取决于用户在检索的‘文档’。验证文件是否存在的测试脚本,可能无法找到不变的识别码来定位该文件。通常情况下,具有变化的标识符的动态元素存在于基于用户操作的结果页面上,然而,显然这取决于Web应用程序。
验证结果
● 断言assert与验证verify
如果您使用的断言,测试将在检查失败时停止,并不运行任何后续的检查。优点:你可以直截了当地看到检查是否通过。缺点:当检查失败,后续的检查不会被执行,无法收集那些检查的结果状态。
**验证命令将不会终止测试。**如果您的测试只使用验证,可以得到保证是—假设没有意外的异常—测试会被执行完毕,而不管是否发现缺陷。缺点:你必须做更多的工作,以检查您的测试结果。您将需要在打印输出控制台或日志文件中查看结果。每次运行测试,你都需要花时间去查看结果输出。如果您运行的是数以百计的测试,每个都有它自己的日志,这将耗费时间。及时得到反馈会更合适,因此断言通常比验证更常使用。
● 权衡:assertTextPresent,assertElementPresent和assertText
您现在应该熟悉这些命令及使用它们的机制。如果没有,请参阅相关章节。在构建你的测试时,你需要决定
→ 只检查在页面上的文本吗?(verify/ assertTextPresent)
→ 只检查是否在页面上存在HTML元素吗?即文本,图像,或其他没被检查的内容,只要和HTML标记相关。(verify/ assertElementPresent)
→ 需要同时检查元素和它的文本内容?(verify/ assertText)
使用assertText,因为这是最严格的类型检查点。
Verify/ assertText是最特殊的测试类型。**HTML元素(标签)或文本的不符合都会导致测试失败。**使用verify/ assertElementPresent,确保一个特定类型的元素存在(如果使用XPath,可以确保它相对页面内其他对象的存在)。但你不关心的内容是什么,你只关心某个特定的元素,比方说,一个图片在一个特定的位置。
随着时间的推移和经验的积累,如何决定使用还是非常简单的。
定位元素的策略
● 选择一个定位策略
使用元素的ID或name定位符,在测试执行方面来说,是最有效的方式。也让你的测试代码更具可读性,如果在页面源代码中的ID或name属性被友好命名的话。XPath语句需要更长的时间来处理,因为浏览器必须运行它的XPath处理器。
使用链接的文本进行定位是很方便的,并运行起来也不错如果链接文本很可能会经常改变,使用<a>
标签定位元素将是更好的选择。
相对使用ID或name属性定位,使用XPath进行定位有一个独特的优势。使用XPath(DOM)中,你可以找到页面上相对于其他对象的一个对象。例如,如果有一个链接必须存在<div>
标签里的第二个段落内,您可以使用XPath进行定位。使用ID和name属性定位,你只能得出它们存在指定的页面,而不知具体的页面位置。如果你必须测试显示公司标志的图像出现在页面顶部的头部分,XPath定位可能是更好的选择。
● 定位动态元素
对于有些元素每次点击都是动态的 即每次都是不一样的 对于这种元素我们可以采用与他相关的其他静态的元素定位
比如 iframe 这个元素的id是动态的 每次都在变化
第一种就是我们观察下 是整个都是变化的还是部分变化 部分变化我们可以采用不变的部分定位 整个都在变化的 只能利用其它不变的元素
通过xpath来定位 drive.find…xpath(“//iframe[starts-with(@x,‘y’)]”) x是不变的元素属性 y则是属性的内容 这里采用以什么开头contains(a, b) 如果a中含有字符串b,则返回true,否则返回false
driver.find_element_by_xpath(“//div[contains(@id, ‘btn-attention’)]”)
starts-with(a, b) 如果a是以字符串b开头,返回true,否则返回false
driver.find_element_by_xpath(“//div[starts-with(@id, ‘btn-attention’)]”)
ends-with(a, b) 如果a是以字符串b结尾,返回true,否则返回false
driver.find_element_by_xpath(“//div[ends-with(@id, ‘btn-attention’)]”)
第二种就是定位到该元素的父节点子节点或者同等级节点 在进行定位 比如先定位到同级元素 在定位到其父节点 在定位子节点 即要定位的节点元素
鼠标
action = ActionChains(self.driver)
action.double_click(elem).perform()
ActionChains(self.driver).send_keys(Keys.ENTER).perform()
*HTML元素(标签)或文本的不符合都会导致测试失败。**使用verify/ assertElementPresent,确保一个特定类型的元素存在(如果使用XPath,可以确保它相对页面内其他对象的存在)。但你不关心的内容是什么,你只关心某个特定的元素,比方说,一个图片在一个特定的位置。
随着时间的推移和经验的积累,如何决定使用还是非常简单的。
定位元素的策略
● 选择一个定位策略
使用元素的ID或name定位符,在测试执行方面来说,是最有效的方式。也让你的测试代码更具可读性,如果在页面源代码中的ID或name属性被友好命名的话。XPath语句需要更长的时间来处理,因为浏览器必须运行它的XPath处理器。
使用链接的文本进行定位是很方便的,并运行起来也不错如果链接文本很可能会经常改变,使用<a>
标签定位元素将是更好的选择。
相对使用ID或name属性定位,使用XPath进行定位有一个独特的优势。使用XPath(DOM)中,你可以找到页面上相对于其他对象的一个对象。例如,如果有一个链接必须存在<div>
标签里的第二个段落内,您可以使用XPath进行定位。使用ID和name属性定位,你只能得出它们存在指定的页面,而不知具体的页面位置。如果你必须测试显示公司标志的图像出现在页面顶部的头部分,XPath定位可能是更好的选择。
● 定位动态元素
对于有些元素每次点击都是动态的 即每次都是不一样的 对于这种元素我们可以采用与他相关的其他静态的元素定位
比如 iframe 这个元素的id是动态的 每次都在变化
第一种就是我们观察下 是整个都是变化的还是部分变化 部分变化我们可以采用不变的部分定位 整个都在变化的 只能利用其它不变的元素
通过xpath来定位 drive.find…xpath(“//iframe[starts-with(@x,‘y’)]”) x是不变的元素属性 y则是属性的内容 这里采用以什么开头contains(a, b) 如果a中含有字符串b,则返回true,否则返回false
driver.find_element_by_xpath(“//div[contains(@id, ‘btn-attention’)]”)
starts-with(a, b) 如果a是以字符串b开头,返回true,否则返回false
driver.find_element_by_xpath(“//div[starts-with(@id, ‘btn-attention’)]”)
ends-with(a, b) 如果a是以字符串b结尾,返回true,否则返回false
driver.find_element_by_xpath(“//div[ends-with(@id, ‘btn-attention’)]”)
第二种就是定位到该元素的父节点子节点或者同等级节点 在进行定位 比如先定位到同级元素 在定位到其父节点 在定位子节点 即要定位的节点元素
鼠标
action = ActionChains(self.driver)
action.double_click(elem).perform()
ActionChains(self.driver).send_keys(Keys.ENTER).perform()