Selenium框架的使用

什么是Selenium

Selenium是一个用于Web应用程序测试的工具。你可以通过在程序中获取前端界面的元素,用代码定义输入内容,点击事件,模拟鼠标位置等操作来模拟人在浏览器中的操作过程。通过在程序中打断点,可以看到具体的看到浏览器每一步的操作

Selenium原理及流程

程序
浏览器驱动
浏览器

比如,我们想在网页上实现某一元素的点击效果。首先我们在在程序中定义点击行为,然后程序将命令发送给浏览器驱动,浏览器驱动将此命令发送给浏览器,浏览器将响应数据返回回来。
具体的流程如下:
selenium 自动化流程如下:
1.程序调用Selenium 客户端库函数(比如点击按钮元素)
2.客户端库会发送Selenium 命令 给浏览器的驱动程序
3.浏览器驱动程序接收到命令后 ,驱动浏览器去执行命令
4.浏览器执行命令
5.浏览器驱动程序获取命令执行的结果,返回给我们自动化程序
6.自动化程序对返回结果进行处理
引用库

pip install selenium

浏览器驱动下载地址:

https://chromedriver.storage.googleapis.com/index.html

须知,浏览器驱动的类型与版本必须与您所使用的浏览器严格对应,比如谷歌85.0.4183.83需下载谷歌驱动85.0.4183.83

正文开始

1.创建浏览器实例

from selenium import WebDriver
#支持多种浏览器的模拟
chromeDriver=WebDriver.Chrome()
firefoxDriver=webdriver.Firefox()
safariDriver=webdriver.Safari()
edgeDriver=webdriver.Edge()

#设置浏览器窗口大小宽*高
chromeDriver.set_window_size(480, 800)
#全屏显示
chromeDriver.maximize_window()

#获取当前页面的title
chromeDriver.title
#获取当前页面的url
chromeDriver.current_url

#关闭当前这个窗口
chromeDriver.close()

#关闭浏览器所有窗口
chromeDriver.quit()
 

2.get访问网址

#访问百度主页
chromeDriver.get('https:www.baidu.com')

3.定位元素
得到网站的数据以后就应该定位到我们想获取的元素
Selenium提供了8种定位方式。
以此为例:

<html>
  <head>
  <body link="#0000cc">
    <a id="result_logo" href="/" onmousedown="return c({
      'fm':'tab','tab':'logo'})">
    <form id="form" class="fm" name="f" action="/s">
      <span class="soutu-btn">span>
        <input id="kw" class="s_ipt" name="wd" value="" maxlength="255" autocomplete="off">
定位方式 单个元素定位:返回找到的第一个 多个元素定位 :返回找的所有 使用说明
id find_element_by_id() find_elements_by_id() find_element_by_id("kw")
name find_element_by_name() find_elements_by_name() dr.find_element_by_name("wd")
class name 类名 find_element_by_class_name() find_elements_by_class_name() dr.find_element_by_class_name("s_ipt")
tag name 标签名 find_element_by_tag_name() find_elements_by_tag_name() dr.find_element_by_tag_name("input")
link text 超链接的完整文本 find_element_by_link_text() find_elements_by_link_text() find_element_by_link_text("hao123")
partial link text 超连接部分文本 find_element_by_partial_link_text() find_elements_by_partial_link_text() find_element_by_link_text("hao")
xpath find_element_by_xpath() find_elements_by_xpath() dr.find_element_by_xpath("//*[@id='kw']") dr.find_element_by_xpath("//*[@name='wd']") dr.find_element_by_xpath("//input[@class='s_ipt']") dr.find_element_by_xpath("/html/body/form/span/input") dr.find_element_by_xpath("//span[@class='soutu-btn']/input") dr.find_element_by_xpath("//form[@id='form']/span/input") dr.find_element_by_xpath("//input[@id='kw' and @name='wd']")
css selector CSS选择器 find_element_by_css_selector() find_elements_by_css_selector() dr.find_element_by_css_selector("#kw") dr.find_element_by_css_selector("[name=wd]") dr.find_element_by_css_selector(".s_ipt") dr.find_element_by_css_selector("html > body > form > span > input") dr.find_element_by_css_selector("span.soutu-btn> input#kw") dr.find_element_by_css_selector("form#form > span > input")

具体XPath的使用方法请参考:

https://www.w3school.com.cn/xpath/xpath_syntax.asp

4.常用方法

方法 说明
chromeDriver.forward() 网页前进
chromeDriver.back() 网页后退
element.clear() 清除文本
element.send_keys (value) 模拟输入文本,如模拟输入账号,密码
element.click() 触发元素的点击事件
element.submit() 提交一个表单,或模拟click()方法
element.size 获取元素的尺寸
element.text 获取元素的文本
element.get_attribute(name) 获取一个元素的属性值
element.is_displayed() 返回元素是否可见

注:”WebDriver前进与后退必须是对于已经访问过的页面,相当于浏览器的←,→
有时候 submit()可以与 click()方法互换来使用, submit()同样可以提交一个按钮, 但 submit()的应用范围远不及 click()广泛。
5.鼠标事件
在WebDriver中,关于模拟鼠标的操作,已经将它封装在了ActionChains类(动作链)中
类的引入:

# 引入 ActionChains 类
from selenium.webdriver.common.action_chains import ActionChains
#实现鼠标悬停操作,
#1.ActionChains(chromeDriver) 调用 ActionChains()类, 将浏览器驱动 chromeDriver作为参数传入。
#2.move_to_element(element) 将鼠标停留在元素element上
#3.执行所有 ActionChains 中存储的行为, 可以理解成是对整个操作的提交动作
ActionChains(chromeDriver).move_to_element(element).perform()

#实现拖动操作
ActionChains(chromeDriver).drag_and_drop(sourcelement,targetelement).perform()

方法 说明
perform() 执行所有 ActionChains 中存储的行为
context_click() 右击
double_click() 双击
drag_and_drop() 拖动
move_to_element() 悬停

6.键盘事件
同样,我们将引用Key()类来模拟键盘的各种操作,如,CTRL+A,CTRL+C ,CTRL+V

项目 Value
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

7.设置等待
为什么要等待?
大多数Web应用程序都是使用Ajax和Javascript开发的。当浏览器加载页面时,我们想要与之交互的元素可能以不同的时间间隔加载。
它不仅难以识别元素,而且如果元素未定位,它将抛出“ ElementNotVisibleException ”异常。使用Waits,我们可以解决此问题。
让我们考虑一个场景,我们必须在测试中使用隐式和显式等待。假设隐式等待时间设置为20秒,显式等待时间设置为10秒。
假设我们试图找到一个具有一些“ExpectedConditions ”(显式等待)的元素,如果该元素不在显式等待(10秒)定义的时间范围内,它将使用由隐式等待定义的时间帧(在抛出“ ElementNotVisibleException ” 之前20秒)。
区别分析:

隐式等待 显示等待
隐式等待时间应用于脚本中的所有元素 显式等待时间仅适用于我们想要的那些元素
在隐等待,我们需要不指定元素的“ExpectedConditions”被定位 在显式等待中,我们需要在要定位的元素上指定“ExpectedConditions”
建议在使用隐式等待中指定的时间帧定位元素时使用 建议在元素花费很长时间加载时使用,也用于验证元素的属性,如(visibilityOfElementLocated,elementToBeClickable,elementToBeSelected)

隐式等待
WebDriver提供了implicitly_wait()方法来实现隐式等待,默认设置为0

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from time import ctime

driver = webdriver.Firefox()

# 设置隐式等待为10秒
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")

try:
    print(ctime())#打印当前时间
    driver.find_element_by_id("kw22").send_keys('selenium')
    #查找id为kw22的元素,隐式等待10秒
except NoSuchElementException as e:
    print(e)
finally:
    print(ctime())#打印当前时间
    driver.quit()

补充:implicitly_wait() 默认参数的单位为秒,本例中设置等待时长为10秒。首先这10秒并非一个固定的等待时间,它并不影响脚本的执行速度。其次,它并不针对页面上的某一元素进行等待。当脚本执行到某个元素定位时,如果元素可以定位,则继续执行;如果元素定位不到,则它将以轮询的方式不断地判断元素是否被定位到。假设在第6秒定位到了元素则继续执行,若直到超出设置时长(10秒)还没有定位到元素,则抛出异常
显示等待
显式等待使WebdDriver等待某个条件成立时继续执行,否则在达到最大时长时抛出超时异常(TimeoutException);它只能应用于指定元素;一旦我们声明显式等待,我们必须使用“ ExpectedCondtions ”,或者我们可以配置我们想要使用Fluent Wait检查条件的频率。Thread.Sleep()通常不建议使用

WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)

参数 说明
driver 浏览器驱动
timeout 最长超时时间,默认以秒为单位。
poll_frequency 检测的间隔(步长)时间,默认为0.5S。
ignoree_exceptions 超时后的异常信息,默认情况下抛NoSuchElementException异常。

until(method, message=‘’) 调用该方法提供的驱动程序作为一个参数,直到返回值为Tru

until_not(method, message=‘’)调用该方法提供的驱动程序作为一个参数,直到返回值为False。

presence_of_element_located()方法判断元素是否存在

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

driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
#每0.5秒验证一次id为kw的是否找到,超过5秒抛出异常
element = WebDriverWait(driver, 5, 0.5).until(
                      EC.presence_of_element_located((By.ID, "kw"))
                      )
element.send_keys('selenium')
driver.quit()

8.多表单的切换
在Web应用中经常会遇到frame/iframe表单嵌套页面的应用,WebDriver只能在一个页面上对元素识别与定位,对于frame/iframe表单内嵌页面上的元素无法直接定位。这时就需要通过switch_to.frame()方法将当前定位的主体切换为frame/iframe表单的内嵌页面中。
比如:

<html>
	<body>
		<p>外层p>