selenium总结 工具介绍 常用方法 动态页面模拟点击 鼠标事件 键盘事件 多表单切换(对于有frame嵌套表单的操作) 多窗口切换 上传文件 下载文件:使用AutoIt实现,--需要安装AutoIt程序,方法同上传 javascript调用,python使用的方法:execute_script() 截图,适用于脚本出错时,对当前窗口进行截图保存,使用函数:get_screenshot_as_file() 关闭窗口 WebElement接口获取值 总结 Selenium:动态页面模拟点击 关于Python 常用获取元素 Driver 总结
-
Selenium
Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器(包括PhantomJS这些*面的浏览器)。
Selenium 可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生。
Selenium 自己不带浏览器,不支持浏览器的功能,它需要与第三方浏览器结合在一起才能使用。但是我们有时候需要让它内嵌在代码中运行,所以我们可以用一个叫 PhantomJS 的工具代替真实的浏览器。
可以从 PyPI 网站下载 Selenium库https://pypi.python.org/simple/selenium ,也可以用 第三方管理器 pip用命令安装:pip install selenium
Selenium 官方参考文档:http://selenium-python.readthedocs.io/index.html
-
PhantomJS
PhantomJS 是一个基于Webkit的“*面”(headless)浏览器,它会把网站加载到内存并执行页面上的 JavaScript,因为不会展示图形界面,所以运行起来比完整的浏览器要高效。
如果我们把 Selenium 和 PhantomJS 结合在一起,就可以运行一个非常强大的网络爬虫了,这个爬虫可以处理 JavaScrip、Cookie、headers,以及任何我们真实用户需要做的事情。
注意:PhantomJS 只能从它的官方网站http://phantomjs.org/download.html) 下载。 因为 PhantomJS 是一个功能完善(虽然*面)的浏览器而非一个 Python 库,所以它不需要像 Python 的其他库一样安装,但我们可以通过Selenium调用PhantomJS来直接使用。
PhantomJS 官方参考文档:http://phantomjs.org/documentation
-
ChromeDriver
ChromeDriver:WebDriver是一个开源工具,用于在许多浏览器上自动测试webapps。ChromeDriver 是 google 为网站开发人员提供的自动化测试接口,它是 selenium2 和 chrome浏览器进行通信的桥梁,驱动谷歌浏览器必须依赖ChromeDriver文件。具体webDriver和ChromeDriver的工作流程
常用方法
Selenium 库里有个叫 WebDriver 的 API。WebDriver 像可以加载网站的浏览器,但是它也可以像 BeautifulSoup 或者其他 Selector 对象一样用来查找页面元素,与页面上的元素进行交互 (发送文本、点击等),以及执行其他动作来运行网络爬虫。
# IPython2 测试代码 # 导入 webdriver from selenium import webdriver # 要想调用键盘按键操作需要引入keys包 from selenium.webdriver.common.keys import Keys # 调用环境变量指定的PhantomJS浏览器创建浏览器对象 driver = webdriver.PhantomJS() # 如果没有在环境变量指定PhantomJS位置 # driver = webdriver.PhantomJS(executable_path="./phantomjs")) # get方法会一直等到页面被完全加载,然后才会继续程序,通常测试会在这里选择 time.sleep(2) driver.get("http://www.baidu.com/") # 获取页面名为 wrapper的id标签的文本内容 data = driver.find_element_by_id("wrapper").text # 打印数据内容 print data # 打印页面标题 "百度一下,你就知道" print driver.title # 生成当前页面快照并保存 driver.save_screenshot("baidu.png") # driver.find_element_by_id("kw").send_keys(u"长城") # 是百度搜索按钮,click() 是模拟点击 driver.find_element_by_id("su").click() # 获取新的页面快照 driver.save_screenshot("长城.png") # 打印网页渲染后的源代码 print driver.page_source # 获取当前页面Cookie print driver.get_cookies() # ctrl+a 全选输入框内容 driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'a') # ctrl+x 剪切输入框内容 driver.find_element_by_id("kw").send_keys(Keys.CONTROL,'x') # 输入框重新输入内容 driver.find_element_by_id("kw").send_keys("itcast") # 模拟Enter回车键 driver.find_element_by_id("su").send_keys(Keys.RETURN) # 清除输入框内容 driver.find_element_by_id("kw").clear() # 生成新的页面快照 driver.save_screenshot("itcast.png") # 获取当前url print driver.current_url # 关闭当前页面,如果只有一个页面,会关闭浏览器 # driver.close() # 关闭浏览器 driver.quit()
页面操作
<input type="text" name="user-name" id="passwd-id" />
# 获取id标签值
element = driver.find_element_by_id("passwd-id")
# 获取name标签值
element = driver.find_element_by_name("user-name")
# 获取标签名值
element = driver.find_elements_by_tag_name("input")
# 也可以通过XPath来匹配
element = driver.find_element_by_xpath("//input[@id='passwd-id']")
定位UI元素 (WebElements)
定位1个元素
find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector
定位1组元素
find_elements_by_id() 如: find_elements_by_id("kw")
find_elements_by_name() 如: find_elements_by_name("wd")
find_elements_by_class_name() 如: find_elements_by_class_name("s_ipt")
find_elements_by_tag_name() 如: find_elements_by_tag_name("input")
find_elements_by_link_text() 如:find_elements_by_link_text(u"新闻")
find_elements_by_partial_link_text() 如:find_elements_by_partial_link_text(u"一个很长的")
find_elements_by_xpath() 如: find_elements_by_xpath(" .//*[@id='kw']")
find_elements_by_css_selector() 如: find_elements_by_css_selector("#kw")
鼠标动作链
模拟一些鼠标操作,比如双击、右击、拖拽甚至按住不动等
#导入 ActionChains 类
from selenium.webdriver import ActionChains
# 鼠标移动到 ac 位置
ac = driver.find_element_by_xpath('element')
ActionChains(driver).move_to_element(ac).perform()
# 在 ac 位置单击
ac = driver.find_element_by_xpath("elementA")
ActionChains(driver).move_to_element(ac).click(ac).perform()
# 在 ac 位置双击
ac = driver.find_element_by_xpath("elementB")
ActionChains(driver).move_to_element(ac).double_click(ac).perform()
# 在 ac 位置右击
ac = driver.find_element_by_xpath("elementC")
ActionChains(driver).move_to_element(ac).context_click(ac).perform()
# 在 ac 位置左键单击hold住
ac = driver.find_element_by_xpath('elementF')
ActionChains(driver).move_to_element(ac).click_and_hold(ac).perform()
# 将 ac1 拖拽到 ac2 位置
ac1 = driver.find_element_by_xpath('elementD')
ac2 = driver.find_element_by_xpath('elementE')
ActionChains(driver).drag_and_drop(ac1, ac2).perform()
填充表单
<select id="status" class="form-control valid" onchange="" name="status"> <option value=""></option> <option value="0">未审核</option> <option value="1">初审通过</option> <option value="2">复审通过</option> <option value="3">审核不通过</option> </select>
# 导入 Select 类
from selenium.webdriver.support.ui import Select
# 找到 name 的选项卡
select = Select(driver.find_element_by_name('status'))
#
select.select_by_index(1)
select.select_by_value("0")
select.select_by_visible_text("未审核")
以上是三种选择下拉框的方式,它可以根据索引来选择,可以根据值来选择,可以根据文字来选择。
- index 索引从 0 开始
- value是option标签的一个属性值,并不是显示在下拉框中的值
- visible_text是在option标签文本的值,是显示在下拉框的值
select.deselect_all() 全部取消选择
弹窗处理
当你触发了某个事件之后,页面出现了弹窗提示,处理这个提示或者获取提示信息方法如下: alert = driver.switch_to_alert()
webdriver中处理js生成的alert、confirm、prompt处理方法是:使用switch_to_alert()定位到alert/confirm/prompt,然后使用text、accept、dismiss、send_keys来根据需要操作。 text:返回alert、confirm、prompt中的文字信息 accept:点击确认按钮 dismiss:点击取消按钮 send_keys:在alert、confirm有对话框时输入值
set_link=dr.find_element_by_xpath("//div[@id='u1']/a[@class='pf']")#找到设置链接元素 ActionChains(dr).move_to_element(set_link).perform()#鼠标移动到设置上 dr.find_element_by_xpath("//a[@class='setpref']").click()#点击搜索设置链接 time.sleep(3) #加等待时间 等按钮可用,否则会报错 save_set=dr.find_element_by_css_selector("#gxszButton > a.prefpanelgo")#获取保存设置按钮 save_set.click()#点击保存设置按钮 alert=dr.switch_to_alert() #进入alert print'----弹出alert中内容为:',alert.text #打印对话框里的文字内容 alert.accept()#对话框里点击alert中确定按钮 #alert.dismiss() #对话框里点击取消按钮 #alert.send_keys("对话框中输入的内容") #在对话框里输入内容
浏览器控制
控制浏览器大小
set_window_size() 例如:driver.set_window_size(400,500)
maximize_window() 例如:driver.maximize_window() #无参数
页面切换
一个浏览器肯定会有很多窗口,所以我们肯定要有方法来实现窗口的切换。切换窗口的方法如下:
driver.switch_to.window("this is window name")
也可以使用 window_handles 方法来获取每个窗口的操作对象。例如:
for handle in driver.window_handles:
driver.switch_to_window(handle)
页面前进和后退
driver.forward() #前进 driver.back() # 后退
Cookies
获取页面每个Cookies值,用法如下: for cookie in driver.get_cookies(): print "%s -> %s" % (cookie['name'], cookie['value']) 删除Cookies,用法如下: # By name driver.delete_cookie("CookieName") # all driver.delete_all_cookies()
页面等待
注意:这是非常重要的一部分!!
现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。
为了避免这种元素定位困难而且会提高产生 ElementNotVisibleException 的概率。所以 Selenium 提供了两种等待方式,一种是隐式等待,一种是显式等待。
隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行。
显式等待
显式等待指定某个条件,然后设置最长等待时间。如果在这个时间还没有找到元素,那么便会抛出异常了。
from selenium import webdriver
from selenium.webdriver.common.by import By
# WebDriverWait 库,负责循环等待
from selenium.webdriver.support.ui import WebDriverWait
# expected_conditions 类,负责条件出发
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("http://www.xxxxx.com/loading")
try:
# 页面一直循环,直到 ))
)
finally:
driver.quit()
如果不写参数,程序默认会 0.5s 调用一次来查看元素是否已经生成,如果本来元素就是存在的,那么会立即返回。
下面是一些内置的等待条件,你可以直接调用这些条件,而不用自己写某些等待条件了。
- title_is
- title_contains
- presence_of_element_located
- visibility_of_element_located
- visibility_of
- presence_of_all_elements_located
- text_to_be_present_in_element
- text_to_be_present_in_element_value
- frame_to_be_available_and_switch_to_it
- invisibility_of_element_located
- element_to_be_clickable – it is Displayed and Enabled.
- staleness_of
- element_to_be_selected
- element_located_to_be_selected
- element_selection_state_to_be
- element_located_selection_state_to_be
- alert_is_present
隐式等待
隐式等待比较简单,就是简单地设置一个等待时间,单位为秒。
from selenium import webdriver
driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("http://www.xxxxx.com/loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")
当然如果不设置,默认等待时间为0。
动态页面模拟点击
获取元素之后,后加 .click() 自动化测试会发生点击对应元素的事件
#!/usr/bin/env python # -*- coding:utf-8 -*- # python的测试模块 import unittest from selenium import webdriver from bs4 import BeautifulSoup class douyuSelenium(unittest.TestCase): # 初始化方法 def setUp(self): self.driver = webdriver.PhantomJS() #具体的测试用例方法,一定要以test开头 def testDouyu(self): self.driver.get('http://www.douyu.com/directory/all') while True: # 指定xml解析 soup = BeautifulSoup(driver.page_source, 'xml') # 返回当前页面所有房间标题列表 和 观众人数列表 titles = soup.find_all('h3', {'class': 'ellipsis'}) nums = soup.find_all('span', {'class': 'dy-num fr'}) # 使用zip()函数来可以把列表合并,并创建一个元组对的列表[(1,2), (3,4)] for title, num in zip(nums, titles): print u"观众人数:" + num.get_text().strip(), u" 房间标题: " + title.get_text().strip() # page_source.find()未找到内容则返回-1 if driver.page_source.find('shark-pager-disable-next') != -1: break # 模拟下一页点击 self.driver.find_element_by_class_name('shark-pager-next').click() # 退出时的清理方法 def tearDown(self): print '加载完成...' self.driver.quit() if __name__ == "__main__": unittest.main()
鼠标事件
ActionChains类提供的常用方法: 1.1 perform():执行ActionChains中存储的所有行为,对整个事件进行提交 1.2 context_click(): 右击 ActionChains(dr).context_click(docfile).perform() 1.3 double_click(): 双击 doubleClick=dr.find_element_by_id("xxx") ActionChains(dr). double_Click(doubleClick).perform() 1.4 drag_and_drop(source,target): 拖动 如: dsource=dr.find_element_by_id("xxx") #拖动的源元素 dtarget=dr.find_element_by_id("xxx") #释放的目标目标元素 ActionChains(dr).drag_and_drop(dsource,dtarget).perform() 1.5 move_to_element(): 鼠标悬停 如: above=dr.find_element_by_id("xxx") ActionChains(dr).move_to_element(above).perform()
键盘事件
# 首先要导入键盘事件的包 from selenium.webdriver.common.keys importKeys dr.get("http://www.baidu.com") #输入内容 dr.find_element_by_id("kw").send_keys("seleniumm") #删除输入内容的最后一个字母, dr.find_element_by_id("kw").send_keys(Keys.BACK_SPACE) #输入:空格+教程 dr.find_element_by_id("kw").send_keys(Keys.SPACE) dr.find_element_by_id("kw").send_keys(u"教程") #ctrl+a全选输入框内容 dr.find_element_by_id("kw").send_keys(Keys.CONTROL,'a') #ctrl+x剪贴输入框内容 dr.find_element_by_id("kw").send_keys(Keys.CONTROL,'x') #ctrl+v剪贴输入框内容 dr.find_element_by_id("kw").send_keys(Keys.CONTROL,'v') #回车键操作 dr.find_element_by_id("su").send_keys(Keys.ENTER)
dr.close()
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+x send_keys(Keys.F1) #F1,类似的有F1-F12
多表单切换(对于有frame嵌套表单的操作)
<html> <body> <frameset> <h3>frame</h3> <iframeid='frameid'name='frameName'width="800"height="500"src="http://www.baidu.com"/> </frameset> </body> </html> dr.get("D:\workspace\pySelenium\resources\frame.htm") dr.switch_to_frame("frameid")#通过frame的id进入iframe #dr.switch_to_frame("frameName") #通过frame的name进入iframe #下面可以对frame进行操作了 dr.find_element_by_id("kw").send_keys("selenium") dr.find_element_by_id("su").click() dr.switch_to_default_content()#退出当前frame返回上一层 1.switch_to_frame()默认直接取表单的id或者name属性来切换 2.完成当前frame表单操作后,可以通过switch_to_default_content()方法返回上一层表单,即离的最近的switch_to_frame()方法 3.对于frame中没有id和name属性的通过下面方式进入frame(定位到frame以页面对象传入)
多窗口切换
selenium-webdriver中使用switch_to_window()方法来切换任意窗口,常用方法有 driver.current_window_handle #获取当前窗口句柄 driver.window_handles #返回所有窗口句柄到当前会话 driver.switch_to_window() #进入窗口,用于切换不同窗口 dr.get("http://www.baidu.com") current_handle=dr.current_window_handle #获取百度首页窗口句柄 index_login=dr.find_element_by_xpath("//div[@id='u1']/a[@class='lb']")#获取登录按钮对象 index_login.click()#点击登录 dr.implicitly_wait(5) dr.find_element_by_class_name("pass-reglink").click()#点击立即注册按钮 all_handles=dr.window_handles #获取所有打开窗口句柄 for handle in all_handles: if handle==current_handle: dr.switch_to_window(handle) ''' ...对首页窗口进行操作 ''' print'----首页页面title:',dr.title for handle in all_handles: if handle!=current_handle: dr.switch_to_window(handle) ''' ...对注册窗口进行操作 ''' print'----注册页面title:',dr.title
上传文件
分2种:普通上传、插件上传 普通上传:将本地文件的路径作为一个值放到input标签中,通过form表单提交时,将值传给服务器中去 插件上传:指基于flash、javascript或ajax技术实现的上传功能或插件。 1.针对普通上传用send_keys实现: dr.get("D:\workspace\pySelenium\resources\upload.htm") loadFile=dr.find_element_by_name("filebutton")# 获取上传文件input元素节点 loadFile.send_keys("D:\workspace\pySelenium\resources\frame.htm")#输入上传文件地址来实现上传 2.插件上传:使用AutoIt实现,--需要安装AutoIt程序 AutoIt安装,使用暂时略,需要时再追加,流程为:用AutoIt编写上传文件脚本生成exe文件,在python脚本中进行调用: loadFile=dr.find_element_by_name("filebutton")# 获取上传按钮 loadFile.click() #点击上传按钮,弹出上传对话框 os.system("D:\autoItFile.exe") #调用autoIt生成的exe文件,实现导入
下载文件:使用AutoIt实现,--需要安装AutoIt程序,方法同上传
ffp=webdriver.FirefoxProfile() ffp.set_preference("browser.download.folderList",2)#0:代表下载到浏览器默认路径下;2:下载到指定目录 ffp.set_preference("browser.download.manager.showWhenStarting",False)#是否显示开始:True:显示;False:不显示 ffp.set_preference("browser.download.dir", os.getcwd())#指定下载文件目录,os.getcwd()无参数,返回当前目录 # ffp.set_preference("browser.helperApps.neverAsk.saveToDisk","application/octet-stream")#下载文件类型, #指定下载页面的content-type值,application/octet-stream为文件类型,http-content-type常用对照表搜索百度 dr=webdriver.Firefox(firefox_profile=ffp) dr.get("https://pypi.python.org/pypi/selenium#downloads") dr.find_element_by_xpath("//div[@id='content']/div[3]/table/tbody/tr[3]/td[1]/span/a[1]").click() #接下来使用autoIt实现
javascript调用,python使用的方法:execute_script()
dr.get("http://www.baidu.com") dr.find_element_by_id("kw").send_keys("selenium") dr.find_element_by_id("su").click() js="var q=document.documentElement.scrollTop=1000" #滚动条滚到最下面 dr.execute_script(js) time.sleep(4) js2="var q=document.documentElement.scrollTop=0" #滚动条滚到页面顶 dr.execute_script(js2)
截图,适用于脚本出错时,对当前窗口进行截图保存,使用函数:get_screenshot_as_file()
dr.get("http://www.baidu.com") try: dr.find_element_by_id("kw1").send_keys("selenium") dr.find_element_by_id("su").click() exceptNoSuchElementException,msg: dr.get_screenshot_as_file("d:\error.jpg") #截图输出到d盘 print msg dr.close()
关闭窗口
quit():退出相关驱动程序并关闭所有窗口。
close():关闭当前窗口,打给多个窗口时,可使用来关闭当前窗口
WebElement接口获取值
size 获取元素的尺寸
text 获取元素的文本
get_attribute(name) 获取属性值
location 获取元素坐标,先找到要获取的元素,再调用该方法
page_source 返回页面源码
driver.title 返回页面标题
current_url 获取当前页面的URL
is_displayed() 设置该元素是否可见
is_enabled() 判断元素是否被使用
is_selected() 判断元素是否被选中
tag_name 返回元素的tagName
总结
新建实例driver = webdriver.Chrome() 1.获取当前页面的Url函数 方法:current_url 实例: driver.current_url 2.获取元素坐标 方法:location 解释:首先查找到你要获取元素的,然后调用location方法 实例: driver.find_element_by_xpath("//*[@id='tablechart']/tbody/tr[14]/td[9]").location 3.表单的提交 方法:submit 解释:查找到表单(from)直接调用submit即可 实例: driver.find_element_by_id("form1").submit() 4.获取CSS的属性值 方法:value_of_css_property(css_name) 实例: driver.find_element_by_css_selector("input.btn").value_of_css_property("input.btn") 5.获取元素的属性值 方法:get_attribute(element_name) 实例: driver.find_element_by_id("sellaiyuan").get_attribute("sellaiyuan") 6.判断元素是否被选中 方法:is_selected() 实例: driver.find_element_by_id("form1").is_selected() 7.返回元素的大小 方法:size 实例: driver.find_element_by_id("iptPassword").size 返回值:{'width': 250, 'height': 30} 8.判断元素是否显示 方法:is_displayed() 实例: driver.find_element_by_id("iptPassword").is_displayed() 9.判断元素是否被使用 方法:is_enabled() 实例: driver.find_element_by_id("iptPassword").is_enabled() 10.获取元素的文本值 方法:text 实例:driver.find_element_by_id("iptUsername").text 11.元素赋值 方法:send_keys(*values) 实例: driver.find_element_by_id("iptUsername").send_keys('admin') 注意如果是函数需要增加转义符u,eg. driver.find_element_by_id("iptUsername").send_keys(u'青春') 12.返回元素的tagName 方法:tag_name 实例: driver.find_element_by_id("iptUsername").tag_name 13.删除浏览器所以的cookies 方法:delete_all_cookies() 实例: driver.delete_all_cookies() 14.删除指定的cookie 方法:delete_cookie(name) 实例:deriver.delete_cookie("my_cookie_name") 15.关闭浏览器 方法:close() 实例:driver.close() 16.关闭浏览器并且推出驱动程序 方法:quit() 实例:driver.quit() 17.返回上一页 方法:back() 实例:driver.back() 18.设置等待超时 方法:implicitly_wait(wait_time) 实例:driver.implicitly_wait(30) 19.浏览器窗口最大化 方法:maximize_window() 实例:driver.maximize_window() 20.查看浏览器的名字 方法:name 实例:drvier.name
参考原文链接: