赞
踩
selenium是一个用于web应用的工具:可以实现web自动化测试,以及爬虫。
特点:
可以在多个浏览器上进行自动化测试
核心:
基于python环境搭建(windows系统)如下:
1、python环境:解释器
2、安装pycharm:编写python代码的工具
配置python编译器文件-设置-项目:...-python 编译器-添加编译器-添加本地编译器-选择系统编译器。
3、安装第三方库:selenium
pip install selenium
4、 浏览器:谷歌浏览器
5、 浏览器驱动
谷歌 驱动下载地址:https://googlechromelabs.github.io/chrome-for-testing/
下载下来是压缩包chrome-win64.zip,解压后的文件夹放到项目下。
注意:浏览器版本一定要和驱动版本号保持一致;并且浏览器驱动要放在项目中才能运行。
验证环境搭建创建连接:
# 导包
import time
from selenium import webdriver
# 创建webdriver对象
#获取驱动对象
driver = webdriver.Chrome()
# 通过驱动访问页面
driver.get("https://www.baidu.com/")
# 将页面最大化
driver.maximize_window()
# 强制等待
time.sleep(5)
# 关闭驱动对象
driver.quit()
1、控制浏览器前进后退——forword()、back()
from selenium import webdriver
driver = webdriver.Chrome()
#访问百度首页
first_url= 'http://www.baidu.com'
driver.get(first_url)
#访问新闻页面
second_url='http://news.baidu.com'
driver.get(second_url)
#返回(后退)到百度首页
driver.back()
#前进到新闻页
driver.forward()
driver.quit()
2、控制浏览器刷新——refresh()
browser.refresh()
3、控制浏览器关闭退出——close()、quit()
# 当开启多个时,关闭当前页面
browser.close()
# 退出并关闭所有页面驱动
browser.quit()
4、执行JavaScript语句
browser.execute_script("window.scrollTo(100,400)")
元素的属性隐藏和显示,主要是 type="hidden"和style="display: none;"属性来控制的。
5、打印浏览器的版本号
print(browser.capabilities['version'])
>>>69.0.3497.100
6、设置页面加载的时间,如果超时会抛异常
webdriver的get方法会一直等待页面加载完毕才会进行后续操作,可如果一直加载的话,会导致后续操作无法进行。
可以通过set_page_load_time()方法来设定时间,然后捕获timeout异常 并 通过执行Javascript来停止页面加载 window.stop()
from selenium.common.exceptions import TimeoutException
import time
from selenium import webdriver
startTime = time.time()
print("start time is: %0.3f"%startTime)
driver = webdriver.Chrome()
# 设定页面加载限制时间
driver.set_page_load_timeout(30)
driver.maximize_window()
try:
driver.get('https://github.com/')
except TimeoutException:
print('time out after 30 seconds when loading page')
#当页面加载时间超过设定时间,通过执行Javascript来stop加载,即可执行后续动作
driver.execute_script('window.stop()')
1、通过id定位(根据元素的id属性来进行定位)
2、通过name属性定位(根据元素的name属性来进行定位)
3、通过class name属性定位(根据元素的class name属性来进行定位)
4、通过标签定位(不常用)(根据元素的标签来进行定位)
5、通过超链接-模糊定位(根据超链接的文本来进行定位)
6、通过超链接-精准定位 (根据超链接的文本来进行定位)
7、通过XPATH定位(常用)(xpath为元素路径定位)
8、通过css定位(常用)(元素样式定位)
class By:
ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEST = "partial link text"
NAME = "name"
TAG_NAME = "tag_name"
CLASS_NAME = "class_name"
CSS_SELECTOR = "css selector"
# 元素定位
driver.find_element(By.ID,"kw").send_keys("美女")
time.sleep(1)
driver.find_element(By.XPATH,'//*[@id="su"]').click() # 字符串中有双引号,外边就是用单引号
如何复制XPATH:在页面上定位到元素的标签,选中改元素标签,在源代码上右键-copy-copy XPath即可。
举例:
选择所有 class 属性值为 animal的元素
elements = wd.find_elements(By.CLASS_NAME, 'animal')
elements = wd.find_elements(By.CSS_SELECTOR, '.animal') # 注意这里class值前多加了一个点。
选择id属性值为searchtext定位元素
有这样一个元素:<input type="text" id='searchtext' />
element = wd.find_element(By.ID, 'searchtext')
element = wd.find_element(By.CSS_SELECTOR, '#searchtext') # 注意这里ID值前多加了一个#。
1、如果 元素2 是 元素1 的 直接子元素,CSS Selector 选择子元素的语法是这样的
元素1 >元素2
注意,最终选择的元素是 元素2, 并且要求这个 元素2 是 元素1 的直接子元素
若元素1下存在多个元素2,则默认是定位到第一个元素2,若需要定位到其他元素2,则需要使用伪类选择器去定位。
2、如果 元素2 是 元素1 的 后代元素,CSS Selector 选择后代元素的语法是这样的
元素1 元素2
中间是一个或者多个空格隔开
最终选择的元素是 元素2 , 并且要求这个 元素2 是 元素1 的后代元素。
1、css 选择器支持通过任何属性来选择元素,语法是用一个方括号 [属性名=属性值]
比如:<a href="http://www.miitbeian.gov.cn">苏ICP备88885574号</a>
element = driver.find_element(By.CSS_SELECTOR, '[href="http://www.miitbeian.gov.cn"]')
# 单引号内的内容就是 CSS Selector 表达式,以上 CSS Selector 表达式是[href="http://www.miitbeian.gov.cn"]
比如:选择所有 标签名为div,且class属性值为SKnet的元素
element = driver.find_element(By.CSS_SELECTOR, 'div[class="SKnet"]')
比如:选择 所有 具有 属性名 为href 的元素,不管它们的值是什么
element = driver.find_element(By.CSS_SELECTOR, '[href]')
2、CSS 可以选择属性值 包含 某个字符串的元素
比如: 要选择a节点,里面的href属性包含了 miitbeian字符串,就可以这样写
element = driver.find_element(By.CSS_SELECTOR, 'a[href*="miitbeian"]')
3、CSS可以选择 属性值 以某个字符串 开头 的元素
比如:要选择a节点,里面的href属性以http 开头 ,就可以这样写
element = driver.find_element(By.CSS_SELECTOR, 'a[href^="http"]')
4、CSS还可以 选择 属性值 以某个字符串 结尾 的元素
比如, 要选择a节点,里面的href属性以gov.cn 结尾 ,就可以这样写
element = driver.find_element(By.CSS_SELECTOR, 'a[href$="gov.cn"]')
5、CSS 选择器可以指定 选择的元素要 同时具有多个属性的限制
比如:<div class="misc" ctype="gun">沙漠之鹰</div>
element = driver.find_element(By.CSS_SELECTOR, 'div[class=misc][ctype=gun]')
兄弟节点就是同一父级元素下,存在多个相同子标签,那么这些子元素就是兄弟节点。
<div id="s-top-left" class="s-top-left-new s-isindex-wrap">
<a href="http://news.baidu.com" target="_blank" class="mnav c-font-normal c-color-t">新闻 </a>
<a href="http://news.hao.com" target="_blank" class="mnav c-font-normal c-color-t">123 </a>
</div>
# 选择第1个<a>里元素
driver.find_element(By.CSS_SELECTOR,"div#s-top-left>a:nth-child(1)")
# 选择第2个<a>里元素
driver.find_element(By.CSS_SELECTOR,"div#s-top-left>a:nth-child(2)")
1、:nth-child(n){}是根据父元素下所有子元素进行排序。
2、:nth-of-type(n){}是根据父元素下所有同类型的子元素进行排序。
那么我们怎么验证 CSS Selector 的语法是否正确选择了我们要选择的元素呢?
由于CSS Selector 是浏览器直接支持的,可以在浏览器 开发者工具栏 中验证。
1、F12打开开发者模式,定位到elements 标签后, 同时按 Ctrl 键 和 F 键, 就会出现搜索框
2、搜索框在里面输入任何 CSS Selector 表达式,即可在当前网页上找到元素。
如此就可验证CSS Selector 的语法是偶选择了我们要选择的元素。
通过js脚本执行让元素改变原来的属性之后再进行定位操作。
html显示与隐藏元素的几种方法
a、display
none:隐藏元素
block:显示为块级元素
B元素
display: none 隐藏自身元素以及它的所有后代元素 ,隐藏后的元素不占据任何空间,不影响页面布局。
b、visibility
hidden:隐藏
visible:显示
B元素
visibility: hidden 隐藏自身元素,但隐藏后的元素空间依旧保留,仍然会影响页面布局。
hidden_element = driver.find_element(By.XPATH, 'xxxxxx')
# 元素不可见,这段代码会报错
exceptions.ElementNotVisibleException: Message: element not visible: Element is not currently visible and may not be manipulated
定位隐藏要素的原理:
①先定位到该元素;
②使用js语句修改属性,将隐藏属性修改为显示。
# 编写JS语句,js可以直接通过id定位元素后改变元素的display属性值。
js = "document.getElementById('Title').style.display='block'"
# 执行JS
driver.execute_script(js)
---------------------------------------------------------------------------------------------------------------------
除了id是定位到的是单个element元素对象,其它的都是elements返回的是list对象。
1.通过id获取
document.getElementById(“id”)
2.通过name获取
document.getElementsByName(“Name”)
返回的是list
3.通过标签名选取元素
document.getElementsByTagName(“tag”)
4.通过CLASS类选取元素
document.getElementsByClassName(“class”)
兼容性:IE8及其以下版本的浏览器未实现getElementsByClassName方法
5.通过CSS选择器选取元素
document.querySelectorAll(“css selector")
a.querySelectorAll():返回所有匹配的结果,list集合。
b.querySelector():不管匹配结果有多少个,只返回第一个。
---------------------------------------------------------------------------------------------------------------------
比如(热门话题搜索框中的热门话题在动态变化)
M32iFFAJVyZi6gqL
4N5vs7uinB7Q9aNs
通过手写xpath进行定位
调用判断元素开头以及结束或者内容进行定位
属性动态变化是指该 element 没有固定的属性值,所以只能通过相对位置定位,比如通过 xpath 的轴,找到该元素的父节点或者子节点等方式
①切换到frame中
def switch_frame(frame_el):
driver.switch_to.frame(frame_el)
el=driver.find_element_by_xpath('//input[@id="kw"]')
el.input('kobe')
frame_el=driver.find_element_by_xpath('//iframe[@name="baidu"]')
switch_frame(frame_el)
②回到主页中
driver.switch_to.default_content()
先切换到弹窗:alert=driver.switch_to.alert
确认:alert.accept()
取消:alert.dismiss()
获取弹窗中文本:alert.getText()
弹窗中输入内容:alert.sendkeys()
注意:识别弹窗。
1、有的弹窗只是一个遮罩,不是弹窗,这种正常处理,获取元素进行相应的操作
2、对于真正的弹窗,点击保存,弹出的弹框才是真正的弹窗,这种弹窗,鼠标右击是没有反应的,没有html标签的。--是通过页面的js语法生成的。
句柄:窗口的唯一标识
1)先获取当前窗口的句柄driver.current_window_handle
2)再获取所有的的窗口句柄driver.window_handle
3)循环判断是否是想要操作的窗口,如果是就可以对窗口进行操作;如果不是就使用driver.switch_to_window方法跳转到新的窗口。
a、通过text文本查找
def select(el):
s=Select(el) #初始化Select对象
s.select_by_visible_text('kobe')
el=driver.find_element_by_xpath('//select[@id="faver"]')
b、通过value值查找
def select(el):
s=Select(el)
s.select_by_value('double')
el=driver.find_element_by_xpath('//select[@id="faver"]')
a、鼠标悬停
1、初始化一个action_chains对象
action=ActionChains(driver)
2、找到要悬浮的元素,
setting_el=driver.find_element_by_xpath(‘//span[@id=“s-usersetting-top”]’) -----> 设置
3、调用鼠标操作的函数,传入move_to_element()函数中
action.move_to_element(setting_el)
4、要让动作生效的话,必须加上perform
action.move_to_element(setting_el).perform()
5、再定位到高级设置标签
top_setting_el=driver.find_element_by_xpath(‘//a[text()=“高级搜索”]’)
top_setting_el.click()
b、拖拽动作
def drag_and_drop(el1,el2)
action=ActionChains(driver)
action.drag_and_drop(el1,el2)
action.proform()
drag_and_drop(el1,el2)
c、双击
def double_click(el)
action=ActionChains(driver)
action.double_click(el)
action.perform()
double_click(el)
代码实现如下:
el1 = driver.find element(By.XPATH,//*[@id="kw"]')
el1.send_keys("帅哥")
time.sleep(1)
el1.clear()
# - 元素大小:size
print(el1.size)
#- 元素文本:text
print(el1.text)
# - 获取属性值:get_attribute ()
print(el1.get_attribute("class"))
#- 元素是否可见:is_display
print(el1.is_displayed())
# - 元素是否可用:is enabled ()
print(el1.is_enabled())
因为在web中看到的元素,不一定写在html中,有可能是通过js代码的dom操作产生出来的,而js产生的元素,很可能先要获取数据,处理之后才会显示,那么不一定页面打开所有的元素就加载完全,需要有一定的等待时间。
如:百度搜索框输入了“美女”,点击“百度一下”按钮,在搜出来的结果中,选择其中一个点击打开。(点击“百度一下”按钮之后才去搜索有关美女的结果,结果未加载出来前,是定位不到元素的) 否则,报错,NoSuchElementException
1)线程等待(强制等待)如time.sleep(2):线程强制休眠2秒钟,2秒过后,再执行后续的代码。建议少用。
2)imlicitlyWait(隐式等待)会在指定的时间范围内不断的查找元素,直到找到元素或超时,特点是必须等待整个页面加载完成。
3)WebDriverWait(显式等待)通常是我们自定义的一个函数代码,这段代码用来等待某个元素加载完成,再继续执行后续的代码。
# 1.强制等待
time.sleep(2)
driver.find_element(By.XPATH,'//*[@id="1"]/div/h3/a').click()
1、在创建好驱动对象之后,调用隐式等待的方式传入等待时间即可
driver.implicitly_wait(5)
2、原理:
在元素的查找过程中,会持续性地获取指定元素对象。如果提前获取到元素,则会继续进行后续的操作。如果没有获取到,则会等待最大的等待时间,也会继续进行后续的操作。设置隐式等待之后,每一行代码的操作都会调用隐式等待。
#2.隐式等待
driver.implicitly_wait(0.02)
driver.find_element(By.XPATH,'//*[@id="1"]/div/h3/a').click()
1、使用方式:
from selenium.webdriver.support.wait import webDriverwait
from selenium.webdriver.support import expected_conditions as EC
el1 = WebDriverWait(driver,5).until(Ec.presence_of_element_located((By.XPATH,'//*[@id="1"]/div/h3/a')))
driver.find_element(By.XPATH,'//*[@id="1"]/div/h3/a').click()
2、原理
每隔一定的时间(单位s)不断尝试查找元素。显式等待在调用之后,如果获取元素成功,则会返回该元素对象,便于后续的继续调用,如果获取元素失败,则会抛出timeout异常,显示message参数定义的内容
#3.显示等待
el1 = WebDriverWait(driver,5).until(Ec.presence_of_element_located((By.XPATH,'//*[@id="1"]/div/h3/a')))
driver.find_element(By.XPATH,'//*[@id="1"]/div/h3/a').click()
WebDriverWait(d,10,1).unitl(EC.presence_of_element_located(locator))
这里表示等待10s,每隔1s去检查一次元素是否出现,出现了就执行下一步,直到10s
结束后还没有出现就会抛出异常。
页面切换类的用隐式等待,弹框类的用显示等待比较好。
但一般正常使用的时候会进行一个封装,而不是在具体定位某个元素的时候进行使用,而是会把 每一个元素需要定位的时候要出发的等待都加上一个B包装饰器去完成高效的元素定位
后期进阶学习:鼠标操作、键盘操作、下拉框操作以及子页面切换等。
设计流程用例:
# 导包
import time
from selenium import webdriver
form selenium.webdriver.common.by import By
# 创建webdriver对象
# 获取驱动对象
driver = webdriver.chrome()
# 通过驱动访问页面
driver.get("https://www.baidu.com/")
# 将页面最大化
driver.maximize_window()
# 编写自动化的用例线性脚本,完成冒烟测试
。输入账号
driver.find_element(By.XPATH," ").send_keys("admin")
。输入密码
driver.find_element(By.XPATH," ").send_keys("123")
。输入验证码
driver.find_element(By.XPATH," ").send_keys("8888") # 模拟呢,肯定是验证码错误
。点击登录
driver.find_element(By.XPATH," ").click()
# 强制等待
time.sleep(5)
# 关闭驱动对象
driver.quit()
# 截取验证码图片
driver.find_element(By.XPATH,'//*[@id="verify"]') .screenshot("verify.png")
通过第三方平台:
# 获取驱动对象
driver = webdriver.chrome()
# 通过驱动访问页面
driver.get("https://www.baidu.com/")
# 将页面最大化
driver.maximize_window()
# 截取验证码图片
driver.find_element(By.XPATH,'//*[@id="verify"]') .screenshot("verify.png")
# 识别验证码,代码实现如下:
url = "http://upload.chaojiying.net/Upload/Processing.php"
data = {
# 第三方平台(超级鹰)用户名
"user":"tianqiu2",
# 第三方平台(超级鹰)密码
"pass":"7tqiu123456",
# 第三方平台(超级鹰)用户id
"sofid":"949627”,
# 验证码类型编号
"codetype": 1902
}
# 打开读取图片
files = {"userfile": open("verify.png",“rb")}
resp = requests.post(url, data=data, files=files) # 要导入requests模块
# print(resp.json)
res = resp.json()
if res["err_no"] == 0:
print("识别成功")
code = res["pi_str"]
print(f"验证码数字为:{code}")
else:
print("识别失败")
# 编写自动化的用例线性脚本,完成冒烟测试
。输入账号
driver.find_element(By.XPATH," ").send_keys("admin")
。输入密码
driver.find_element(By.XPATH," ").send_keys("123")
。输入验证码
driver.find_element(By.XPATH," ").send_keys(code)
。点击登录
driver.find_element(By.XPATH," ").click()
# 强制等待
time.sleep(5)
# 关闭驱动对象
driver.quit()
一般线性脚本和处理功能的脚本不会写在一起;
具体的功能实现,比如验证码识别会进行独立的封装进行调用。
另外创建一个py文件util.py
def imgcode(files):
# 识别验证码,代码实现如下:
url = "http://upload.chaojiying.net/Upload/Processing.php"
data = {
# 用户名
"user":"tianqiu2",
# 密码
"pass":"7tqiu123456",
# 用户id
"sofid":"949627”,
# 验证码类型编号
"codetype": 1902
}
# 打开读取图片
files = {"userfile": open(files,“rb")}
resp = requests.post(url, data=data, files=files) # 要导入requests模块
# print(resp.json)
res = resp.json()
if res["err_no"] == 0:
print("识别成功")
code = res["pi_str"]
print(f"验证码数字为:{code}")
else:
print("识别失败")
调用验证码识别函数,获取验证码实际值
#截取验证码图片
driver.find_element(By.XPATH,'//*[@id="verify"]') .screenshot("verify.png")
#调用验证码识别函数,获取返回结果值
code = imgcode("verify.png")
登录测试用例执行后登录上了,后期的测试用例是登录后才可执行,所以要一直保持登录状态。
1、保持自动登录的方式
通过cookie信息的唯一标识id
一直保持不退出状态,就可以实现自动登录
2、退出登录
注销登录状态
关闭浏览器
删除已登录状态的cookie信息
所以保持登录的方法就是-给页面设置已登录状态的cookie信息,刷新页面清除缓存实现保持登录状态。
# 给页面设置已登录状态的cookie信息(SESSIONID:RH23T4353YH7VH854该cookie信息是已登录状态的)
drever.add_cookie(
{"name":SESSIONID,"value":RH23T4353YH7VH854}
)
# 刷新页面
driver.refresh()
适用于所有的web项目,实际上使用的时候,要找开发拿到服务器验证你cookie的实际的值。
1、在页面第一次登录成功之后,保存当前页面的cookie信息;
2、在页面第二次及以后的登录过程中,直接使用保存的cookie信息。
第一步:需要定义两个函数
保存页面cookie信息的函数
def save_cookie(driver):
# 获取当前页面所有的cookie信息
cookies = driver.get_cookies()
# 拿到所有的cookie信息是一个字典(键值对),要保存到json当中
with open("cookies.json","w") as f:
f.write(json.dumps(cookies)) #通过json模块dumps转换,将键值对格式转换成json格式
使用页面cookie信息的函数
def load_cookie(driver):
# 从本地文件cookies.json文件中读取cookie信息
try:
driver.get("http://47.107.116.139/fangwei/m.php.....")
with open("cookies.json","r") as f: # 只读r可以省略
cookies = json.loads(f.read())
for cookie in cookies:
driver.add-cookie(cookie)
else:
# 将页面所有cookie信息添加完成之后,刷新页面
driver.refresh()
except:
pass
此处使用else原因就是,只有for循环正常结束,才会执行else代码,如果未正常结束,不会执行else代码块。
# 判断当前页面是否登录状态
def is_login(driver):
if “管理员登录” in driver.title:
print("需要进行登录”)
return True
else:
print("已登录状态")
return False
通过获取和使用cookie信息万和城呢个自动化登录或者流程登录:
第二步:自定义函数的使用(自动获取cookie信息)
# 导包 import time import requests from selenium import webdriver from selenium.webdriver.common.by import By from utils import imgcode, sava_cookie, load_cookie, is_login #创建webdriver对象 # 获取驱动对象 driver = webdriver.chrome() # 通过驱动访问页面 driver.get("http://47.107.116.139/fangwei/m.php?m=Public&a=login&") # 将页面最大化 driver.maximize_window() # 使用cookie信息 load_cookie(driver)
if is_login(driver): # 截取验证码图片 driver.find_element(By.xPATH, '//*[@id="verify"]').screenshot(''verify.png") # 调用验证码识别函数,获取返回结果值 code = imgcode("verify.png") # 编写自动化的用例线性脚本 #- 完成功能冒烟测试 # - 输入账号 driver.find_element(By.XPATH,"/htm1/body/form/table/tbody/tr/td[3]/table/tbody/tr[2]/td[2]/input") .send_keys("admin") #- 输入密码 driver.find element(By.XPATH. "/htm1/body/form/table/tbody/tr/td[3]/table/tbody/tr[3]/td[2]/input").send_keys("msjy123" #- 输入验证码 driver.find element(By.XPATH. "/html/body/form/table/tbody/tr/td[3]/table/tbody/tr[5]/td[2]/input") .send_keys(code) #- 点击登录 # input(":::") driver.find_element(By.xPATH, '//*[@id="login_btn"]').click() # 保存cookie信息 sava_cookie(driver) # 强制等待 time.sleep(5) #_关闭驱动对象 driver.quit()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。