一、selenium介绍
selenium是一个用于测试web程序的工具。selenium测试直接运行在浏览器上,就像真正的用户在操作浏览器一样。
selenium的主要功能有:测试与浏览器的兼容性,测试应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能,创建回归测试检验软件功能和用户需求。
selenium的优点:
- 免费且开源
- 支持linux、windows、macos系统
- 支持IE、Chorme、Firefox、 Safari、Opera等浏览器
- 支持Java、Python、Ruby、JS、C#、PHP语言等编程语言
- 可以轻松地与其他工具进行集成,例如unittest、pytest、Junit、TestNG、Maven、Jenkins等
- 通过Selenium Grid实现并行分布式测试
二、selenium安装
1.安装selenium
pip install selenium
2.下载驱动
不同的浏览器的不同版本下载不同的驱动,驱动下载解压,然后添加环境变量。下载驱动地址:https://www.selenium.dev/documentation/en/webdriver/driver_requirements/
如果要打开IE浏览器的话,需要在浏览器的Internet选项中的安全页里有4个安全选项,Internet、本地Internet、受信任的站点、受限制的站点,这4个里面都有一个启用保护模式,都需要勾选上才可以,还得把驱动的路径加入到环境变量中。
三、selenium启动浏览器
本文以python语言,Chorme浏览器为例
1.启动浏览器
from selenium import webdriver
driver = webdriver.Chrome() #启动浏览器
driver.get("https://www.baidu.com") #在浏览器中打开百度页面
driver.quit() #退出浏览器
2.屏蔽chrome浏览器的信息提示栏
from selenium import webdriver
options = webdriver.ChromeOptions() #设置chrome浏览器选项
# options.add_argument('disable-infobars') #这种方式失效了
options.add_experimental_option("excludeSwitches",['enable-automation'])
driver = webdriver.Chrome(chrome_options=options)
driver.get("https://www.baidu.com")
driver.quit()
3.chrome浏览器模拟手机
from selenium import webdriver
mobileEmulation = {"deviceName":"iPhone 6"} #设置手机型号,都是比较老的机型
options = webdriver.ChromeOptions()
options.add_experimental_option("mobileEmulation",mobileEmulation)
driver = webdriver.Chrome(chrome_options=options)
driver.get("https://www.baidu.com")
driver.quit()
4.设置无头模式
# chrome无头浏览
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument("--headless") #设置无头浏览
options.add_argument("log-level=1") #设置log显示等级为1,默认为0,不然会有很多info信息打印;INFO=0 WARNING=1 LOG_ERROR =2 LOG_FATAL=3
driver = webdriver.Chrome(chrome_options=options)
driver.get("http://www.baidu.com")
element = driver.find_element_by_id("kw")
print(element.get_attribute("outerHTML"))
driver.quit()
5.设置浏览器窗口大小
driver.set_window_size(400,800) #设置浏览器窗口大小为宽400,高800
driver.maximize_window() #最大化浏览器窗口
driver.minimize_window() #最小化浏览器窗口
6.浏览器的前进后退和刷新
driver.forward() #前进
driver.back() #后退
driver.refresh() #刷新
7.浏览器的关闭
driver.close() #关闭浏览器当前页面
driver.quit() #关闭浏览器所有页面和驱动
四、selenium定位方式
在操作页面元素之前我们首先要对页面元素进行定位,元素定位的过程就是查找HTML元素的过程。find_element通过定位方式查找一个元素,如果有多个返回第一个;find_elements通过定位方式查找所有符合条件的元素,返回一个list
1.使用元素的属性定位
element = driver.find_element_by_id("kw") #通过元素的id属性值定位,id属性通常都是唯一的,但是id可能是动态的
element = driver.find_element_by_name("wd") #通过元素的name属性值定位,name属性不一定是唯一的
element = driver.find_element_by_class_name("s_ipt") #通过元素的class属性值定位,class属性不一定是唯一的
element = driver.find_elements_by_tag_name("input") #通过元素的标签名称定位,元素名称通常都不止只有一个,经常用find_elements_by_tag_name定位一组元素
element = driver.find_element_by_link_text("1石家庄今日新增确诊病例26例新") #通过有超链接的元素文本定位,需要输入完整的文内内容,否则会定位失败;一般用来定位页面上的超链接
element = driver.find_element_by_partial_link_text("石家庄今日新增确诊病例26例") #通过有超链接的元素的部分文本定位,一般用来定位页面上的超链接
2.使用xpath定位
xpath 是一门在 XML 文档中查找信息的语言,了解相关信息https://www.w3school.com.cn/xpath/index.asp
element = driver.find_element_by_xpath('xpath路径')
2.1 使用绝对路径定位:从根节点开始一层一层查找
/表示绝对路径,例如使用driver.find_element_by_xpath("html/body/div/div/div/div/div/form/span/input")可以定位到百度搜索输入框,但是繁琐
2.2通过相对路径定位
//表示相对路径,.表示当前元素,..表示父元素
- 通过属性定位,//*代表所有标签名,//*[@属性名="属性值"]
- 使用标签+属性查找;//标签名[@属性名="属性值"];
- 使用层级定位,先定位目标标签的父标签来定位子标签;//父标签名[@父标签属性名="父标签属性值"]/子标签;层级定位不限于两层,可以是多层的
- 索引,当一个父标签有多个相同标签名的子标签时使用;//父标签名[@父标签属性名="父标签属性值"]/子标签[索引值];xpath的索引值是从1开始的;不写标签值,如果有多个相同子标签默认定位第一个
- 逻辑and/or/not,当元素属性与其他元素有相同的部分,需要使用多个属性定位一个元素时使用and连接多个属性;//标签名[@属性名1="属性值1" and @属性名2="属性值2"]
- text关键字,//*[text()="百度一下"] 文本是百度一下的元素
- 模糊匹配,contains包含,starts-with匹配开头,ends-with匹配结尾,matchs正则匹配;//*[contain(@属性名,"部分属性值")]
- | 连接符 通过在路径表达式中使用|,可以选取若干个路径;//div/p | //input查找div标签下的所有p标签和所有input标签
- 通过轴定位关联标签;//标签名称/轴名称::标签名称;轴名称:
- ancestor:祖先节点 包括父
- parent:父节点
- prceding-sibling:当前元素节点标签之前的所有兄弟节点
- prceding:当前元素节点标签之前的所有节点
- following-sibling:当前元素节点标签之后的所有兄弟节点
- following:当前元素节点标签之后的所有节点
element = driver.find_element_by_xpath('//input[@id="kw"]') #利用标签名+属性定位百度搜索框
element = driver.find_element_by_xpath('//*[@name="wd" and @class="s_ipt"]') #利用2种属性定位百度搜索框
element = driver.find_element_by_xpath('//div[@id="s-top-left"]/a[2]') #利用层级定位和索引定位百度页面左上角的hao123超链接地址
3.使用CSS定位
css是一种语言,用来描述HTML和XML文档的表现。css使用选择器来为页面元素绑定属性,这些选择器可以被selenium用作定位。css比xpath定位快
element = driver.find_element_by_css_selector('css表达式')
3.1通过属性定位,id用#表示,#kw;class用.表示,.s_ipt;其实属性使用属性名,[属性名="属性值"];还可以加上标签,标签名[属性名="属性值"]
3.2使用层级定位,父标签[父标签属性名="父标签属性值"]>子标签
3.3使用索引定位,父标签[父标签属性名="父标签属性值"]>子标签:nth-child(索引值),索引值从1开始;nth-child(索引值)表示父标签下所有子标签的顺序值,可省略子标签名;父标签[父标签属性名="父标签属性值"]>p:nth-of-type(n) 表示父标签下第n个p标签
3.4使用逻辑定位,标签名[属性名1="属性值1"][属性名2="属性值2"] 表示and
3.5使用模糊匹配,^表示匹配开头,$匹配结尾,*表示包含;标签名[属性名*="属性值"]
element = driver.find_element_by_css_selector('#kw') #利用id属性定位百度搜索框
element = driver.find_element_by_css_selector('input[name="wd"][class*="ipt"]') #利用2种属性定位百度搜索框
element = driver.find_element_by_css_selector('div#s-top-left>a:nth-child(2)') #利用层级定位和索引定位百度页面左上角的hao123超链接地址
4.如何选择元素定位
如果有标签有id属性,使用id定位;如果没有id,或者id是动态的,使用xpath或css定位,css定位更快,推荐使用css;如果有超链接,使用link_text或partial_link_text定位
5.复制xpath路径和css路径
五、元素操作
element.click() #点击
element.send_keys("输入的内容") #输入
element.clear() #清空
element.submit() #用于表单提交
element.size #获取元素的尺寸大小
element.text #获取元素的文本
element.tag_name #获取元素标签名
driver.title #获取当前页面的标题
driver.current_url #获取当前页面的url
element.get_attribution("属性名") #获取元素的属性值
element.is_displayed() #判断元素是否可见
element.is_enabled() #判断元素是否可用
element.is_selected() #判断元素是否被选中,可用于单选框和复选框的选项
print(element.get_attribute("outerHTML")) #可以打印被定位的element的代码
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window() #最大化窗口
time.sleep(3)
element = driver.find_element_by_id("kw") #定位百度搜索框
print(element.get_attribute("outerHTML")) #打印元素代码
element.send_keys("python") #在百度搜索框输入python
driver.find_element_by_id("su").click() #再点击百度一下
time.sleep(3)
print(driver.title) #打印页面标题
element.clear() #清空输入框
time.sleep(3)
driver.quit()
六、鼠标事件
在测试中除了简单的click()点击鼠标左键的操作,还会涉及到点击鼠标右键,双击鼠标左键等操作,webdriver中使用ActionChains()类来提供鼠标相关操作。ActionChains()提供鼠标事件的常用方法:
- click(element):单击鼠标左键
- double_click(element):双击鼠标左键
- click_and_hold(element):长按鼠标左键
- context_click(element):单击鼠标右键
- drag_and_drop(source,target):把元素拖拽到目标元素上然后松开
- drag_and_drop_by_offset(source,x,y):把元素拖拽到(x,y)位置
- move_by_offset(x,y):把鼠标移动到(x,y)位置
- move_to_element(element):把鼠标移到元素位置
- move_to_element_by_offset(element,x,y):把鼠标移动到距离元素多少距离的位置
- release(element):在某个元素位置松开鼠标左键
- perform():执行链中的所有操作
在使用ActionChains之前需要导入类from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains #导入鼠标操作类
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window() #最大化窗口
time.sleep(3)
setting = driver.find_element_by_id("s-usersetting-top") #定位右上角设置菜单
ActionChains(driver).move_to_element(setting).perform() #鼠标悬停在设置菜单上,显示出子菜单选项
gs = driver.find_element_by_link_text("高级搜索") #定位子菜单上的高级搜索
gs.click() #点击高级搜索
time.sleep(3)
driver.quit() #关闭浏览器
七、键盘事件
有时我们在测试中需要使用tab键将标点聚焦到下一个元素,用于验证元素的排序是否正确;webdriver中的Keys()类提供键盘上的所有键输入,甚至可以模拟一些组合键操作,例如ctrl+a等;在某些复杂情况还会使用send_keys()来模拟上下键操作下拉列表的情况。
使用Keys()类来模拟键盘操作:
- send_keys(Keys.BACK_SPACE):删除键Backapace
- send_keys(Keys.SPACE):空格键Space
- send_keys(Keys.ESCAPE):退出键Esc
- send_keys(Keys.ENTER):回车键Enter
- send_keys(Keys.CONTROL,"a"):全选ctrl+a
- send_keys(Keys.CONTROL,"c"):复制ctrl+c
- send_keys(Keys.CONTROL,"v"):粘贴ctrl+v
- send_keys(Keys.CONTROL,"x"):剪切ctrl+x
- send_keys(Keys.F1):按F1
- send_keys(Keys.F12):按F12
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window() #最大化窗口
time.sleep(3)
element = driver.find_element_by_id("kw") #定位百度搜索框
element.send_keys("python") #在搜索框中输入python
element.send_keys(Keys.ENTER) #在搜索框中回车
time.sleep(3)
driver.quit()
八、二次定位
1.二次定位:先定位父元素再定位其子孙元素
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window() #最大化窗口
time.sleep(3)
e1 = driver.find_element_by_id("s-top-left") #先定位父元素左上方导航栏
# e1.find_elements_by_tag_name("a")[1].click() #定位导航栏的子元素,在父元素的代码找a标签返回一个列表,取第二个hao123
# e1.find_element_by_css_selector("a:nth-child(2)").click() #二次定位使用css
e1.find_element_by_xpath("./a[2]").click() #二次定位使用xpath要写.表示e1元素,再根据e1元素找子元素,写//会在全页面里找
time.sleep(3)
driver.quit()
2.使用select二次定位,只能select下拉框使用
from selenium import webdriver
from selenium.webdriver.support.select import Select #导入Select
import time
driver = webdriver.Chrome()
driver.get("https://www.selenium.dev/documentation/en/") #国外网站selenium,加载很慢,加载完成后才开始进行下步操作
driver.maximize_window() #最大化窗口
time.sleep(3)
s = driver.find_element_by_id("select-language") #首先定位到select元素
# s.find_elements_by_tag_name("option")[5].click() #使用二次定位定位option元素
# Select(s).select_by_index(5) ##根据索引选择,从0开始
# Select(s).select_by_value("https://www.selenium.dev/documentation/zh-cn/") #根据value属性选择
Select(s).select_by_visible_text("中文简体") #根据文本内容选择,不需要click()
time.sleep(3)
driver.quit()
九、页面操作
1.滚动条操作
在HMTL中有些元素是动态加载的,元素根据滚动条的下拉而被加载;通过JS脚本来控制滚动条
设置JS脚本控制滚动条:js = "window.scrollTo(0,1000)",前面的0是水平距离,1000是垂直距离,单位是像素
selenium同步执行js脚本:driver.execute_script(js)
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
time.sleep(3)
js = "window.scrollTo(document.body.scrollWidth,0)" #水平滚动条拉到最右边,document.body.scrollWidth表示实际宽度,也可以写一个足够大的数字
#js = "window.scrollTo(0,document.body.scrollHeight) #垂直滚动到最底部,document.body.scrollHeight表示实际高度
driver.execute_script(js)
time.sleep(3)
driver.execute_script("window.scrollTo(0,0)") #水平滚动条拉到最左边,第一个数字写0
time.sleep(3)
driver.quit()
2.聚焦元素
滚动条滚动到元素位置,js代码,js = "arguments[0].scrollIntoView();"
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
time.sleep(3)
setting = driver.find_element_by_id("s-usersetting-top") #定位右边的设置菜单
driver.execute_script("arguments[0].scrollIntoView();",setting) #执行js脚本滚动到设置的位置
time.sleep(3)
driver.quit()
3.frame
在web应用中经常用到表单嵌套页面,frame标签有frameset、frame、iframe三种,frameset与其他元素一样,不会影响到定位;而frame和iframe需要切换进去才能定位到其中的元素。通过switch_to_frame()(也可以写switch_to.frame())方法把当前定位的主体切换到表单内嵌页面中。再要定位frame外面的邮箱,需要再切换到外层
#iframe
#网易邮箱
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://mail.163.com/")
iframe = driver.find_element_by_css_selector("div#loginDiv>iframe") #定位到iframe
driver.switch_to_frame(iframe) #切换到iframe
email = driver.find_element_by_css_selector("div#account-box>div>input") #定位到邮箱地址输入框
print(email.get_attribute("outerHTML"))
# driver.switch_to_default_content() #切换到最外层,也可以写driver.switch_to.default_content()
driver.switch_to.parent_frame() #切换到上一层,如果只有一层frame,这两个操作都可以
e = driver.find_element_by_link_text("企业邮箱") #定位外层的企业邮箱链接
print(e.get_attribute("outerHTML"))
driver.quit()
4.多窗口切换
在页面中点击每个元素会弹出新的窗口,这时需要切换到新窗口操作
- switch_to.window():在不同窗口切换,也可以写switch_to_window()
- current_window_handle:获得当前的窗口句柄
- window_handles:获取所有的窗口句柄
#切换窗口
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
time.sleep(3)
driver.find_element_by_link_text("hao123").click() #点击hao123页面
handles = driver.window_handles #获取所有的窗口句柄
print(driver.current_window_handle) #打印当前窗口句柄,CDwindow-96A0DC2749E8B6E507D72A73872755B7,每次打印的都不一样
print(driver.title) #打印当前窗口标题,百度一下,你就知道
driver.switch_to_window(handles[1]) #切换窗口
print(driver.title) #打印当前窗口标题,hao123_上网从这里开始
driver.quit()
5.浏览器自带弹窗
webdriver处理js所生成的alert、confirm、prompt,需要使用switch_to_alert()(也可以写switch_to.alert())去定位到弹框,然后使用text/accept/dismiss/send_keys()进行操作
- text:alert/confirm/prompt弹框中的文本
- accept:点击确认按钮
- dismiss:点击取消按钮,有才能操作
- send_keys():输入值,有输入框才能操作
6.自定义弹框
由于alert弹框不美观,很多网站都自定义弹框,webdriver使用js处理自定义弹框,利用html dom style对象,有一个display属性,设置元素如何被显示;js = 'document.getElementById("id属性值").style.display="none";';document文档,指整个页面代码
#处理自定义弹框
#哔哩哔哩
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("https://www.bilibili.com")
driver.maximize_window()
time.sleep(3)
js = 'document.getElementById("elevator").style.display="none";' #js脚本不显示id为elevator的元素
driver.execute_script(js) #执行js脚本
time.sleep(3)
driver.quit()
6.单选框和复选框
单选框radio默认是圆形选框,复选框checkbox默认是方形选框
6.1 radio
先定位选项再点击可以选中
#百度
#单选框
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
#导入鼠标操作类
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window() #最大化窗口
time.sleep(3)
setting = driver.find_element_by_id("s-usersetting-top") #定位右上角设置菜单
ActionChains(driver).move_to_element(setting).perform() #鼠标悬停在设置菜单上,显示出子菜单选项
gs = driver.find_element_by_link_text("搜索设置") #定位子菜单上的高级搜索
gs.click()
time.sleep(3)
s1 = driver.find_element_by_id("s1_1") #定位搜索框显示单选框的显示
# s1.click() #已选中再次点击没有取消选中
print(s1.is_selected()) #打印选项是否被选中;True
s2 = driver.find_element_by_id("s1_2") #定位不显示
s2.click() #点击不显示
print(s1.is_selected()) #打印选项是否被选中;False
print(s2.is_selected()) #打印选项是否被选中;True
time.sleep(3)
driver.quit()
6.2 checkbox
复选框,如果未选中点击会选中,如果已经选中再次点击会取消选中,所以点击之前要先判断是否选中;
#博客园随笔编辑页面
#复选框
from selenium import webdriver
import time
#因为需要登陆,加载了chorme浏览器的用户数据,获取cookie;但是不能开2个浏览器,会报错,提示“Message: invalid argument: user data directory is already in use”
options = webdriver.ChromeOptions()
options.add_argument("user-data-dir=C:\\Users\\***\\AppData\\Local\\Google\\Chrome\\User Data")
driver = webdriver.Chrome(chrome_options=options)
driver.get("")
print(driver.get_cookies()) #可以获取cookies
driver.maximize_window() #最大化窗口
time.sleep(3)
#滚动到最底部
js = "window.scrollTo(0,10000)"
driver.execute_script(js)
#定位复选框的上层元素
e = driver.find_element_by_css_selector("[name='高级选项']>div:nth-child(2)>div")
#二次定位所有的复选框元素
boxes = e.find_elements_by_css_selector("input[type='checkbox'")
#需要勾选的2个选项的id
list = ["displayOnHomePage","isPinned"]
for box in boxes:
#复选框会有默认选项,判断是否已选中,如果已选中,反选取消选中
if box.is_selected():
box.click()
#获取元素的id属性,如果是要勾选的,点击勾选
if box.get_attribute("id") in list:
box.click()
time.sleep(3)
driver.quit()
7.富文本操作
富文本是一个iframe,需要切换到frame再操作内嵌元素
8.文件上传
8.1 一般文件上传是<input type=file ...>,先定位到元素,再send_keys(文件地址)上传文件
uploadfile = driver.find_element_by_name("UploadFile")
uploadfile.send_key("文件地址")
time.sleep(n)
上传文件的注意事项:在上传文件的时候需要对文件的类型、大小等做充分的验证;在执行上传脚本时,加一定的等待时间,sleep
8.2 少数上传文件不是input标签,需要借助autoit工具或者SendKeys第三方库解决
https://www.jianshu.com/p/fba37cc5d5e2
9.文件下载
文件下载可以通过加载浏览器配置,也可以自行设置下载的配置项,下面介绍的是设置下载的配置项的方法
9.1Firefox文件下载
#Firefox下载文件
from selenium import webdriver
import time
import os
#通过FirefoxProfile()对其参数做设置,这些参数可以通过在Firefox浏览器地址栏输入:about:config进行设置
fp = webdriver.FirefoxProfile()
fp.set_preference("browser.download.folderList",2) #0表示下载到桌面,1表示下载到默认下载地址,2表示自定义下载路径
fp.set_preference("browser.downlaod.manager.showWhenStarting",False) #在开始下载时是否显示下载管理器
fp.set_preference("browser.download.dir",os.getcwd()) #指定下载路径,os.getcwd()返回当前目录
fp.set_preference("browser.helperApps.never.saveToDisk","application/octet-stream") #不再弹框询问文件类型,application/octet-stream表示二进制流,不知道文件类型;HTTP content-type常用对照表
driver = webdriver.Firefox(firefox_profile=fp)
driver.get("http://chromedriver.storage.googleapis.com/index.html?path=87.0.4280.88/")
time.sleep(3)
driver.find_element_by_xpath('//a[text()="chromedriver_win32.zip"]').click()
time.sleep(5)
driver.quit()
9.2 chrome文件下载
#chrome浏览器文件下载
from selenium import webdriver
import time
options = webdriver.ChromeOptions()
prefs = {
"profile.default_content_settings.popups":0, #设置0表示禁止弹出弹框
"download.default_directory":"E:\\" #设置文件下载地址
}
options.add_experimental_option("prefs",prefs)
driver = webdriver.Chrome(chrome_options=options)
driver.get("http://chromedriver.storage.googleapis.com/index.html?path=87.0.4280.88/")
time.sleep(3)
driver.find_element_by_xpath('//a[text()="chromedriver_win32.zip"]').click()
time.sleep(5)
driver.quit()
10.截图
#截图
from selenium import webdriver
import time
import os
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("http://www.baidu.com")
time1 = time.strftime("%Y_%m_%d_%H_%M_%S",time.localtime())
filename = time1 + ".png"
path = os.path.abspath("screenshot")
pathname = path + "\\"+filename
# driver.save_screenshot(filename) #截图保存在当前目录,文件名为当时时间
# driver.save_screenshot(pathname) #截图保存在screenshot目录,文件名为当前时间
driver.get_screenshot_as_file(pathname) #另一种截图保存方法
driver.quit()
十、浏览器免登陆
现在web应用登陆时,通常需要输入验证码,自动化测试时怎么处理验证码:
- 测试环境让开发去掉验证码
- 设置一个万能验证码
- 验证码识别技术
- 获取cookie免登陆;需要先登陆网站且不能退出,退出cookie会失效
下面介绍通过cookie绕过验证码
1.浏览器加载配置
通过加载浏览器配置可以获取浏览器的cookie信息,绕过登陆
1.1 Firefox
- 获取Firefox的配置文件路径:菜单>帮助>故障排除信息>配置文件夹;profile_directory=配置文件夹
- 加载配置文件
profile = FirefoxProfile(profile_directory)
driver = webdriver.Firefox(profile)
1.2 Chrome
options = webdriver.ChromeOptions()
options.add_argument("user-data-dir=C:\\Users\\***\\AppData\\Local\\Google\\Chrome\\User Data") #只能打开一个chrome浏览器不然会报错
driver = webdriver.Chrome(chrome_options=options)
2.通过cookie
driver.get_cookies():获取所有的Cookie,返回列表格式,列表里面套字典
driver.get_cookie(name):获取指定name的Cookie值
driver.add_cookie(dict):添加cookie,必须要有name和value
driver.delete_cookie(name):删除指定name的cookie
driver.delete_all_cookie():删除所有的Cookie
#cookie登录博客园
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.maximize_window() #最大化屏幕
driver.get("") #进入博客园页面
time.sleep(5)
#cookies登录博客园
cookies = [{'domain': '.cnblogs.com', 'expiry': 1611398938, 'httpOnly': False, 'name': '_gat_gtag_UA_48445196_1', 'path': '/', 'secure': False, 'value': '1'},
{'domain': 'i.cnblogs.com', 'httpOnly': True, 'name': '.AspNetCore.Session', 'path': '/', 'secure': False, 'value': 'C***'},
{'domain': '.cnblogs.com', 'expiry': 1611485278, 'httpOnly': False, 'name': '_gid', 'path': '/', 'secure': False, 'value': '**'},
{'domain': '.cnblogs.com', 'expiry': 1671607788, 'httpOnly': False, 'name': '_ga_4CQQXWHK3C', 'path': '/', 'secure': False, 'value': 'G**'},
{'domain': '.cnblogs.com', 'expiry': 1674470878, 'httpOnly': False, 'name': '_ga', 'path': '/', 'secure': False, 'value': 'GA**'},
{'domain': '.cnblogs.com', 'expiry': 1634994906, 'httpOnly': False, 'name': '__gads', 'path': '/', 'secure': False, 'value': 'ID**'},
{'domain': '.cnblogs.com', 'expiry': 1619531791, 'httpOnly': False, 'name': 'UM_distinctid', 'path': '/', 'secure': False, 'value': '**'},
{'domain': '.cnblogs.com', 'expiry': 1612672030, 'httpOnly': True, 'name': '.Cnblogs.AspNetCore.Cookies', 'path': '/', 'secure': False, 'value': '**'},
{'domain': '.cnblogs.com', 'expiry': 1632998446, 'httpOnly': False, 'name': 'Hm_lvt_39b794a97f47c65b6b2e4e1741dcba38', 'path': '/', 'secure': False, 'value': '160***'}]
for cookie in cookies:
driver.add_cookie(cookie)
time.sleep(3)
driver.refresh() #刷新浏览器,不刷新页面是看不到登陆后的信息的
time.sleep(3)
driver.find_element_by_id("user_icon").click() #点击右上方图像进入个人博客主页
time.sleep(5)
print(driver.title) #打印现在的页面标题,小测试00的主页 - 博客园
driver.quit()
十一、元素等待
由于现在大多数web应用程序都结合Ajax/JavaScript技术开发,当浏览器进行页面信息加载时,页面中的元素会在不同的时间间隙陆续完成加载;还有网络、电脑配置、服务器反应时间等因素影响,为了保证脚本的稳定性,需要给脚本增加一定的等待时间。
1.强制等待
time.sleep(s):针对Python代码,强制等待;有时控件加载或2个操作之间会sleep,防止网站认为是爬虫
2.隐式等待
driver.wait_implicatly(s):webdriver会在DOM中查找该元素,如果没找到将继续等待,超出设置的等待最大时间后将抛出找不到元素的异常。隐式等待服务于当前的整个测试脚本。
from selenium import webdriver
import time
driver = webdriver.Chrome()
print(time.time())
driver.implicitly_wait(10) #隐式等待
driver.get("https://github.com/")
print(time.time())
element = driver.find_element_by_partial_link_text("Sign up") #查找一个存在的元素
print(element.get_attribute("outerHTML"))
print(time.time())
try:
element1 = driver.find_element_by_tag_name("canvas1") #查找一个不存在的元素
except Exception as e:
print(e)
print(time.time())
driver.quit()
3.显示等待
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)在设定时间内等待指定元素,超出最长等待时间则抛出错误:
- driver:浏览器驱动
- timeout:最长等待时间,默认单位为秒
- poll_frequency:监测隔间时间,默认为0,5s
- ignored_exceptions:忽略的报错信息
- WebDriverWait有until和until_not方法;until(method,message);until_not(method,message)
#显示等待
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
element = WebDriverWait(driver,10).until(lambda x:x.find_element_by_id("kw")) #until参数必须是一个方法,不能直接用driver.find_element;找一个存在的元素,找到返回元素,不存在报错
print(element.get_attribute("outerHTML"))
element_is_displayed = WebDriverWait(driver,10).until(lambda x:x.find_element_by_id("kw").is_displayed()) #一个元素是否可见,返回布尔值
print(element_is_displayed)
try:
element = WebDriverWait(driver,10).until(lambda x:x.find_element_by_id("kk"),"没找到元素") #找一个不存在的元素
print(element.get_attribute("outerHTML"))
except Exception as e:
print(e)
driver.quit()
4.expected_conditiions
expected_conditions是selenium的一个模块(简称EC),其中包含一系列可用于判断的条件;EC返回的是方法,常和WebDriverWait配合使用:
- title_is(title):判断网页title是否是括号内文本,返回布尔值
- title_contains(title):判断网页title是否包含文本,返回布尔值
- url_to_be(url):网页网址是否完全等于指定url,返回布尔值
- url_coantains(url):网页网址是否包含指定内容,返回布尔值
- url_matches(url):网页网址是否匹配指定内容,返回布尔值
- presence_of_element_located(locator):判断一个元素是否存在于页面DOM数中,存在则返回元素本身,不存在则返回False;locator是一个(by,path)元组,表示元素位置
- presence_of_all_elements_located(locator):定位的元素范围内,是否有一个元素存在于页面DOM中,如果是,返回满足条件的所有元素组成的list,否则返回False
- visibility_of_element_located(locator):判断一个元素是否存在与页面DOM数中且可见,可见意为元素的高和宽都大于0,存在则返回元素本身,不存在则返回False
- visibility_of(element):判断element是否可见,是返回元素,不存在返回False
- visibility_of_any_elements_located(locator):判断是否至少有一个元素在页面中可见,是返回列表
- invisibility_of_element_located(locator):判断一个元素是否不可见或者不存在页面DOM中,不存在则返回True,
- element_to_be_clickable(locator):判断一个元素是否可见并可点击,如果可以则返回该元素,否则返回False
- element_to_be_selected(element):判断一个元素是否已选择,是返回True
- text_to_be_present_in_element(locator,text):判断一个元素的文本是否包含text,返回布尔值
- text_to_be_present_in_element_value(locator,text):判断一个元素的属性值中是否包含text,返回布尔值
- frame_to_be_available_and_switch_to_it(locator):判断一个frame是否可以切换,如果可以切换frame并且返回True,否则返回False
- staleness_of(element):等待一个元素从页面DOM中消失,如果元素一直存在返回False,否则返回True
- alert_is_present():判断页面上是否有弹窗,如果存在返回弹框,如果不存在返回False
#WebDriverWait and excepted_conditions
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
t1 = EC.title_is("百度一下,你就知道")
t2 = EC.title_contains("我不知道")
print(t1,"\n",t2) #打印方法
print(t1(driver),"\n",t2(driver)) #打印布尔值
locator = (By.CLASS_NAME,"s_ipt") #使用By定位的写法,需要先导入By,定位方式全大写
locator2 = ("class name","s_ipt") #不需要导入By,用下划线连接的名称变为空格分开
e1 = EC.presence_of_element_located(locator2) #一个页面上存在的元素
print(e1) #打印方法
print(e1(driver)) #打印元素
try:
e2 = EC.presence_of_element_located((By.CLASS_NAME,"s_ipt11"))
print(e2)
print(e2(driver))
except Exception as e:
print(e)
e3 = WebDriverWait(driver,10).until(EC.presence_of_element_located(("class name","s_ipt")))
print(e3) #打印元素
driver.quit()