<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
option,select{
width: 100px;
}
option{
height: 20px;
}
</style>
<body>
<form action="" method="get">
<input type="text" id="username" name="username" placeholder="username" class='input-text'>
<br />
<input type="password" id="password" name="password" placeholder="password" class="input-password">
<br />
<input type="text" name="password2" placeholder="确认密码"><br />
</form>
<H8> </H8>
<div id='links'>
<ul>
<li><a>标签</a></li>
<li><a>Genetic Algorithms in Search, Optimization, and Machine Learning</a></li>
<li>hello</li>
<li>world</li>
</ul>
</div>
<H8> </H8>
<div>
<button id="button" onclick="click()">我是一个按钮</button>
<span id="click_count">鼠标单击次数: 0</span>
</div>
<H8> </H8>
<div>
<select name="select" id="select-single">
<option value="1" selected>zhangsan</option>
<option value="2">lisi</option>
<option value="3">wangwu</option>
<option value="4">zhaoliu</option>
<option value="5">tangli</option>
</select>
</div>
<H8> </H8>
<div>
<select name="select" id="select-multiple" multiple>
<option value="1" selected>zhangsan</option>
<option value="2">lisi</option>
<option value="3">wangwu</option>
<option value="4">zhaoliu</option>
<option value="5">tangli</option>
</select>
</div>
</body>
<script>
let click_count = 0
let button = document.getElementById('button')
button.onclick = function click(event) {
click_count++;
document.getElementById('click_count').innerHTML = `鼠标单击次数: ${click_count}`;
}
</script>
</html>
什么是Selenium
-
Selenium是一个用于Web应用程序测试的工具,可以直接调用浏览器,它支持所有主流的浏览器。
-
最初是为网站自动化测试而开发的,但却被很多爬虫爱好者发扬光大
Selenium特点
- 开源软件:源代码开放可以根据需要来增加工具的某些功能
- 跨平台:linux 、windows 、mac
- 核心功能:就是可以在多个浏览器上进行自动化测试
- 多语言:Java、Python、C#、JavaScript、Ruby等
- 成熟稳定:目前已经被google , 百度, 腾讯等公司广泛使用
- 功能强大:能够实现类似商业工具的大部分功能,因为开源性,可实现定制化功能
什么是WebDriver?
Webdriver 是一种用于控制浏览器的程序,不同的浏览器有不同的 webdriver。
-
Chrome (ChromeDriver)
-
IE(InternetExplorerDriver)
-
Opera(OperaDriver)
-
Firefox (FirefoxDriver)
-
safari(SafariDriver)
-
HtmlUnit (HtmlUnit Driver)
webdriver 提供了对外的接口,其他程序通过这些接口控制 webdriver 与浏览器的交互。例如:我们可以写 python 程序来调用 webdriver 的接口。实际上从其他程序的角度看,webdriver 就是充当了和浏览器交互的一个桥梁。 -
提示:
Firefox、Chrome:对元素定位和操作有良好的支持,同时对JavaScript支持也非常好。
IE: 只能在windows平台运行,所有浏览器中运行速度最慢
HtmlUnit:无GUI(界面)运行,运行速度最快;
Selenium 执行过程
python代码--> selenium 封装的 python 接口--> WebDriver 提供接口--> 浏览器
环境搭建
基于Python环境搭建
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
注意: 在安装selenium时,前提是Python3.5以上版本安装完毕且能正常运行
谷歌浏览器驱动安装
确认浏览器的版本
查看方式
下载驱动
下载与浏览器版本一致的驱动版本
国内不能直接访问Chrome官网,可以在ChromeDriver仓库中下载 或者 https://npm.taobao.org/mirrors/chromedriver
选择自己对应的平台版本WebDriver 元素定位简单方式
selenium页面元素定位的方法,是在selenium中可以通过多种方式来定位标签,返回标签元素对象:
- 通过 id 属性定位 : find_element_by_id
- 通过 name 属性定位 : find_element_by_name
- 通过 class 属性定位 : find_element_by_class_name
- 通过标签名定位 : find_element_by_tag_name
- 通过内容定位 a 标签(绝对匹配) : find_element_by_link_text
- 通过内容定位 a 标签(模糊匹配) : find_element_by_partial_link_text
from selenium.webdriver import Chrome
import traceback
from selenium.webdriver.chrome.service import *
from selenium.webdriver.common.by import By
service = Service("./chromedriver")
driver = Chrome(service=service)
# 通过指定chromedriver的路径来实例化driver对象
# 控制浏览器访问url地址
# file://{本地文件绝对路径}
driver.get('file://./test.html') # 打开本地 html 文件
try:
print(driver.find_element_by_id('username')) # 通过 id 属性定位
driver.find_element_by_name('password2') # 通过 name 属性定位
driver.find_element_by_class_name('input-password') # 通过 class 属性定位
driver.find_element_by_tag_name('ul') # 通过标签名定位
driver.find_element_by_link_text('标签') # 通过内容定位 a 标签(绝对匹配)
driver.find_element_by_partial_link_text('Optimization') # 通过内容定位 a 标签(模糊匹配)
except Exception:
print(traceback.format_exc())
finally:
# 退出浏览器
driver.quit()
- Chrome(executable_path='./chromedriver')中executable参数指定的是下载好的chromedriver文件的路径
- 要在代码中尽量保证driver.quit()能够成功执行,进而关闭driver退出模拟浏览器;不然将在操作系统中残留进程,对系统造成不必要的压力
- find_element_by_方式已不推荐使用,推荐使用find_element(By_,元素)
xpath 方式
- XPath 即为 XML Path 的简称,它是一种用来确定 XML/HTML 文档中某部分位置的语言。
- XPath文档:http://www.w3school.com.cn/xpath/index.asp
- HTML 可以看做是 XML 的一种实现,所以 Selenium 用户可以使用这种强大的语言在Web应用中定位元素。
xpath路径
- html,xml 中的元素可以嵌套其他元素,但是根元素只有一个。我们可以这种嵌套关系看成路径。路径分绝对路径和相对路径:
- 绝对路径:从根元素到指定元素之间所有经过元素层级路径,绝对路径以 "/" 开始,例如: input 的绝对路径是: /html/body/form/input
- 相对路径:从任何元素开始到该元素的路径,相对路径以 "//" 开始,例如: 用户名输入框标签的相对路径有: //form/input,//body/form/input
xpath 定位
xpath 定位是结合路径来进行定位的,分为绝对定位和相对定位。定位过程中还可以结合元素的属性值。
定位方法是 find_element_by_xpath
纯路径定位
绝对定位: find_element_by_xpath("/html/body/form/input")
相对定位: find_element_by_xpath("//div/ul/li/a")
结合属性
单个属性: find_element_by_xpath("//input[@type='text']")
多个属性: driver.find_element_by_xpath("//input[@type='text' and @name='username']")
选择上一级元素
find_element_by_xpath("//input/..") 返回的是 form 元素
满足条件的多个元素,选择其中一个
driver.find_element_by_xpath("//ul/li") 有多个 li 满足条件,选择其中一个,通过下标来完成,下标从 1 开始
driver.find_element_by_xpath("//ul/li[1]")
可以结合特殊方法 last() 从后面开始选择 ,比如 //ul/li[last()] 选择最后一个 //ul/li[last()-1] 倒数第二个
from selenium.webdriver import Chrome
import traceback
# 通过指定chromedriver的路径来实例化driver对象
driver = Chrome(executable_path='./chromedriver')
# 控制浏览器访问url地址
# file://{本地文件绝对路径}
driver.get('file:///home/python/code/unit_testing/selenium_code/test.html') # 打开本地 html 文件
try:
print(driver.find_element_by_xpath('/html/body/form/input'))
print(driver.find_element_by_xpath('//div/ul/li'))
print(driver.find_element_by_xpath('//form/input[@name="password"]'))
print(driver.find_element_by_xpath('//form/input[@name="password2" and @type="text"]'))
print(driver.find_element_by_xpath('//li/..'))
print(driver.find_element_by_xpath('//ul/li[1]'))
print(driver.find_element_by_xpath('//ul/li[last()]'))
print(driver.find_element_by_xpath('//ul/li[last()-1]'))
except Exception:
print(traceback.format_exc())
finally:
# 退出浏览器
driver.quit()
CSS 方式
CSS 选择器
在Selenium中也可以使用这种选择器,通过 find_element_by_css_selector
:
- 在selenium中极力推荐CSS定位,因为它比XPath定位速度要快
- CSS 选择器语法非常强大,在这里我们只学习在测试中常用的几个
选择器 | 例子 | 描述 |
---|---|---|
#id | #userA | id选择器,选择id="userA"的所有元素 |
.class | .telA | class选择器,选择class="telA"的所有元素 |
element | input | 选择所有input元素 |
[attribute=value] | [type="password"] | 选择type="password"的所有元素 |
element>element | p>input | 选择所有父元素为p元素的input元素 |
driver.find_element_by_css_selector('#username') # 通过 id
driver.find_element_by_css_selector('.input-text') # 通过 class
driver.find_element_by_css_selector('form') # 通过标签名
driver.find_element_by_css_selector('input[type="password"]') # 通过标签属性
driver.find_element_by_css_selector('div>ul') # 通过父子元素
查询多个元素
- 通过 id 属性定位 : find_elements_by_id
- 通过 name 属性定位 : find_elements_by_name
- 通过 class 属性定位 : find_elements_by_class_name
- 通过标签名定位 : find_elements_by_tag_name
- 通过内容定位 a 标签(绝对匹配) : find_elements_by_link_text
- 通过内容定位 a 标签(模糊匹配) : find_elements_by_partial_link_text
- 通过 xpath : find_elements_by_xpath
- 通过 CSS 选择器: find_elements_by_css_selector
和选择单个元素的字面区别就是多了个 s。
调用这类方法,会返回一个列表,没有找到元素则返回空列表,查找单个元素的方法会在找不到元素时抛出 NoSuchElementException 异常
driver.find_elements_by_id('#no-exist-id') # 返回空数组
driver.find_elements_by_tag_name('li') # 返回数组多个元素
什么是元素等待?
概念:WebDriver定位页面元素时如果未找到,会在指定时间内一直等待的过程。
为什么要设置元素等待?
当使用脚本定位元素或去验证程序的运行状态时,由于资源受限或网络延迟引起的响应速度太慢,导致要定位的元素还未加载到页面。
例如:页面是通过 Ajax 发起请求,但是网络有延迟,提交按钮点击完后,页面等待服务器的返回结果来更新页面,那么在这期间,测试代码是不能够直接去查找预期的元素的。
元素等待类型
显式等待
隐式等待
显式等待
概念:使 WebDriver 等待某个条件成立,否则在达到最大时长时抛出超时异常(TimeoutException)
WebDriverWait 类
from selenium.webdriver.support.wait import WebDriverWait
参数:
- driver: webdriver对象
- timeout: 等待多长时间
- poll_frequency: 每次执行失败时休眠多长时间
调用方法
WebDriverWait.util(method, message=''):
参数说明:
- method 函数,这个函数必须定义一个参数,接受 driver 对象。例如: def contain_title(driver)
- message 如果等待失败,message 作为消息抛出
返回值:如果找到,返回找到元素的对象
from selenium.webdriver import Chrome
import traceback
from selenium.webdriver.support.wait import WebDriverWait
driver = Chrome('./chromedriver')
# 3. 打开网址
# file://{本地网址绝对路径}
driver.get('http://www.baidu.com')
try:
# time.sleep(2)
# 1. 指定最长的等待时间,指定检测until函数的时间
# driver对象,最长等待5s, 如果没有找到,每隔0.5s, 检测until()指定的函数,如果5s都没有找到,抛出异常
wait_driver = WebDriverWait(driver, 5, 0.5)
# WebDriverWait.until(), 需要传入一个函数名, 这个函数,参数为Chrome类型
el = wait_driver.until(lambda temp: temp.find_element_by_tag_name('html'))
print(el)
except Exception as e:
# print(e) # 只打印错误信息
print(traceback.format_exc()) # 有错误路径显示
finally:
# 不管有没有异常,都保证driver可以关闭
driver.quit()
隐式等待
隐式等待调用方法
driver.implicitly_wait(10)
隐式等待执行-说明
如果定位某一元素定位失败,那么就会触发隐式等待有效时长,如果在指定时长内加载完毕,则继续执行,否则抛出 NoSuchElementException 异常。
from selenium.webdriver import Chrome
from selenium.webdriver.support.wait import WebDriverWait
import traceback
import time
# 通过指定chromedriver的路径来实例化driver对象
driver = Chrome(executable_path='./chromedriver')
# 控制浏览器访问url地址
driver.get('https://www.baidu.com')
driver.implicitly_wait(5) # 隐式等待
try:
driver.find_element_by_id('kw')
except Exception as e:
print('type = ', type(e))
# print(traceback.format_exc())
finally:
# 退出浏览器
driver.quit()
网友评论