Selenium是一个用于Web应用程序测试的工具。你可以通过在程序中获取前端界面的元素,用代码定义输入内容,点击事件,模拟鼠标位置等操作来模拟人在浏览器中的操作过程。通过在程序中打断点,可以看到具体的看到浏览器每一步的操作
比如,我们想在网页上实现某一元素的点击效果。首先我们在在程序中定义点击行为,然后程序将命令发送给浏览器驱动,浏览器驱动将此命令发送给浏览器,浏览器将响应数据返回回来。
具体的流程如下:
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>
9.多窗口的切换
在页面操作过程中有时候点击某个链接会弹出新的窗口,这时就需要主机切换到新打开的窗口上进行操作。WebDriver提供了switch_to.window()方法,可以实现在不同的窗口之间切换,需要注意的是可以切换的窗口都是已经打开的窗口。 以百度首页和百度登录页为例,在两个窗口之间的切换如下图。
sreach_windows = chromeDriver.current_window_handle#获取当前窗口句柄(百度首页)
chromeDriver.find_element_by_link_text('登录').click()#打开登录界面
# 获得当前所有打开的窗口的句柄
all_handles = driver.window_handles
# 进入注册窗口
for handle in all_handles:
if handle != sreach_windows:#当前页面不是百度首页
driver.switch_to.window(handle)#跳转到登录窗口
print('now register window!')
driver.find_element_by_name("account").send_keys('username')
driver.find_element_by_name('password').send_keys('password')
time.sleep(2)
# ……
driver.quit()
方法 | 说明 |
---|---|
current_window_handle | 获得当前窗口句柄。 |
window_handles|返回所有窗口的句柄到当前会话。
switch_to.window()|用于切换到相应的窗口,与上一节的switch_to.frame()类似,前者用于不同窗口的切换,后者用于不同表单之间的切换。
10.警告框的处理
在WebDriver中处理JavaScript所生成的alert、confirm以及prompt十分简单,具体做法是使用 switch_to.alert 方法定位到 alert/confirm/prompt,然后主要使用一下几种方法进行操作
方法 | 说明 |
---|---|
text | 返回 alert/confirm/prompt 中的文字信息。 |
accept() | 接受现有警告框。 |
dismiss() | 解散现有警告框。 |
send_keys(keysToSend) | 发送文本至警告框。keysToSend:将文本发送至警告框。 |
#效果等同于警告框点击接收
chromeDriver.switch_to.alert.accept()
11.下拉框的选择
WebDriver提供了Select类来处理下拉框:
Select类用于定位select标签。
select_by_value() 方法用于定位下接选项中的value值。
from selenium.webdriver.support.select import Select
Select(sel).select_by_value('50') # 定位到value为50的选项中
12.文件上传
文件上传就是一个type为file类型的input控件从send_key(‘文件路径’)方法接收到了一个文件,然后上传。
<input type="file" name="file" />
# 定位上传按钮,添加本地文件
chromeDriver.find_element_by_name("file").send_keys(r'文件路径')
13.Cookie操作
WebDriver提供了操作Cookie的相关方法,可以读取、添加和删除cookie信息。
网页爬虫经常遇到的问题就是登录账户,有些简单的网站我们可以简单的send key来输入账户密码就可以登录,但是有很多网站需要验证码之类的就不太好用了,这时候就体现到了cookie登录的优点了
方法 | 说明 | 用法 |
---|---|---|
get_cookies() | 获得所有cookie信息。 | cookie= chromeDriver.get_cookies() |
add_cookie(cookie_dict) | 添加cookie。“cookie_dict”指字典对象,必须有name 和value 值 | driver.add_cookie({‘name’: ‘key-aaaaaaa’, ‘value’: ‘value-bbbbbb’}) |
get_cookie(name) | 返回字典的key为“name”的cookie信息 | … |
delete_cookie(name,optionsString) | 删除cookie信息。“name”是要删除的cookie的名称,“optionsString”是该cookie的选项,目前支持的选项包括“路径”,“域” | '… |
delete_all_cookies() | 删除所有cookie信息。 | … |
14.javascript代码调用
<!-- window.scrollTo(左边距,上边距); -->
window.scrollTo(0,450);
#设置浏览器窗口的滚动条位置
chromeDriver.execute_script(js)
完结
胸中有丘壑 立马见山河