1 多标签
当我们从一个网站上点击一个链接之后,可能会弹出一个新的窗口,我们手动测试可以直接选中弹出的窗口进行操作,但是计算机不可以,计算机需要在多个标签之间进行切换,接下来我们就学习下如何实现
1.获取所有的标签句柄列表
driver.window_handles
2.切换到指定标签
driver.switch_to_window(driver.window_handles[1])
3.switch_to(更为推荐的方法)
driver.switch_to.window(driver.window_handles[n])
练习案例
from selenium import webdriver
import time
driver = webdriver.Firefox()
url = 'http://bj.58.com'
driver.get(url)
# 打印点击之前的窗口句柄列表
print('点击之前的窗口句柄:',driver.window_handles)
print('当前的url:',driver.current_url,'当前的标题:',driver.title)
# 定位到房屋出租,点击
el = driver.find_element_by_link_text('房屋出租')
el.click()
print('-------------------------------------------------------------')
# 获取到所有的窗口
handles = driver.window_handles
print('点击之后的窗口句柄:',handles)
print('当前的url:',driver.current_url,'当前的标题:',driver.title)
# 切换到新开窗口
driver.switch_to.window(handles[1])
print('切换之后的窗口句柄:',handles)
print('当前的url:',driver.current_url,'当前的标题:',driver.title)
try:
# 定位一个再新窗口页面上的元素,如果能够定位到,则表明当前在新窗口上,如果失败则表明现在不在新窗口上
el = driver.find_element_by_css_selector('.listUl > li:nth-child(1) > div:nth-child(2) > h2:nth-child(1) > a:nth-child(1)')
print (el.text)
print('driver在新页面')
except:
print('没有在新页面')
try:
# 定位一个在就窗口上的元素,如果能够定位到,则表明现在在就窗口上
el = driver.find_element_by_css_selector('div.col3:nth-child(2) > em:nth-child(1) > a:nth-child(1)')
print (el.text)
print('driver在旧页面')
except:
print('没有在旧页面')
2 多表单切换
在Web应用中经常会遇到frame/iframe表单嵌套页面的应用,WebDriver只能在一个页面上对元素识别与定位,对于frame/iframe表单内嵌页面上的元素无法直接定位。这时就需要通过switch_to.frame()方法将当前定位的主体切换为frame/iframe表单的内嵌页面中。
1.switch_to.frame() 默认可以直接取表单的id 或name属性。如果iframe没有可用的id和name属性,则可以通过下面的方式进行定位。
from selenium import webdriver
import time
url = 'http://www.126.com/'
driver = webdriver.Firefox()
# 访问126邮箱
driver.get(url)
time.sleep(5)
# 直接通过id进入
driver.switch_to.frame('x-URS-iframe')
# 先定位到元素再进入
el_frame = driver.find_element_by_id('x-URS-iframe')
driver.switch_to.frame(el_frame)
try:
# 定位并输入账号
el_user = driver.find_element_by_name('email')
el_user.send_keys('itcast_soft_test')
# 定位并输入密码
el_pwd = driver.find_element_by_name('password')
el_pwd.send_keys('1qaz2wsx#EDC')
# 定位并点击登录
el_sub = driver.find_element_by_id('dologin')
el_sub.click()
time.sleep(5)
except:
print ('页面上没有账号密码输入框')
driver.quit()
2.driver.switch_to.default_content()
跳回最外层的页面。
3.driver.switch_to.parent_frame()
跳回上层的页面。
案例(此案例需配合文件运行):
from selenium import webdriver
import os
import time
file_path = 'file:///' + os.path.abspath('example_frame.html')
print (file_path)
driver = webdriver.Firefox()
# 加载本地html文件
driver.get(file_path)
# 进入到第一层表单,通过id值
driver.switch_to.frame('itcast_frame1')
time.sleep(5)
# 进入到第二层表单,通过元素定位
driver.switch_to.frame('itcast_frame2')
time.sleep(5)
# 定位到搜索栏标签
el_input = driver.find_element_by_id('sb_form_q')
el_input.send_keys('selenium')
el_sub = driver.find_element_by_id('sb_form_go')
el_sub.submit()
time.sleep(5)
driver.switch_to.parent_frame()
try:
el_input = driver.find_element_by_id('sb_form_q')
except:
print('已经退出到上级表单')
3 鼠标&键盘操作
当我们进行手动测试的时候,有的时候我们可能会实现双击,拖动等操作,在 WebDriver 中, 将这些关于鼠标操作的方法封装在 ActionChains 类提供。
1.鼠标操作
导入类
from selenium.webdriver import ActionChains # 导入类
ActionChains(driver) # 调用 ActionChains()类, 将浏览器驱动 driver 作为参数传入。
perform() 执行所有 ActionChains 中存储的行为(接在ActionChains类之后)
右击 context_click()
from selenium import webdriver
# 导入动作链
from selenium.webdriver import ActionChains
import time
url = 'http://www.baidu.com'
driver = webdriver.Firefox()
driver.get(url)
# 创建动作池对象
acobj = ActionChains(driver)
# 定位到百度的logo图片
el_lg = driver.find_element_by_id('lg')
# 添加邮件点击动作并执行
acobj.context_click(el_lg).perform()
# print (dir(acobj))
time.sleep(5)
driver.close()
双击 double_click()
from selenium import webdriver
# 导入动作链
from selenium.webdriver import ActionChains
import time
url = 'http://www.baidu.com'
driver = webdriver.Firefox()
driver.get(url)
# 创建动作对象
acobj = ActionChains(driver)
# 定位到视频元素
el = driver.find_element_by_css_selector('a.mnav:nth-child(1)')
# 执行双击操作
acobj.double_click(el).perform()
time.sleep(5)
driver.quit()
鼠标悬停 move_to_element()
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
url = 'https://www.jd.com/'
driver = webdriver.Firefox()
driver.get(url)
#获取左侧种类元素列表
mylist = driver.find_elements_by_css_selector('li.cate_menu_item')
# print (mylist)
# 创建动作动作对象
acobj = ActionChains(driver)
for el in mylist:
acobj.move_to_element(el).perform()
time.sleep(3)
driver.close()
2.键盘事件
Keys()类提供了键盘上几乎所有按键的方法。 前面了解到, send_keys()方法可以用来模拟键盘输入, 除此 之外, 我们还可以用它来输入键盘上的按键, 甚至是组合键, 如 Ctrl+A、 Ctrl+C 等。
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
# print (dir(Keys))
url = 'https://cn.bing.com/'
driver = webdriver.Firefox()
driver.get(url)
el = driver.find_element_by_id('sb_form_q')
el.send_keys('selenium')
# 全选并删除
el.send_keys(Keys.CONTROL,'a')
time.sleep(3)
el.send_keys(Keys.CONTROL,'x')
# 退格并回车
el.send_keys('seleniumm')
time.sleep(3)
el.send_keys(Keys.BACK_SPACE)
time.sleep(3)
el.send_keys(Keys.ENTER)
time.sleep(5)
driver.quit()
以下为常用的键盘操作:
send_keys(Keys.BACK_SPACE) 删除键(BackSpace)
send_keys(Keys.SPACE) 空格键(Space)
send_keys(Keys.TAB) 制表键(Tab)
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,‘x’) 剪切(Ctrl+X)
send_keys(Keys.CONTROL,‘v’) 粘贴(Ctrl+V)
send_keys(Keys.F1) 键盘 F1
……
send_keys(Keys.F12) 键盘 F12
4 弹出框(警告框)
在WebDriver中处理JavaScript所生成的alert、confirm以及prompt十分简单,具体做法是使用 switch_to.alert 方法定位到 alert/confirm/prompt,然后使用text/accept/dismiss/ send_keys等方法进行操作
进入到警告框中
driver.switch_to.alert #当出现弹出框的时候,可以使用条语句进入到警告框中
text:返回 alert/confirm/prompt 中的文字信息。
accept():接受现有警告框。
dismiss():解散现有警告框。
send_keys(keysToSend):发送文本至警告框。keysToSend:将文本发送至警告框。
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
url = 'http://www.baidu.com'
# 创建浏览器对象
driver = webdriver.Firefox()
# 访问百度
driver.get(url)
# 点击设置
el_set = driver.find_element_by_link_text('设置')
el_set.click()
# 点击搜索设置
el_sset = driver.find_element_by_link_text('搜索设置')
el_sset.click()
# 定位到保存按钮
el_save = driver.find_element_by_css_selector('.prefpanelgo')
el_save.click()
# 进入到弹出框,执行接受
time.sleep(3)
# driver.switch_to.alert.accept()
driver.switch_to.alert.dismiss()
time.sleep(5)
driver.quit()
5 下拉框
有时我们手动测试的时候会碰到下拉框,WebDriver提供了Select类来处理下拉框
from selenium import webdriver
from selenium.webdriver.support.select import Select
import time
url = 'http://www.baidu.com'
driver = webdriver.Firefox()
driver.get(url)
# 定位搜索按钮
el_so = driver.find_element_by_css_selector('a.pf:nth-child(8)')
el_so.click()
# 定位搜索设置按钮,并点击
el_set = driver.find_element_by_css_selector('.setpref')
el_set.click()
# 定位下拉框对象
sel = driver.find_element_by_id('nr')
# 构建选择对象
selobj = Select(sel)
# print(selobj)
# print(dir(selobj))
# 显示所有已经选择的选项
print (selobj.all_selected_options)
# 显示第一个已经选择的选项
print (selobj.first_selected_option)
# 显示所有选项
print (selobj.options)
# 使用索引选择
selobj.select_by_index(0)
time.sleep(5)
selobj.select_by_index(1)
time.sleep(5)
selobj.select_by_index(2)
# 通过值进行选择
selobj.select_by_value("20")
time.sleep(2)
selobj.select_by_value("50")
# 通过可见文本
selobj.select_by_visible_text('每页显示50条')
time.sleep(2)
selobj.select_by_visible_text('每页显示20条')
time.sleep(5)
driver.close()
Select类用于定位select标签。 select_by_value() 方法用于定位下接选项中的value值。
6 调用JavaScript代码
虽然WebDriver提供了操作浏览器的前进和后退方法,但对于浏览器滚动条并没有提供相应的操作方法。在这种情况下,就可以借助JavaScript来控制浏览器的滚动条。WebDriver提供了execute_script()方法来执行JavaScript代码。
用于调整浏览器滚动条位置的JavaScript代码如下:
window.scrollTo(0,450); window.scrollTo()方法用于设置浏览器窗口滚动条的水平和垂直位置。方法的第一个参数表示水平的左间距,第二个参数表示垂直的上边距。其代码如下:
from selenium import webdriver
import time
url = 'https://www.hao123.com/'
driver = webdriver.Firefox()
driver.get(url)
for i in range(100):
# 滚动到固定位置
js = 'window.scrollTo(0,%s)'%(100*i)
# 滚动到距离顶部指定长度
# js = "var q=document.documentElement.scrollTop=%s"%(100*i)
driver.execute_script(js)
time.sleep(0.1)
time.sleep(5)
driver.quit()
通过浏览器打开百度进行搜索,然后通过execute_script()方法执行JavaScripts代码来移动滚动条的位置。
7 等待
现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。
为了避免这种元素定位困难而且会提高产生 ElementNotVisibleException 的概率。所以 Selenium 提供了两种等待方式,一种是隐式等待,一种是显式等待。
隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行。
1.显式等待
显式等待使WebdDriver等待某个条件成立时继续执行,否则在达到最大时长时抛出超时异常(TimeoutException)。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
url = 'http://www.baidu.com'
driver = webdriver.Firefox()
driver.get(url)
# 设置显示等待
el = WebDriverWait(driver, 60, 0.5).until(EC.presence_of_element_located((By.CSS_SELECTOR,'#lh > a:nth-child(3)')))
print (el.text)
driver.close()
WebDriverWait类是由WebDirver 提供的等待方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常。具体格式如下:
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
driver :浏览器驱动。
timeout :最长超时时间,默认以秒为单位。
poll_frequency :检测的间隔(步长)时间,默认为0.5S。
ignored_exceptions :超时后的异常信息,默认情况下抛NoSuchElementException异常。
WebDriverWait()一般由until()或until_not()方法配合使用,下面是until()和until_not()方法的说明。 until(method, message=‘’) 调用该方法提供的驱动程序作为一个参数,直到返回值为True。 until_not(method, message=‘’) 调用该方法提供的驱动程序作为一个参数,直到返回值为False。
在本例中,通过as关键字将expected_conditions 重命名为EC,并调用presence_of_element_located()方法判断元素是否存在。
2.隐式等待
WebDriver提供了implicitly_wait()方法来实现隐式等待,默认设置为0。如果不设置隐式等待的值,那么当我们进行元素定位的时候,一旦定位不到将会直接报错出来,而如果我们设置了隐式等待的值,当定位不到元素的时候,程序将在隐式等待设定时间内多次尝试定位元素,当时间超过设定的隐式等待时间,将会报错出来,它的用法相对来说要简单得多
from selenium import webdriver
import time
url = 'https://www.amazon.cn/'
driver = webdriver.Firefox()
driver.get(url)
# 设置隐式等待
driver.implicitly_wait(10)
driver.quit()
implicitly_wait()默认参数的单位为秒,本例中设置等待时长为10秒。首先这10秒并非一个固定的等待时间,它并不影响脚本的执行速度。其次,它并不针对页面上的某一元素进行等待。当脚本执行到某个元素定位时,如果元素可以定位,则继续执行;如果元素定位不到,则它将以轮询的方式不断地判断元素是否被定位到。假设在第6秒定位到了元素则继续执行,若直到超出设置时长(10秒)还没有定位到元素,则抛出异常。
8 cookies
有时候我们需要验证浏览器中cookie是否正确,因为基于真实cookie的测试是无法通过白盒和集成测试进行的。WebDriver提供了操作Cookie的相关方法,可以读取、添加和删除cookie信息。
WebDriver操作cookie的方法:
get_cookies(): 获得所有cookie信息。
get_cookie(name): 返回字典的key为“name”的cookie信息。
add_cookie(cookie_dict) : 添加cookie。“cookie_dict”指字典对象,必须有name 和value 值。
delete_cookie(name,optionsString):删除cookie信息。“name”是要删除的cookie的名称,“optionsString”是该cookie的选项,目前支持的选项包括“路径”,“域”。
delete_all_cookies(): 删除所有cookie信息。
下面通过get_cookies()来获取当前浏览器的cookie信息。
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.youdao.com")
# 获得cookie信息
cookie= driver.get_cookies()
# 将获得cookie的信息打印
print(cookie)
driver.quit()
从执行结果可以看出,cookie数据是以字典的形式进行存放的。知道了cookie的存放形式,接下来我们就可以按照这种形式向浏览器中写入cookie信息。
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.youdao.com")
# 向cookie的name 和value中添加会话信息
driver.add_cookie({'name': 'itcast', 'value': 'itheima'})
# 遍历cookies中的name 和value信息并打印,当然还有上面添加的信息
for cookie in driver.get_cookies():
print("%s -> %s" % (cookie['name'], cookie['value']))
driver.quit()