Selenium 是一个 Web 的自动化测试工具,类型像我们玩游戏用的按键精灵,它支持所有主流的浏览器(包括 PhantomJS 这些无界面的浏览器)。Selenium 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截 屏,或者判断网站上某些动作是否发生。
举个栗子:
乘客:他告诉司机去哪里,大概怎么走
司机:他按照乘客的要求来操控出租车
出租车:安装司机的操作完成行驶,把乘客送到目的地
工程师写的自动化测试代码:发送请求给浏览器驱动
浏览器驱动:解析自动化测试代码,解析后发给浏览器
浏览器:执行浏览器发来的指令,完成工程师想要的操作
API-----------驱动-----------浏览器
[ C/S架构 ]
[ HTTP协议 ]
驱动Server监听API的HTTP请求,收到请求后操控对应的浏览器
浏览器执行具体的测试步骤,将步骤执行结果返回给HTTP server
HTTP server又将2结果返回给Selenium的脚本。
WebDriver的协议
WebDriver使用的协议是:JSON Wire protocol
通信的数据格式是JSON
其实就是在HTTP协议之上封装了一层协议,使其能够识别多种Selenium脚本
【1】单元素查找('结果为1个节点对象')
1.1) 【最常用】browser.find_element_by_id('id属性值')
1.2) 【最常用】browser.find_element_by_name('name属性值')
1.3) 【最常用】browser.find_element_by_class_name('class属性值')
1.4) 【最万能】browser.find_element_by_xpath('xpath表达式')
1.5) 【匹配a节点时常用】browser.find_element_by_link_text('链接文本')
1.6) 【匹配a节点时常用】browser.find_element_by_partical_link_text('部分链接文本')
1.7) 【最没用】browser.find_element_by_tag_name('标记名称')
1.8) 【较常用】browser.find_element_by_css_selector('css表达式')
【2】多元素查找('结果为[节点对象列表]')
2.1) browser.find_elements_by_id('id属性值')
2.2) browser.find_elements_by_name('name属性值')
2.3) browser.find_elements_by_class_name('class属性值')
2.4) browser.find_elements_by_xpath('xpath表达式')
2.5) browser.find_elements_by_link_text('链接文本')
2.6) browser.find_elements_by_partical_link_text('部分链接文本')
2.7) browser.find_elements_by_tag_name('标记名称')
2.8) browser.find_elements_by_css_selector('css表达式')
【3】注意
当属性值中存在 空格 时,我们要使用 . 去代替空格
页面中class属性值为: btn btn-account
driver.find_element_by_class_name('btn.btn-account').click()
# | 属性 | 属性描述 |
---|---|---|
1 | driver.name | 浏览器名称 |
2 | driver.current_url | 当前url |
3 | driver.title | 当前页面标题 |
4 | driver.page_source | 当前页面源码 |
5 | driver.current_window_handle | 窗口句柄 |
6 | driver.window_handles | 当前窗口所有句柄 |
7 | driver.back() | 后退 |
8 | driver.forward() | 前进 |
9 | driver.refresh() | 刷新 |
10 | driver.close() | 关闭当前窗口 |
11 | driver.quit() | 退出浏览器 |
12 | driver.switch_to.frame() | 切换到frame |
13 | driver.switch_to.alert | 切换到alert |
14 | driver.switch_to.active_element | 切换到活动元素 |
# | 属性 | 属性描述 |
---|---|---|
1 | id | 标示 |
2 | size | 宽高 |
3 | rect | 宽高和坐标 |
4 | tag_name | 标签名称 |
5 | text | 文本内容 |
# | 方法 | 方法描述 |
---|---|---|
1 | send_key() | 输入内容 |
2 | clear() | 清除内容 |
3 | click() | 单击 |
4 | get_attribute() | 获得属性值 |
5 | is_selected() | 是否被选中 |
6 | is_enabled() | 是否可用 |
7 | is_displayed() | 是否显示 |
8 | value_of_css_property() | css属性值 |
print(e.get_attribute('type')) # text
print(e.get_attribute('name'))
print(e.get_attribute('value'))
流程:
下拉列表需要用到Selenium一个工具类Select
# | 方法/属性 | 方法/属性描述 |
---|---|---|
1 | select_by_value() | 根据值选择 |
2 | select_by_index() | 根据索引选择 |
3 | select_by_visible_text() | 根据文本选择 |
4 | select_by_value | 根据值反选 |
5 | select_by_index | 根据索引反选 |
6 | select_by_visible_text | 根据文本反选 |
7 | deselect_all | 反选所有 |
8 | options | 所有选项 |
9 | all_selected_options | 所有选中选项 |
10 | first_selected_option | 第一个选择选项 |
alert:用来提示
confirm:用来确认
prompt:输入内容
# | 方法/属性 | 方法/属性描述 |
---|---|---|
1 | accept() | 接受 |
2 | dismiss() | 取消 |
3 | text | 显示的文本 |
4 | send_keys | 输入内容 |
WebDriverWait是selenium提供得,显式等待模块引入路径
from selenium.webdriver.support.wait import WebDriverWait
WebDriverWait参数
# | 参数 | 参数说明 |
---|---|---|
1 | driver | 传入WebDriver实例 |
2 | timeout | 超时时间,等待的最长时间 |
3 | poll_frequency | 调用until或until_not的方法的间隔时间,默认0.5秒 |
4 | ignored_exceptions | 忽略的异常 |
WebDriver方法
# | 参数 | 参数说明 |
---|---|---|
1 | method | 在等待时间,每隔一段时间调用这个传入的方法,知道返回值不是False |
2 | message | 如果超时,抛出TimeoutException,将message传入异常 |
ps:如果同时设置几个等待方法,谁超时时间长,谁生效
exp:
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver
from time import sleep
from selenium.webdriver.support.wait import WebDriverWait
class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.get('http://www.baidu.com')
def test_wait(self):
wait = WebDriverWait(self.driver, 2)
# 等待2秒钟,0.5秒轮训,2秒未能找到标题,则抛出异常
wait.until(EC.title_is('百度一下,你就知道'))
self.driver.find_element_by_id('kw').send_keys('selenium')
self.driver.find_element_by_id('su').click()
self.driver.quit()
if __name__ == '__main__':
case = TestCase()
case.test_wait()
from selenium.webdriver.support import expected_conditions as EC
等待条件
from selenium import webdriver
from time import sleep
class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.get("http://www.baidu.com")
def test4(self):
self.driver.find_element_by_id("kw").send_keys("selenium")
self.driver.find_element_by_id("su").click()
sleep(2)
js = 'window.scrollTo(0,document.body.scrollHeight)'
self.driver.execute_script(js)
sleep(2)
self.driver.quit()
if __name__ == '__main__':
case = TestCase()
case.test4()
WebDriver内置了一些在测试中捕获屏幕并保存的方法:
# | 方法 | 方法描述 |
---|---|---|
1 | save_screenshot(filename) | 获取当前屏幕截图并保存为指定文件,filename指指定保存的路径或者图片的文件名 |
2 | get_screenshot_as_base64() | 获取当前屏幕截图base64编码字符串 |
3 | get_screenshot_as_file(filename) | 获取当前的屏幕截图,使用完整路径 |
4 | get_screenshot_as_png() | 获取当前屏幕截图的二进制文件数据 |
from selenium import webdriver
from time import sleep, time, strftime, localtime
class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.get("http://www.baidu.com")
def test1(self):
self.driver.find_element_by_id("kw").send_keys('selenium')
self.driver.find_element_by_id('su').click()
sleep(2)
# 以截屏时间为文件名存储
# self.driver.save_screenshot('baidu.png')
# st = strftime("%Y-%m-%d_%H-%M-%S", localtime(time()))
# file_name = st + '.png'
# self.driver.save_screenshot(file_name)
# 存储至指定文件夹
st = strftime("%Y-%m-%d_%H-%M-%S", localtime(time()))
file_name = st + '.png'
path = os.path.abspath('scrennshot')
file_path = path + '\\' + file_name
print(file_path)
self.driver.get_screenshot_as_file(file_path)
if __name__ == '__main__':
case = TestCase()
case.test1()
# | 方法 | 方法描述 |
---|---|---|
1 | switch_to.frame(reference) | 切换frame,reference是传入的参数,用来定位frame,可以传入id、name、index以及selenium的WebElement对象 |
2 | switch_to.default_content() | 返回主文档 |
3 | switch_to.parent_frame() | 返回父文档 |
from selenium import webdriver
from time import sleep
class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.get("http://sahitest.com/demo/framesTest.htm")
def test1(self):
top = self.driver.find_element_by_name('top')
self.driver.switch_to.frame(top)
self.driver.find_element_by_xpath('/html/body/table/tbody/tr/td[1]/a[1]').click()
self.driver.switch_to.default_content()
second = self.driver.find_element_by_xpath('/html/frameset/frame[2]')
self.driver.switch_to.frame(second)
self.driver.find_element_by_xpath('/html/body/table/tbody/tr/td[1]/a[2]').click()
if __name__ == '__main__':
case = TestCase()
case.test1()
from selenium import webdriver
options = webdriver.ChromeOptions()
# 添加无界面参数
options.add_argument('--headless')
browser = webdriver.Chrome(options=options)
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
#参数数字为像素
print("设置浏览器480宽,800高")
driver.set_window_size(480,800)
driver.quit()
Selenium IDE是Selenium提供的一个浏览器插件,支持Chrome和Firefox浏览器。可以实现Web自动化测试的录制和回放,还可以生产自动化测试脚本。对于初学者学习Selenium编程和回归测试都很有帮助
解决方案一:
使用pytesseract模块和PIL模块解决
只能处理非常简单的图片验证码
解决方案二:
使用第三方API处理验证码
万维易源:https://www.showapi.com/
图片验证码识别:https://www.showapi.com/apiGateway/view/184/