WebDriver工作原理
- 对于每一条Selenium脚本,一个http请求会被创建并发送给浏览器的驱动
- 浏览器驱动轴包含了一个HTTP Server,用来接收这些http请求
- HTTP Server接收到请求后根据请求来具体操控对应的浏览器
- 浏览器执行具体的测试步骤
- 浏览器将步骤执行结果返回给HTTP Server
- HTTP Server又将结果返回给Selenium的脚本,如果是错误的http代码我们就会在控制台看到对应的报错信息
WebDriver的协议
- WebDriver使用的协议是:JSON Wire protocol
- 通信的数据格式是JSON
WebDriver的属性
属性 | 属性描述 |
driver.name | 浏览器名称 |
driver.current_url | 当前url |
driver.title | 当前页面标题 |
driver.page_source | 当前页面源码 |
driver.current_window_handle | 窗口句柄(相当于一个tab) |
driver.window_handles | 当前窗口所有句柄 |
WebDriver方法
方法 | 方法描述 |
driver.back() | 浏览器后退 |
driver.forward() | 浏览器前进 |
driver.fresh() | 浏览器刷新 |
driver.close() | 关闭当前窗口 |
driver.quit() | 退出浏览器 |
driver.switch_to.frame() | 切换到frame |
driver.switch_to.alert | 切换到alert |
driver.switch_to.active_element | 切换到活动元素 |
driver.switch_to.window | 切换窗口 |
WebElement属性
当我们使用WebDriver的find方法定位到元素后,会返回一个WebElement对象,该对象用来描述Web页面上的一个元素.WebElement的常用属性和方法见下表
属性 | 属性描述 |
id | 标识 |
size | 宽高 |
rect | 宽高和坐标 |
tag_name | 标签名称 |
text | 文本内容 |
WebElement方法
方法 | 方法描述 |
send_keys() | 输入内容 |
clear() | 清空内容 |
click() | 单击 |
get_attribute() | 获得属性值 |
is_selected() | 是否被选中 |
is_enabled() | 是否可用 |
is_displayed() | 是否显示 |
value_of_css_property() | css属性值 |
操作下拉列表
处理下拉列表,需要用到selenium中的一个工具类Select,工具位置 from selenium.webdriver.support.select import Select,使用方法
def test_select(self): se = self.driver.find_element_by_id('province') select =Select(se) select.select_by_index(2) sleep(2) select.select_by_value('bj') sleep(2) select.select_by_visible_text('上海')
select常见方法
方法/属性 | 描述 |
select_by_value() | 根据源码value选择 |
select_by_index() | 根据索引选择 |
select_by_visible_text() | 根据文本选择 |
deselect_by_value() | 根据源码value反选 |
deselect_by_index() | 根据索引反选 |
deselect_by_visible_text() | 根据文本反选 |
deselect_all | 反选所有 |
options | 返回包含所有选项的列表 |
all_selected_options | 所有已选中选项 |
first_selected_option | 第一个选择选项 |
处理弹框
页面上的弹框有三种
- alert:用来提示
- confirm:用来确认
- prompt:输入内容
方法/属性 | 描述 |
accept() | 接受 |
dismiss() | 取消 |
text | 弹框的文本 |
send_keys | 输入内容 |
selenium的三种等待方式
- time.sleep(sec) 固定等待,不推荐实际测试时使用,可以用来调试
- implicitly_wait 如果某些元素不是立即可用的,隐式等待是告诉WebDriver去等待一定的时间后去查找元素。默认等待时间是0秒,一旦设置该值,隐式等待是设置该WebDriver的实例的生命周期
- WebDriverWait 显式等待是你在代码中定义等待一定条件发生后再进一步执行你的代码,推荐用此方法
显式等待使用方法
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions
def test_wait(self):
wait = WebDriverWait(self.driver, 2)
wait.until(expected_conditions.title_contains('百度一下'))
self.driver.find_element_by_id('kw').send_keys('selenium')
WebDriverWait参数:
- driver:传入WebDriver实例,即我们上例中的driver
- timeout:超时时间,等待的最长时间
- poll_frequency:调用until或until_not中的方法的间隔时间,默认是0.5秒
- ignored_exceptions:忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常,则不中断代码,继续等待,如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有NoSuchElementException。
这个模块中,一共只有两种方法 until 与 until_not:
- until:当某元素出现或什么条件成立则继续执行
- until_not:当某元素消失或什么条件不成立则继续执行
until 与 until_not 参数如下:
- method:在等待期间,每隔一段时间调用这个传入的方法,直到返回值不是False
- message:如果超时,抛出TimeoutException,将message传入异常
WebDriverWait的17种等待条件
条件 | 描述 | 返回值 |
titile_is | 判断title,是否出现 | 布尔 |
title_contains | 判断title,是否包含某些字符 | 布尔 |
presence_of_element_located | 判断某个元素是否被加到了dom树里, 并不代表该元素一定可见 |
WebElement |
visibility_of_element_located | 判断某个元素是否被加到了dom树里, 并且可见,宽和高都大于0 |
WebElement |
visibility_of | 判断元素是否可见,如果可见就返回这个元素 | WebElement |
presence_of_all_element_located | 判断是否至少有1个元素存在于dom树中 | 列表 |
visibility_of_any_element_located | 判断是否至少有1个元素在页面中可见 | 列表 |
text_to_be_present_in_element | 判断指定的元素中是否包含了预期的字符串 | 布尔 |
text_to_be_present_in_element_value | 判断指定元素的属性值中是否包含了预期的 字符串 |
布尔 |
frame_to_be_available_and_switch_to_it | 判断frame是否可以switch进去 | 布尔 |
invisibility_of_element_located | 判断某个元素是否存在于dom或不可见 | 布尔 |
element_to_be_clickable | 判断某个元素中是否可见并且是enable的,代表可点击 | 布尔 |
staleness_of | 等待某个元素从dom树中移除 | 布尔 |
element_to_be_selected | 判断某个元素是否被选中了,一般用在下拉列表 | 布尔 |
element_selection_state_to_be | 判断某个元素的选中状态是否符合预期 | 布尔 |
element_located_selection_state_to_be | 判断某个元素的选中状态是否符合预期 | 布尔 |
alert_is_present | 判断页面上是否存在alert | alert |
Selenium鼠标和键盘事件
selenium中的鼠标和键盘事件被封装在ActionChains类中,正确的使用方法是:
ActionChains(driver).click(button).perform()
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) | 发送某个键到指定元素 |
代码演示
def test_mouse(self): btn=self.driver.find_element_by_xpath('/html/body/form/input[2]') #双击 ActionChains(self.driver).double_click(btn).perform() sleep(2) btn = self.driver.find_element_by_xpath('/html/body/form/input[3]') #单击 ActionChains(self.driver).click(btn).perform() sleep(2) btn = self.driver.find_element_by_xpath('/html/body/form/input[4]') #右击 ActionChains(self.driver).context_click(btn).perform() sleep() def test_key(self): self.driver.get('http://www.baidu.com') kw=self.driver.find_element_by_id('kw') kw.send_keys('selenium') #按下control+a全选 kw.send_keys(Keys.CONTROL,'a') sleep(2) # 按下control+x剪切 kw.send_keys(Keys.CONTROL,'x') sleep(2) # 按下control+v粘贴 kw.send_keys(Keys.CONTROL,'v') sleep(2)
Selenium屏幕截图
WebDriver内置了一些在测试中捕获屏幕并保存的方法
方法 | 方法描述 |
save_screenshot(filename) | 获取当前屏幕截图并保存当当前目录 |
get_screenshot_as_base64() | 获取当前屏幕截图base64编码字符串 |
get_screenshot_as_file(filename) | 获取当前的屏幕截图,使用完整的路径 |
get_screenshot_as_png() | 获取当前屏幕截图的二进制文件数据 |
代码示例
def test(self): self.driver.find_element_by_id('kw').send_keys('selenium') self.driver.find_element_by_id('su').click() sleep(2) self.driver.get_screenshot_as_file('d:/baidu.png') self.driver.quit()
Selenium定位frame ifame
frame标签有frameset,frame,iframe三种,framset跟其他普通标签没有区别,不会影响到正常的定位,而frame与iframe堆selenium定位而言是一样的,selenium有一组方法对frame进行操作.
方法 | 方法描述 |
switch_to_frame(reference) | 切换frame,,reference是传入的参数,用来定位frame,可以传入id,name,index 以及selenium的WebDriver对象 |
switch_to.default_content() | 返回主文档 |
switch_to.parent_frame() | 返回父文档 |
时间控件操作
通过js脚本实现
driver.get("https://www.12306.cn/index/") js = "document.getElementById('train_date').removeAttribute('readonly')" driver.execute_script(js) driver.find_element_by_id("train_date").clear() driver.find_element_by_id("train_date").send_keys("2020-10-16")