
Selenium+Python自动化测试
省略浏览器驱动路径
我们的代码创建 WebDriver对象时,需要指定浏览器驱动路径,比如
from selenium.webdriver.chrome.service import Service
wd = webdriver.Chrome(service=Service(r'd:\tools\chromedriver.exe'))
这样写有几个问题:
一是,比较麻烦, 每次写自动化代码都 要指定路径。
二是,如果你的代码给别人运行,他的电脑上存放浏览器驱动的路径不一定和你一样(比如他的电脑是苹果Mac电脑),得改脚本。
有什么好办法呢?
我们可以把浏览器驱动 所在目录 加入环境变量 Path , 写代码时,就可以无需指定浏览器驱动路径了,像下面这样
wd = webdriver.Chrome()
因为,Selenium会自动在环境变量 Path 指定的那些目录里查找名为chromedriver.exe 的文件。
一定要注意的是, 加入环境变量 Path 的,
不是浏览器驱动全路径,比如 d:\tools\chromedriver.exe
而是 浏览器驱动所在目录,比如 d:\tools
而且设置完环境变量后,别忘了重启IDE(比如 PyCharm) 新的环境变量才会生效。
特别注意:Selenium 升级到版本 4 以后, 下面这种 find_element_by* 方法都作为过期不赞成的写法
# 初始化代码 ....
wd.find_element_by_id('username').send_keys('byhy') wd.find_element_by_class_name('password').send_keys('sdfsdf') wd.find_element_by_tag_name('input').send_keys('sdfsdf') wd.find_element_by_css_selector('button[type=submit]').click()
运行会有告警,所以现在都要写成下面这种格式
from selenium.webdriver.common.by import By
# 初始化代码 ....
wd.find_element(By.ID, 'username').send_keys('byhy')
wd.find_element(By.CLASS_NAME, 'password').send_keys('sdfsdf')
wd.find_element(By.TAG_NAME, 'input').send_keys('sdfsdf')
wd.find_element(By.CSS_SELECTOR,'button[type=submit]').click()
ActionChains类(鼠标操作)
click(on_element=None) --- 鼠标单击
double_click(on_element=None) --- 双击
context_click(on_element=None) --- 右击
click_and_hold(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) --- 在某个元素位置松开鼠标左键
举例:
鼠标右击
from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChains # 引入 ActionChains 类
driver = webdriver.Firefox()
driver.get("http://yunpan.360.cn")
#.......此处省略1W代码,哈哈哈
# 定位到要右击的元素
right_click = driver.find_element
# 对定位到的元素执行鼠标右键操作
ActionChains(driver).context_click(right_click).perform()
#.......(省略其他代码)
1)ActionChains(driver)
调用 ActionChains() 类,将浏览器驱动 driver 作为参数传入。
2)context_click(right_click)
context_click() 方法用于模拟鼠标右击操作,在调用时需要指定元素定位。
3)perform()
执行所有 ActionChains 中存储的行为,可以理解为是对整个操作的提交动作。
下拉框操作
# 1.导入包Select类
from selenium.webdriver.support.select import Select
# 2.定位下拉菜单元素
# 3.把定位的下拉菜单元素存储到Select类中创建下拉框对象
select = Select(下拉菜单元素)
# 4.1 通过value属性来选择,option标签的一个属性值
select.select_by_value('属性值')
# 4.2 通过选项索引(index)值选择 索引从0开始
select.select_by_index(索引值)
# 4.3 通过选项名称选择
select.select_by_visible_text('选择名称')
2、下拉菜单对象的其他操作(了解)
调用方法选择下拉框中的选项
操作 说明
all_selected_options 查看所有已选
first_selected_option 查看第一个已选
is_multiple 查看是否是多选
options 查看选项元素列表
取消选择:
操作说明
deselect_by_value() 通过option标签的value属性来选择
deselect_by_index() 通过选项索引(index)值选择 索引从0开始
deselect_by_visible_text() 通过选项名称选择
对JS元素操作
增加属性
driver.execute_script(“arguments[0].%s=arguments[1]” %attributeName,elementObj, value)
修改属性
driver.execute_script(“arguments[0].setAttribute(arguments[1],arguments[2])”, elementObj, attributeName, value)
获取属性
elementObj.get_attribute(attributeName)
删除属性
driver.execute_script(“arguments[0].removeAttribute(arguments[1])”,elementObj, attributeName)
attributeName 就是属性名字 elementObj 就是元素对象 value 就是值
多窗口切换 window_handles
current_window_handle:获得当前窗口句柄
window_handles:获取所有窗口的句柄到当前会话,返回一个窗口句柄列表
switch_to.window():切换窗口句柄
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
# 获得百度搜索窗口句柄
search_windows = driver.current_window_handle
print(search_windows)
driver.find_element_by_link_text('登录').click()
driver.find_element_by_link_text("立即注册").click()
# 获得当前所有打开的窗口的句柄
all_handles = driver.window_handles
print(all_handles)
# 切换到注册窗口 方式1 通过判断是否与当前窗口句柄一致
for handle in all_handles:
if handle != search_windows:
driver.switch_to.window(handle)
driver.find_element_by_name("userName").send_keys('我是测试小白')
driver.find_element_by_name('phone').send_keys('12345678910')
time.sleep(2)
# 后续步骤省略
# 切换到注册窗口 方式2 通过获取的所有窗口列表的索引切换
# driver.switch_to.window(all_handles[1])
# driver.find_element_by_name("userName").send_keys('我是测试小白')
# driver.find_element_by_name('phone').send_keys('12345678910')
# time.sleep(2)
driver.quit()
三大等待方式
1. 强制等待
方法:sleep(seconds),seconds 等待时间,单位 秒 s
说明:不管浏览器是否加载完了,程序都得等待3秒,不建议使用,严重影响执行速度
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get('https://blog.csdn.net/IT_heima?spm=1001.2014.3001.5343')
sleep(2) # 强制等待2秒再执行下一步
print(driver.current_url)
print(driver.title)
driver.close()
2. 隐式等待
方法:implicitly_wait(time_to_wait) , time_to_wait 等待时间, 单位秒 s
说明:设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步。此方法是全局性的,设置一次即可
弊端:程序会一直等待整个页面加载完成,也就是一般情况下看到浏览器标签栏那个小圈不再转,才会执行下一步,但是页面的元素已加载完,js等未加载完,仍会等待
from selenium import webdriver
driver = webdriver.Chrome()
# 隐式等待,最长等20秒
driver.implicitly_wait(20)
driver.get('https://blog.csdn.net/IT_heima?spm=1001.2014.3001.5343')
print(driver.current_url)
print(driver.title)
driver.close()
3. 显示等待
init方法:__init__(driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None)
driver :浏览器驱动driver :浏览器驱动
timeout :最长超时时间,默认以秒为单位。timeout :最长超时时间,默认以秒为单位。
poll_frequency :检测的间隔(步长)时间,默认为0.5S。
ignored_exceptions :超时后的异常信息,默认情况下抛NoSuchElementException异常。
unit方法:until( method, message='')
method:传入执行的方法
message:超时时的提示信息
until_not方法:同until
使用: WebDriverWait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)
from selenium import webdriver
from selenium.common.exceptions import ElementNotVisibleException
from selenium.webdriver.support.ui import WebDriverWait
driver = webdriver.Chrome()
# 隐式等待,最长等20秒
driver.implicitly_wait(20)
driver.get('http://baidu.com')
print(driver.current_url)
print(driver.title)
# 每隔0.5s去查找元素 kw,超时时间为10s,返回WebElement对象
element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("kw"))
element.send_keys('selenium')
# 每隔1去查找元素 kw是否可见,超时时间为30s,返回结果为布尔值
is_disappeared = WebDriverWait(driver, 30, 1, ElementNotVisibleException).until_not(
lambda x: x.find_element_by_id("kw1").is_displayed())
print(is_disappeared)
# 错误用法 until() 第一个参数应该是方法,此处传入的是WebElement对象,所以不正确,可参照上面的写法
# WebDriverWait(driver, 10).until(driver.find_element_by_id('kw'))
driver.close()
4. 总结
sleep(n):强制等待n秒,影响程序执行速度
implicitly_wait( ):隐式等待,全局性,设置一次即可,针对的是整个页面是否加载完成
WebDriverWait( ):显示等待,针对单个元素判断,灵活
隐式等待和显时等待同时使用时,超时时间取两者最长的
- 感谢你赐予我前进的力量