本文总结使用selenium进行web/UI自动化时,会用到的一些常用操作。
定位元素
driver.find_element_by_xpath()#1、绝对路径 2、元素属性 3、层级和属性结合 4、使用逻辑运算符
driver.find_element_by_id()#根据id定位,HTML规定id属性在HTML文档中必须是唯一的
driver.find_element_by_name()#name属性定位
driver.find_element_by_class_name()#class属性定位
driver.find_element_by_tag_name()#标签名字定位 因为标签基本都不是唯一的,所以不用这个
driver.find_element_by_link_text()#定位文本链接,需要对应的元素有href属性
driver.find_element_by_partial_link_text()#模糊定位文本链接
driver.find_element_by_css_selector()#CSS选择器
By定位元素
是元素定位另外一种方式,跟上面的8种底层一样。
1
2
from
selenium.webdriver.common
import
By
driver.find_element(By.
ID
,
'kw'
)
定位一组元素
1
2
driver.find_elements_by_xpath()
#其他方法同理
driver.find_elements(By.XPATH,'')
浏览器操作
driver.set_window_size()#设置浏览器大小,可以设置成移动端大小
driver.back()#浏览器后退
driver.forward()#浏览器前进
driver.set_window_position()
driver.set_window_rect()
driver.refresh()#模拟浏览器刷新
driver.maximize_window()#最大化浏览器
设置浏览器参数
在定义driver的时候设置chrome_options参数,该参数是一个Options类所实例化的对象。其中,常用的参数是设置浏览器是否可视化和浏览器的请求头等信息,前者可以加快代码的运行速度,后者可以有效地防止网站的反爬虫检测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from
selenium.webdriver.chrome.options
import
Options
url
=
'https://movie.douban.com/'
#Options类实例化
chrome_options
=
Options()
#设置浏览器参数
#--headless是不 显示浏览器启动和执行过程c
chrome_options.add_argument(
'--headless'
)
#设置lang和User-Agent信息,防止反爬虫检测
chrome_options.add_argument(
'lang=zh_CN.UTF-8'
)
UserAgent
=
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.101 Safari/537.36'
chrome_options.add_argument(
'User-Agent='
+
UserAgent)
#启动浏览器并设置chrome_options参数
driver
=
webdriver.Chrome(options
=
chrome_options)
driver.get(url)
driver.maximize_window()
print
(driver.title)
# print(driver.page_source) #获取网页的html代码
元素操作
driver.find_element_by_xpath().click()#点击元素
driver.find_element_by_xpath().clear()#清空文本
driver.find_element_by_xpath().send_keys()#模拟键盘输入
页面交互
webElement接口提供了一些可以与页面交互的方法
submit和click在某些情况下可以互换,submit只用于表单的提交按钮。
driver.find_element_by_xpath().submit()#提交输入框的内容 类似于回车提交搜索框内容
driver.find_element_by_xpath().size#返回元素尺寸
driver.find_element_by_xpath().text#获取元素文本
driver.find_element_by_xpath().get_attribute()#获取元素属性值
driver.find_element_by_xpath().is_selected()#是否被选中
driver.find_element_by_xpath().is_enabled()#判断元素是否可以使用
driver.find_element_by_xpath().is_displayed()#返回元素是否用户可见
鼠标事件
关于鼠标操作的方法都封装在Actionchains中
from selenium.webdriver.common.action_chains import ActionChains
rigt_check=driver.find_element_by_id('kw')
ActionChains(driver).context_click(rigt_check).perform()#context_click对元素右击操作
#perform()执行所有ActionChains中存储的行为
ActionChains(driver).move_to_element(rigt_check).perform()#鼠标悬停
ActionChains(driver).double_click(rigt_check).perform()#鼠标双击
ActionChains(driver).drag_and_drop(source,target).perform()#鼠标由源元素拖动至目标元素
1
2
3
4
5
6
7
8
9
10
11
url
=
'https://passport.bilibili.com/login'
driver
=
webdriver.Chrome()
driver.get(url)
#双击登录按钮
ele
=
driver.find_element_by_class_name(
'tit'
)
ActionChains(driver).double_click(ele).perform()
sleep(
2
)
#拖拽滑块
ele
=
driver.find_element_by_class_name(
'gt_slider_knob,gt_show'
)
ActionChains(driver).drag_and_drop_by_offset(ele,
100
,
0
).perform()
键盘事件
模拟键盘输入,可以是按键,组合键。
from selenium.webdriver.common.keys import Keys
driver.find_element_by_xpath().send_keys(Keys.BACK_SPACE)#对该元素操作一次backspace
driver.find_element_by_xpath().send_keys(Keys.SPACE)#对该元素输入空格
driver.find_element_by_xpath().send_keys(Keys.CONTROL,'a')#ctrl+A全选输入框内容
driver.find_element_by_xpath().send_keys(Keys.CONTROL,'x')#ctrl+x剪切输入框内容
driver.find_element_by_xpath().send_keys(Keys.CONTROL,'v')#ctrl+v粘贴内容到输入框
driver.find_element_by_xpath().send_keys(Keys.ENTER)#通过回车键代替单击操作
driver.find_element_by_xpath().send_keys(Keys.F1)#键盘F1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from
selenium
import
webdriver
from
selenium.webdriver.common.action_chains
import
ActionChains
from
selenium.webdriver.common.keys
import
Keys
from
selenium.webdriver.common.by
import
By
from
time
import
sleep
url
=
'https://www.baidu.com'
driver
=
webdriver.Chrome()
driver.get(url)
ele
=
driver.find_element_by_id(
'kw'
)
ele.send_keys(
"selenium"
)
sleep(
2
)
#删除最后一个文字
ele.send_keys(Keys.BACK_SPACE)
sleep(
2
)
#添加空格键+教程
ele.send_keys(Keys.SPACE)
ele.send_keys(
"教程"
)
sleep(
2
)
#ctrl+a全选输入框内容
ele.send_keys(Keys.CONTROL,
'a'
)
sleep(
2
)
#ctrl+x 剪切输入框内容
ele.send_keys(Keys.CONTROL,
'x'
)
sleep(
2
)
#ctrl+v 粘贴内容到输入框
ele.send_keys(Keys.CONTROL,
'v'
)
sleep(
2
)
#回车键代替单击
driver.find_element_by_id(
'su'
).send_keys(Keys.ENTER)
获得验证信息
自动化用例执行完成后,可以从页面上获取一些信息来证明用例执行成功或者失败
driver.title #获得页面title
driver.current_url#获得页面curl
driver.find_element_by_xpath().text#获取元素文本
元素等待
由于web页面多数使用AJAX技术,浏览器在加载页面时,页面上的元素可能不是同时被加载完成的,需要加入等待。
显式等待:显性等待能够根据判断条件而灵活地等待,程序每隔一段时间检测一次,如果检测结果与条件相符,就执行下一步,否则继续等待,直到超过设置的最长时间为止
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element=WebDriverWait(driver,5,0.5).until(EC.presence_of_element_located(By.ID,'kw'))
#每0.5秒检测一次这个元素能否被定位到,5秒后超时
#expected_conditions提供了很多预期条件判断方法
#也可以用is_displayed()判断元素是否可见
隐式等待
隐性等待是指在一个设定的时间内检测网页是否加载完成,也就是一般情况下用户看到浏览器标签栏那个小圈不再转,才会执行下一步。比如代码中设置30秒等待时间,网页只要在30秒内完成加载就会自动执行下一步,如果超出30秒就会抛出异常。值得注意的是,隐性等待对整个driver的周期都起作用,所以只要设置一次即可。
通过一定的时长等待页面上某元素加载完成,如果超出了设置的时长元素,还没有被加载,则抛出没有元素异常。
通常设置在driver后面。
driver.implicitly_wait(10)
sleep休眠方法
在需要的地方添加。
1
2
from
time
import
sleep
sleep(
3
)
隐性等待和显性等待相比于time.sleep这种强制等待更为灵活和智能,可解决各种网络延误的问题,隐性等待和显性等待可以同时使用,但最长的等待时间取决于两者之间的最大数,如上述代码的隐性等待时间为30秒,显性等待时间为20秒,则该代码的最长等待时间为隐性等待时间。
多框架切换
frame是一个框架页面,在HTML 5中已经不支持使用框架,但在一些网站中依然会看到它的身影。frame的作用是在HTML代码中嵌套一个或多个不同的HTML代码,每嵌套一个HTML代码都需要由frame来实现
iframe和frame实现的功能是相同的,只不过使用方式和灵活性有所不同,无论是iframe还是frame,Selenium的定位和操作方式都是一样的
由于一个HTML可以嵌套一个或多个iframe,因此Selenium在操作不同的iframe时需要通过switch_to.frame()来切换到指定的iframe,再执行相应的操作
driver.switch_to.frame('kw')#可以直接取表单的id或者name属性,如果表单没有这两个属性,可以先定位表单元素,再切换
driver.switch_to.parent_frame('kw')#跳出当前一级表单
driver.switch_to.default_content('kw')#跳回最外层页面
#根据索引定位
driver.switch_to_frame(0)
#根据id或者name属性
driver.switch_to_frame('framea')
新版本 driver.switch_to.frame(0)
如百度知道的文本框
如下代码实现打开百度知道题目页面,点击我要回答,定位至iframe,输入内容,跳出iframe,并点击提交回答按钮
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
url
=
'https://zhidao.baidu.com/question/1903337615241287780.html'
driver
=
webdriver.Chrome()
driver.get(url)
driver.maximize_window()
#点击我要回答
driver.find_element_by_id(
'answer-bar'
).click()
#切换到frame内部的html
driver.switch_to.frame(
'ueditor_0'
)
#定位frame内部的元素
driver.find_element_by_xpath(
'/html/body'
).send_keys(
'美国'
)
#跳回网页HTML 如果不切回网页,则找不到提交回答按钮,且js代码也执行不了
# driver.switch_to.default_content()
js
=
'window.scrollTo(0,100)'
driver.execute_script(js)
sleep(
3
)
#点击网页提交回答按钮
driver.find_element_by_xpath(
"//div[@class='addons line']/a"
).click()
多窗口切换
search_windows=driver.current_window_handle #获得当前窗口句柄
all_handles=driver.window_handles #获得所有窗口的句柄
driver.switch_to.window(handle)#切换窗口
handles=driver.window_handles
driver.switch_to_window(handles[0])
driver.switch_to_window(handles[1])
应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from
selenium
import
webdriver
from
selenium.webdriver.common.by
import
By
url
=
'https://www.baidu.com/'
driver
=
webdriver.Chrome()
driver.get(url)
driver.implicitly_wait(
10
)
search_windows
=
driver.current_window_handle
#获得窗口句柄
driver.find_element_by_link_text(
'登录'
).click()
driver.find_element_by_link_text(
'立即注册'
).click()
import
time
#获得所有窗口的句柄
all_handles
=
driver.window_handles
#切换到注册窗口
for
handle
in
all_handles:
if
handle!
=
search_windows:
driver.switch_to.window(handle)
print
(
"当前是注册窗口"
)
time.sleep(
2
)
#回到搜索窗口
for
handle
in
all_handles:
if
handle
=
=
search_windows:
driver.switch_to.window(handle)
print
(
"当前是搜索窗口"
)
driver.find_element_by_id(
'TANGRAM__PSP_4__closeBtn'
).click()
#关闭注册窗口
driver.find_element_by_id(
'kw'
).send_keys(
"selenium"
)
driver.find_element_by_id(
'su'
).click()
time.sleep(
2
)
driver.quit()
警告框处理
webdriver中处理JavaScript生成的alert,confirm,prompt十分简单,具体做法是使用switch_to_alert方法定位到alert/confirm/prompt,然后使用text/accept/dismiss/send_keys等方法进行操作。
- text:返回alert/confirm/prompt中的文字信息
- accept():接受现有警告框
- dismiss():解散现有警告框
- send_keys:发送文本至警告框
应用,如图切换至alert并接受
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from
selenium
import
webdriver
from
selenium.webdriver.common.action_chains
import
ActionChains
from
selenium.webdriver.common.by
import
By
from
time
import
sleep
url
=
'https://www.baidu.com/'
driver
=
webdriver.Chrome()
driver.get(url)
driver.maximize_window()
driver.implicitly_wait(
10
)
#鼠标悬停至设置链接
link
=
driver.find_element_by_id(
"s-usersetting-top"
)
ActionChains(driver).move_to_element(link).perform()
driver.find_element_by_link_text(
'搜索设置'
).click()
#保存设置
driver.find_element_by_class_name(
'prefpanelgo'
).click()
sleep(
2
)
#接受警告框
# driver.switch_to_alert().accept()
driver.quit()
上传文件
一般文件上传,是打开windows窗口从窗口中选择本地文件,但webdriver无法操作windows控件。
1、普通上传 将本地文件路径作为值传给input标签,注意必须是input标签
2、插件上传,基于flash,js,Ajax等技术实现上传
#定位上传按钮,添加本地文件
driver.find_element_by_name('file').send_keys("D:\upload_file.txt")
另一种方法为基于AutoIt软件来实现上传。但是不推荐,因为不在Python范围。
下载文件
webdriver允许设置默认的文件下载路径,文件会被自动下载并存放到设置的目录中
操作cookie
什么情况下回用到cookie操作?当开发人员开发一个功能,当用户登录后,会将用户的用户名写入浏览器cookie,指定key为username,就可以通过get_cookies()找到username,打印value。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
url
=
'https://www.youdao.com/'
driver
=
webdriver.Chrome()
driver.get(url)
driver.maximize_window()
driver.implicitly_wait(
10
)
# #获得cookie
driver.add_cookie({
'name'
:
'Login_User'
,
'value'
:
'Password'
})
cookie
=
driver.get_cookies()
print
(
"所有Cookie为"
,cookie)
#获取name为Login_User的cookie
one_cookie
=
driver.get_cookie(
'Login_User'
)
print
(
"Login_User的Cookie为"
,one_cookie)
# "删除name为Login_User的cookie
driver.delete_cookie(
'Login_User'
)
surplus_cookies
=
driver.get_cookies()
print
(
"剩余的cookie为:"
,surplus_cookies)
driver.delete_all_cookies()
surplus_cookies
=
driver.get_cookies()
print
(
"剩余的cookie为:"
,surplus_cookies)
driver.quit()
返回结果为
所有Cookie为[{
'domain': 'www.youdao.com',
'httpOnly': False,
'name': '___rl__test__cookies',
'path': '/',
'secure': False,
'value': '1662293521877'
}, {
'domain': '.youdao.com',
'expiry': 1696853521,
'httpOnly': False,
'name': 'OUTFOX_SEARCH_USER_ID',
'path': '/',
'secure': False,
'value': '"555592633@10.108.162.135"'
}, {
'domain': 'www.youdao.com',
'httpOnly': False,
'name': 'Login_User',
'path': '/',
'secure': True,
'value': 'Password'
}, {
'domain': '.youdao.com',
'expiry': 1696853520,
'httpOnly': False,
'name': 'OUTFOX_SEARCH_USER_ID_NCOO',
'path': '/',
'secure': False,
'value': '1883563674.2397'
}]
Login_User的Cookie为 {
'domain': 'www.youdao.com',
'httpOnly': False,
'name': 'Login_User',
'path': '/',
'secure': True,
'value': 'Password'
}
剩余的cookie为: [{
'domain': 'www.youdao.com',
'httpOnly': False,
'name': '___rl__test__cookies',
'path': '/',
'secure': False,
'value': '1662293521877'
}, {
'domain': '.youdao.com',
'expiry': 1696853521,
'httpOnly': False,
'name': 'OUTFOX_SEARCH_USER_ID',
'path': '/',
'secure': False,
'value': '"555592633@10.108.162.135"'
}, {
'domain': '.youdao.com',
'expiry': 1696853520,
'httpOnly': False,
'name': 'OUTFOX_SEARCH_USER_ID_NCOO',
'path': '/',
'secure': False,
'value': '1883563674.2397'
}]
剩余的cookie为: []
调用Javascript
可以用来控制浏览器滚动条
1
2
3
4
5
6
7
8
9
10
11
url
=
'https://www.baidu.com/'
driver
=
webdriver.Chrome()
driver.get(url)
driver.find_element_by_id(
'kw'
).send_keys(
"selenium"
)
driver.find_element_by_id(
'su'
).click()
driver.set_window_size(
600
,
600
)
#通过js设置浏览器窗口的滚动条位置
js
=
"window.scrollTo(500,500);"
driver.execute_script(js)
窗口截图
1
2
3
4
5
6
7
8
9
10
url
=
'https://www.baidu.com/'
driver
=
webdriver.Chrome()
driver.get(url)
driver.find_element_by_id(
'kw'
).send_keys(
"selenium"
)
driver.find_element_by_id(
'su'
).click()
sleep(
2
)
driver.get_screenshot_as_file(
"C:\\Users\\yangyl13\\Desktop\\3.png"
)
driver.quit()
关闭窗口
driver.quit() #退出相关驱动程序,关闭所有窗口
driver.close()#关闭单个窗口。
验证码处理
1、测试环境去掉验证码
2、万能验证码
3、验证码识别技术 如python-tesseract
4、记录cookie
下拉框选择
from selenium.webdriver.support.select import Select
Select(driver.find_element_by_id('')).select_by_index('2')#根据下拉框索引选择
Select(driver.find_element_by_id('')).select_by_value('Python')#根据下拉框value属性选择
Select(driver.find_element_by_id('')).select_by_visible_text('Python')#根据下拉框可见文本选择
版权归原作者 Anthony_路人甲 所有, 如有侵权,请联系我们删除。