文章目录
本文是自己近期学习selenium过程中的一个归纳总结,在学习过程中重点借鉴了《Python+Selenium基础入门及实践》:https://www.jianshu.com/p/1531e12f8852
当然现在也只是初步接触selenium,其中还有很多知识点需要进一步学习和实践。
也是希望通过本篇学习笔记给更多刚接触selenium的小伙伴带来一些帮助。
一、selenium简介
selenium是一个关于web的自动化测试工具。而对于我们非专业人士来说,可以利用selenium帮助我们完成很多在浏览器上的自动化操作,从而方便我们的生活和工作。
selenium具有以下特点:
- 支持多语言:C、java、python、ruby等
- 支持多主流浏览器:IE、Firefox、Safari、Opera、Chrome
- 支持多平台:Windows、MAC、Linux
——
二、selenium+python环境配置
简单三步走:安装selenium→下载webdriver→安装webdriver
1. 打开命令行,安装selenium
- window:pip install selenium
- MAC:pip3 install selenium
2. 下载webdriver
不同浏览器要安装对应的webdriver才可以,各大浏览器webdriver地址可参见:https://docs.seleniumhq.org/download/
3. webdriver安装路径(一定要安装对头)
Win:复制webdriver到Python安装目录下
Mac:复制webdriver到/usr/local/bin目录下
——
三、浏览器基本操作
1、启动浏览器
01 直接启动浏览器
在这里我们以Chrome浏览器为例,只需要简单三行代码,即可通过Python启动Chrome浏览器并访问百度官网
from selenium import webdriver # 从selenium库中导入webdriver模块
browser = webdriver.Chrome() # 调用Chrome浏览器
browser.get('http://www.baidu.com/') #请求网址:www.baidu.com
02 加载配置启动Chrome
通过以上方式利用selenium操作浏览器是不会加载任何个人配置的,如果你想在浏览器打开时同时加载个人配置,那么可以采取以下方式:
- 先在Chrome地址栏输入chrome://version/,查看自己的“个人资料路径”
- 在Python中写入程序代码如下:
from selenium import webdriver # 从selenium库中导入webdriver模块
option = webdriver.ChromeOptions() # 调用Chrome浏览器设置
option.add_argument(r'--user-data-dir=C:\Users\29685\AppData\Local\Google\Chrome\User Data\Default') # 添加浏览器设置路径
browser = webdriver.Chrome(chrome_options=option) # 加载配置启动Chrome浏览器
需要注意的是路径设置那块需要使用原始字符串。
2、元素定位
首先你一定得初步了解些HTML和CSS方面的知识。
如同我们通过鼠标和键盘在浏览器中不停进行点击、输入等操作,计算机想要自动进行这些操作那么首先得识别出这些元素才能进行操作。
如同我们每个人都有自己对应的姓名、身份证号、居住地址、电话等属性特征一样,浏览器中的每个元素也都有着各自的相应的属性特征。
我们就可以通过这些属性特征找到这些元素,然后进行一系列的操作。
webdriver 提供了一系列的元素定位方法,常用的有以下几种:
- id定位:find_element_by_id()
- css定位:find_element_by_css_selector()
- name定位:find_element_by_name()
- class定位:find_element_by_class_name()
- link定位:find_element_by_link_text()
- partial link定位:find_element_by_partial_link_text()
- tag定位:find_element_by_tag_name()
- xpath定位:find_element_by_xpath()
元素定位可以通过以上八种方式,就我个人而言,常用的还是id定位和css定位。
3、等待方式
首先搞清楚什么是等待、为什么要等待。
我们浏览器的页面元素加载是一点点加载出来的,这个过程是需要耗费一定时间的。
有时候页面中某个对象还没加载出来,那么程序又自动往下一步执行,由于没能找到相应的对象就有可能导致程序出错。
所以为了保证程序运行的稳定性,需要程序中添加等待时间。
等待的方式有三种:强制等待、隐性等待和显性等待。
01 强制等待
- 使用:需要导入time库,调用方法time.sleep()
- 特点:等待固定时间,再进行下一步操作
- 缺点:只能死板地等待固定时间,严重影响程序执行速度
from selenium import webdriver # 从selenium库中导入webdriver模块
from time # 导入time库
browser = webdriver.Chrome() # 调用Chrome浏览器
browser.get('http://www.baidu.com/') # 请求网址:www.baidu.com
time.sleep(2) # 强制等待2秒,再进行下面的操作
print(browser.current_url) # 打印url
02 隐性等待
- 使用:调用方法implicity_wait(),括号里输入时间
- 特点:设置了一个最长等待时间,页面在最长等待时间内加载完毕即可进行下一步;否则达到最长等待时间后立即执行下一步,比起time.sleep()要稍显灵活
- 缺点:在最长等待时间内,只能等待整个页面加载完毕才能进行下一步
from selenium import webdriver # 从selenium库中导入webdriver模块
browser = webdriver.Chrome() # 调用Chrome浏览器
browser.get('http://www.baidu.com/') # 请求网址:www.baidu.com
browser.implicity_wait(10) # 隐性等待,最长时间为10秒
print(browser.current_url) # 打印url
需要注意的是,隐性等待对整个程序周期都起作用,所以只需设置一次即可。
03 显性等待
如果你希望页面在某些特定元素加载出来后即可进行一步,而非等待整个页面加载完成才进行下一步该如何办?
那么你就需要使用显性等待了,而且是一种超级灵活的等待方式。
同时显性等待的使用方式也会相对复杂许多,我们先来认识下。
导入包
from selenium.webdriver.support.wait import WebDriverWait
参数介绍
(1)driver::传入WebDriver实例,即我们例子中的browser
(2)timeout:超时时间,等待的最长时间(同时要考虑隐性等待时间)
(3)poll_frequency:调用until或until_not中的方法的间隔时间,默认是0.5秒
(4)ignored_exceptions::忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常,则不中断代码,继续等待;如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有NoSuchElementException。
until和until_not方法介绍
(1)method:在等待期间,每隔一段时间(参数中的poll_frequency)调用这个传入的方法,直到返回值不是False
(2)message:如果超时,抛出TimeoutException,将message传入异常
(3)until_not恰恰与until相反,until是当某元素出现或什么条件成立则继续执行;until_not是当某元素消失或什么条件不成立则继续执行,参数也相同。
总结起来调用方法如下:
WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时返回的信息)
- 其中调用频率、忽略异常、超时返回信息为非必须参数
- 可使until和until_not两种方法
显性等待本质上就是通过判断条件的成立或不成立来选择是否继续往下执行
其中要重点说明的是method参数可以使用expected_conditions 模块中的各种条件,或者WebElement的 is_displayed() 、is_enabled()、is_selected()方法,亦或者自己封装的方法。
4、常用浏览器操作
- 浏览器最大化显示:browser.maximize_window()
- 浏览器最小化显示:browser.minimize_window()
- 浏览器设置固定大小:browser.set_window_size(300,500) 宽300,高500
- 浏览器前进:browser.forword() 前进
- 浏览器后退:browser.back() 后退
——
四、键盘和鼠标事件
1、键盘事件
要模拟键盘事件,首先要导入包
from selenium.webdriver.common.keys import Keys
常用模拟键盘输入:
1. send_keys(‘输入的内容’)
2. send_keys(Keys.TAB) ------ TAB键
3. send_keys(Keys.ENTER) ------回车键 可以代替点击登录键
4. send_keys(Keys.SPACE)------空格键
5. send_keys(Keys.BACK_SPACE)-------删除键
组合键用法:
1. send_keys(Keys.CONTROL,‘a’) ----Ctrl+a 全选
2. send_keys(Keys.CONTROL,‘c’) ----Ctrl+c 复制
3. send_keys(Keys.CONTROL,‘v’) ----Ctrl+v 粘贴
其他的组合键可以按照同样的方式进行指定。
2、鼠标事件
要使用鼠标事件,同样需要导入包
from selenium.webdriver.common.action_chains import ActionChains
常用鼠标方法
1. perform() 执行所有ActionChains中存储的行为
2. click() 单击
3. context_click() 右击
4. double_click() 双击
5. drag_and_drop(sourse,target) 拖动
6. move_to_element() 鼠标悬停
7. click_and_hold——点击并按住不放
8. move_by_offset(x,y)——鼠标移动
9. release——释放鼠标
操作示例
dragger = driver.find_element_by_css_selector('.vcode-slide-button') #找到滑块位置
ActionChains(driver).click_and_hold(dragger).perform() #左键点击并按住不放
time.sleep(0.5)
ActionChains(driver).move_by_offset(250, 0).perform() #水平移动
ActionChains(driver).release(dragger).perform() #释放滑块
——
五、多层框架/层级定位
在定位元素过程中,我们经常会遇到这样的情况,明明在浏览器通过查找确定唯一项了,但是在Python中采用该定位方法却怎么也定位不到。
通常找不到元素的问题有三种:
- 页面请求超时
- 元素定位方法不对
- 页面存在iframe或内嵌窗口
其中如果是第三种问题:页面存在iframe或内嵌窗口,那么就需要调用方法:browser.switch_to_frame()或者browser.switch_to_window(),先定位到该框架和窗口下才能定位到指定元素。
如下图所示,通过id=u定位到唯一元素,但是在Python中调用方法find_element_by_id(‘u’),却怎么也找不到该元素。
这就是因为该元素存在于iframe之下,必须调用方法browser.switch_to_frame()
代码如下:
frame1 = driver.find_element_by_id('login_frame') #划重点 必须首先定位到元素所在的frame下
driver.switch_to_frame(frame1)
——
六、Expected Conditions解析
通常来说Expected Conditions使用场景有以下两种:
- 直接在断言中使用
- 与WebDriverWait配合使用,动态等待页面元素出现或消失
使用前同样需要先导入包
from selenium.webdriver.support import expected_conditions as EC
expected_conditions实在有点太长,所以我们可以进行自定义命名为EC
相关方法一览(不过我个人基本没用过…):
- title_is: 判断当前页面的title是否精确等于预期
- title_contains: 判断当前页面的title是否包含预期字符串
- presence_of_element_located:判断某个元素是否被加到了dom树里,并不代表该元素一定可见
- visibility_of_element_located:判断某个元素是否可见.可见代表元素非隐藏,并且元素的宽和高都不等于0
- visibility_of:跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了
- presence_of_all_elements_located:判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是’column-md-3’,那么只要有1个元素存在,这个方法就返回True
- text_to_be_present_in_element:判断某个元素中的text是否包含了预期的字符串
- text_to_be_present_in_element_value:判断某个元素中的value属性是否包含了预期的字符串
- frame_to_be_available_and_switch_to_it:判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False
- invisibility_of_element_located:判断某个元素中是否不存在于dom树或不可见
- element_to_be_clickable:判断某个元素中是否可见并且是enable的,这样的话才叫clickable
- staleness_of:等某个元素从dom树中移除,注意,这个方法也是返回True或False
- element_to_be_selected:判断某个元素是否被选中了,一般用在下拉列表
- element_selection_state_to_be:判断某个元素的选中状态是否符合预期
- element_located_selection_state_to_be:跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator
- alert_is_present:判断页面上是否存在alert
——