webdriver actionchains 和 TouchActions 的鼠标操作+键盘操作 + 等待 一系列操作
1.1 actionchains
1.1.1 actionchains官方文档: https://selenium-python.readthedocs.io/api.html
- ActionChains: 执行PC端的鼠标点击、双击、右键、拖拽等事件
- TouchActions: 模拟PC和移动端的点击、滑动、拖拽、多点触控等多种手势操作
1.1.2 动作链接actionchains
执行原理:
调用ActionChains的方法时,不会立即执行,而是将所有的操作,按顺序存放到一个队列中,当调用perform()方法时,队列中的事件会依次执行
基本方法:
- 生成一个动作:action = ActionChains(driver)
- 动作添加方法1: action.方法1
- 动作添加方法2: action.方法2
- 调用perform()方法执行: action.perform()
具体写法:
链式写法: ActionChains(driver).move_to_element(element).click(element).perform()
分步写法:
- actions = ActionChains(driver)
- actions.move_to_element(element)
- actions.click(element)
- actions.perform()
1.1.3 用法实战
用法一: 点击、右键、双击操作
- action = ActionChains(driver)
- action.click(element)
- action.double_click(element)
- action.context_click(element)
- action.perform()
- 打开页面:http://sahitest.com/demo/clicks.htm
- 分别对按钮‘click me’,\’dbl click me\’,\’right click me\’ 执行 点击、双击、右键操作
- 打印上面展示框中的内容
from time import sleep from selenium import webdriver from selenium.webdriver import ActionChains class TestActionChains: def setup(self): self.driver = webdriver.Chrome() self.driver.maximize_window() self.driver.implicitly_wait(5) def teardown(self): self.driver.close() def test_actionchains(self): self.driver.get(\'http://sahitest.com/demo/clicks.htm\') myclick = self.driver.find_element_by_xpath(\'//input[@value="click me"]\') mydubboclick = self.driver.find_element_by_xpath(\'//input[@value="dbl click me"]\') myrightclich = self.driver.find_element_by_xpath(\'//input[@value="right click me"]\') action = ActionChains(self.driver) action.click(myclick) action.double_click(mydubboclick) action.context_click(myrightclich) sleep(3) action.perform() sleep(3)
用法二:鼠标移动到元素上
- action = ActionChains(self.driver)
- action.move_to_element(element)
- action.perform()
from time import sleep import pytest from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By class TestActionChains: def setup(self): self.driver = webdriver.Chrome() self.driver.maximize_window() self.driver.implicitly_wait(5) def teardown(self): self.driver.close() def test_moveto_action(self): self.driver.get(\'https://www.baidu.com/\') mts = self.driver.find_element(By.ID,\'s-usersetting-top\') ActionChains(self.driver).move_to_element(mts).perform() sleep(3)
用法三 拖拽
网页:http://sahitest.com/demo/dragDropMooTools.htm
from time import sleep import pytest from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By class TestActionChains: def setup(self): self.driver = webdriver.Chrome() self.driver.maximize_window() self.driver.implicitly_wait(5) def teardown(self): self.driver.close() def test_drag_drop(self): self.driver.get(\'http://sahitest.com/demo/dragDropMooTools.htm\') # drag_element = self.driver.find_element_by_id(\'dragger\') # drag_element = self.driver.find_element_by_xpath(\'//*[@class="drag"]\') drag_element = self.driver.find_element_by_css_selector(\'.drag\') drop_element = self.driver.find_element_by_xpath(\'/html/body/div[2]\') action = ActionChains(self.driver) action.drag_and_drop(drag_element,drop_element) action.perform() sleep(5)
用法四:按键
模拟按键有很多种方法,能用win32API、SendKeys、selenium的WebElement对象的send_keys() 实现,这里ActionChains类也提供了几个模拟按键的方法
- action = ActionChains(driver)
- action.send_keys(Keys.BACK_SPACE)
- 或者 action.key_down(Keys.CONTROL).send_keys(\’a\’).key_up(Keys.CONTROL)
- action.perform()
链接:http://sahitest.com/demo/label.htm
from time import sleep import pytest from selenium import webdriver from selenium.webdriver import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys class TestActionChains: def test_keys(self): self.driver.get(\'http://sahitest.com/demo/label.htm\') self.driver.find_element_by_xpath(\'/html/body/label[1]/input\').click() action = ActionChains(self.driver) action.send_keys(\'hi ~\').pause(1) action.send_keys(Keys.BACKSPACE).pause(1) action.send_keys(\'你好吗?\').pause(1) action.send_keys(Keys.CLEAR).pause(1) action.perform() sleep(2)
1.2 touchaction
官网:https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.common.touch_actions
类似actionChains, actionchains:只针对PC端鼠标模拟,对H5不生效, touchaction: 可以针对H5 ,点击滑动,拖拽,模拟手势等
手势控制:
- tap :在指定元素上敲击
- double_tap:在指定元素上双击
- tap_and_hold: 在指定元素上点击不释放
- move:手势移动指定的偏移(未释放)
- release:释放手势
- scroll: 手势点击并滚动
- scroll_from_element: 从某个元素位置开始手势并滚动(向下滚动为正数,向上滚动为负数)
- long_press:长按元素
- flick: 手势滑动
- flick_element:从某个元素位置开始手势滑动(向上滑动负数,向下滑动正数)
- perform: 执行
1.2.1 用法一:滑动、点击
- 打开Chrome
- 打开URL:https://www.baidu.com/
- 向输入框输入\’selenium测试\’
- 通过TouchAction点击搜索框
- 滑到底部,点击下一页
- 关闭浏览器
# -*- coding: utf-8 -*- # @Time : 2020/7/15 10:15 # @Author : 饭盆里 # @File : test_touch_action.py # @Software: PyCharm # @desc : from time import sleep from selenium import webdriver from selenium.webdriver import TouchActions class TestTouchAction: def setup(self): option = webdriver.ChromeOptions() option.add_experimental_option(\'w3c\',False) self.driver = webdriver.Chrome(options=option) self.driver.get(\'https://www.baidu.com/\') self.driver.implicitly_wait(5) def teardown(self): self.driver.quit() def test_touch_action(self): search_element = self.driver.find_element_by_id(\'kw\') click_element = self.driver.find_element_by_xpath(\'//*[@value="百度一下"]\') search_element.send_keys(\'selenium\') action = TouchActions(self.driver) action.tap(click_element) action.perform() sleep(3) action.scroll_from_element(search_element,0,10000).perform() sleep(3)
注意⚠️: 运行的时候报不符合W3C,需要加上这段代码
option = webdriver.ChromeOptions()
option.add_experimental_option(\'w3c\',False)
self.driver = webdriver.Chrome(options=option)
1.2.2 用法二:表单
什么是表单?
- 表单是一个包含表单元素的区域
- 表单元素是允许用户在表单中输入信息的元素,比如:文本域、下拉列表、单选框、多选框等
- 表单使用表单标签(<form>)定义,例如:<form><input /></form>
操作表单元素步骤:
- 首先定位到表单元素
- 然后去操作元素:清空、输入、点击
实战任务步骤:
- 打开testhome登录地址
- 输入用户名
- 输入密码
- 点击‘记住’标签
- 点击登录,提交表单
from time import sleep from selenium import webdriver class TestForm: def setup(self): self.driver = webdriver.Chrome() self.driver.get(\'https://testerhome.com/account/sign_in\') self.driver.implicitly_wait(5) def teardown(self): self.driver.close() def test_form(self): self.driver.find_element_by_name(\'user[login]\').send_keys(\'134\') self.driver.find_element_by_id(\'user_password\').send_keys(\'pswd\') self.driver.find_element_by_id(\'user_remember_me\').click() self.driver.find_element_by_name(\'commit\').click() sleep(5)
1.4练习
1.4.2 鼠标操作
鼠标操作包括:双击、右击、悬停、单击
实现思路:
- 引入类ActionChains
- 然后定位相关元素
- 在ActionChains()中调用相关鼠标操作方法
ActionChains 类提供的鼠标操作的常用方法:
- perform() 执行所有 ActionChains 中存储的行为
- context_click() 右击
- double_click() 双击
- drag_and_drop() 拖动
- move_to_element() 鼠标悬停
#/usr/bin python #-*- coding:UTF-8 -*- #########鼠标操作############## from selenium import webdriver from time import sleep #引入鼠标操作的包 from selenium.webdriver.common.action_chains import ActionChains driver = webdriver.Chrome() driver.get(\'https://www.baidu.com/\') driver.maximize_window() element = driver.find_element_by_id(\'kw\') element.send_keys(\'selenium 官网\') driver.find_element_by_css_selector(\'#su\').click() #双击 调用ActionChains的 double_click 方法,入参为定位的元素,perform() 代表执行 ActionChains(driver).double_click(element).perform() sleep(3) #右击 ActionChains(driver).context_click(element).perform() sleep(3) #悬停 ActionChains(driver).move_to_element(driver.find_element_by_css_selector(\'.pf\')).perform() sleep(3) driver.quit()
1.4.2 键盘操作
键盘简单操作:复制,剪切,粘贴等
任务:在百度输入框输入 selenium 学习 ,然后复制粘贴到 搜狗浏览器
#/usr/bin python #-*- coding:UTF-8 -*- #########键盘简单操作 from selenium import webdriver from time import sleep from selenium.webdriver.common.keys import Keys driver = webdriver.Chrome() driver.get(\'https://www.baidu.com/\') driver.find_element_by_css_selector(\'#kw\').send_keys(\'selenium 学习\') driver.find_element_by_css_selector(\'.s_btn\').click() sleep(3) #Ctrl +A driver.find_element_by_css_selector(\'#kw\').send_keys(Keys.CONTROL,\'a\') sleep(2) #Ctrl +C driver.find_element_by_css_selector(\'#kw\').send_keys(Keys.CONTROL,\'c\') sleep(2) #Ctrl +X # driver.find_element_by_css_selector(\'#kw\').send_keys(Keys.CONTROL,\'x\') # sleep(2) driver.get(\'https://www.sogou.com/\') #Ctrl +V driver.find_element_by_css_selector(\'.sec-input\').send_keys(Keys.CONTROL,\'v\') sleep(10)
from selenium import webdriver from time import sleep from selenium.webdriver.common.keys import Keys driver=webdriver.Chrome() driver.get(\'https://www.baidu.com/\') driver.find_element_by_css_selector(\'.s_ipt\').send_keys(\'hah\'); #通过回车键盘来代替点击操作 driver.find_element_by_id(\'su\').send_keys(Keys.ENTER); sleep(2) driver.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+V)
send_keys(Keys.F1) 键盘 F1 ……
send_keys(Keys.F12) 键盘 F12
1.5. 等待
因为网页或者其他因素影响,导致页面可能未加载完或者等待时间过长,故需要扩充下 等待的方法
- 显示等待是针对某一个元素进行相关等待判定;(比如等到后再进行下一步操作)
- 隐式等待不针对某一个元素进行等待,全局元素等待。
相关模块
- WebDriverWait 显示等待针对元素必用
- expected_conditions 预期条件类(里面包含方法可以调用,用于显示等待)
- NoSuchElementException 用于隐式等待抛出异常
- By 用于元素定位
3.1 直接等待
强制等待,线程休眠一定的时间 : sleep(3)
3.2 显示等待 — 针对某个元素
原理:显示等待,就是明确的要等到某个元素的出现或者是某个元素的可点击等条件,等不到,就一直等,除非在规定的时间之内都没找到,那么久跳出Exception
(简而言之,就是直到元素出现才去操作,如果超时则报异常)
- 在代码中定义等待条件,当条件发生时才继续执行代码
- \’WebDriverWait\’ 配合until()和until_not()方法,根据判断条件进行等待
- 程序每隔一段时间(默认0.5s) 进行条件判断,如果条件成立,则执行下一步,否则继续等待,直到超过设置的最长时间
注意: 指定了是具体的哪一个操作需要显示等待
案例:检测百度页面搜索按钮是否存在,存在就输入关键词“自学网 Selenium” 然后点击搜索
#/usr/bin python #-*- coding:UTF-8 -*- ################################显式等待 from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from time import sleep driver = webdriver.Chrome() driver.get("https://www.baidu.com/") sleep(2) driver.find_element_by_css_selector(\'#kw\').send_keys(\'selenium 官网\') element = WebDriverWait(driver,5,0.5).until(EC.presence_of_element_located((By.ID,\'su\'))) element.click() sleep(3) driver.quit()
3.3 隐式等待 –全局设置
原理:隐式等待,就是在创建driver时,为浏览器对象创建一个等待时间,这个方法是得不到某个元素就等待一段时间,直到拿到某个元素位置。
注意:在使用隐式等待的时候,实际上浏览器会在你自己设定的时间轮询的刷新页面去寻找我们需要的元素,如果没有出现就抛出异常
缺点: 全局等待,时间差太大时,设置有影响,特别是当有个元素出现异常的时候,需要等待的时间更长
self.driver.implicitly_wait(5)
#/usr/bin python #-*- coding:UTF-8 -*- from selenium import webdriver from selenium.common.exceptions import NoSuchElementException from time import ctime,sleep driver = webdriver.Chrome() driver.get(\'https://www.baidu.com/\') sleep(2)
#最长等待5s driver.implicitly_wait(5) try: print(ctime()) driver.find_element_by_css_selector(\'#kw\').send_keys(\'selenium 官网\')
#su1错误的定位 driver.find_element_by_css_selector(\'#su1\').click() except NoSuchElementException as msg: print(msg) finally: print(ctime()) sleep(2) driver.quit()
执行结果:
最多等待5s,且错误给出明确的提示信息
implicity_wait()默认参数的单位为妙,本例中设置等待时长为5秒,首先这5秒并非一个固定的等待时间,它并不影响脚本的执行速度。其次,它并不针对页面上的某一元素进行等待。当脚本执行到某个元素定位是,如果元素可以定位,则继续执行,如果元素定位不到,则它将以轮询的方式不断地判断元素是否被定位到。假设在第3秒定位到了元素则继续执行,若直到超出设置的时长5秒还没有定位到元素,则抛出异常。
# -*- coding: utf-8 -*- # @Time : 2020/7/13 23:45 # @Author : 饭盆里 # @File : test_wait.py # @Software: PyCharm # @desc : from time import sleep from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait class TestWait: def setup(self): self.driver = webdriver.Chrome() self.driver.get(\'https://ceshiren.com/\') self.driver.maximize_window() ##隐式等待 self.driver.implicitly_wait(5) def teardown(self): self.driver.close() def test_wait(self): ##直接等待 # self.driver.find_element(By.LINK_TEXT,\'所有分类\').click() # sleep(5) # self.driver.find_element_by_xpath(\'//*[@class="latest-topic-list ember-view"]/div[1]\').click() # sleep(2) ##隐式等待 # self.driver.find_element(By.LINK_TEXT, \'所有分类\').click() # self.driver.find_element_by_xpath(\'//*[@class="latest-topic-list ember-view"]/div[1]\').click() ##显示等待 # self.driver.find_element(By.LINK_TEXT, \'所有分类\').click() # def wait(x): # return len(self.driver.find_elements(By.XPATH,(\'//*[@class="latest-topic-list ember-view"]/div[1]\')))>=1 # WebDriverWait(self.driver,10).until(wait) ##显示等待 self.driver.find_element(By.LINK_TEXT, \'所有分类\').click() WebDriverWait(self.driver,10).until( EC.visibility_of_element_located((By.XPATH,\'//*[@class="latest-topic-list ember-view"]/div[1]\')))