先看几张图体会一下:

上节内容主要说明了元素的定位,本节内容说要说对元素的操作,元素的操作分为两部分一部分是鼠标的操作,另一种是对键盘对元素的操作,下面我们主要讲解一下鼠标对元素的操作。

图片 1

图片 2

webdriver 模块中几种比较常见的几种操作元素的方式:

放大镜

图片 3

1.clear()       #清楚输入框的内容

分析原理

打开一些电商网站的商品详情页面,把鼠标移动到左侧展示的图片上,会看到如下的效果

  • 一个半透明的方块出现(简称方块)在鼠标下,鼠标在图片上移动,方块也跟着移动,但始终不会超出图片边界
  • 右侧出现一个方框,里面的图片内容与方块所覆盖的图片部分吻合,但是更清晰
  • 鼠标移出图片范围,方块消失,“放大”的图片也消失

看上去,方块是“放大镜”,右边方框呈现“放大”后的内容。
我们所看到的这种放大镜的实质是两张内容相同而分辨率不同的图片组合的,当鼠标在分辨率小的图片(简称小图)上移动时,分辨率大的图片(简称大图)作出等比例的移动,由于大图只有位于方框中的部分才被显示,所以看起来会有放大镜的效果。

我用一幅示意图来表示原理;

图片 4

示意图-1

图片 5

2.send_keys(‘内容’) #在文本框内输入内容

效果实现

实在很佩服自己就那样默默忍受了很多很多年。其实这些东西在网上小小的一搜,5分钟就能搞定。

3.click()        #点击按钮

准备工作
  • 需要一个容纳所有部件的容器元素(简称容器),一个放小图的容器和一个放大图的容器,一个可以在小图上自由移动但又不超出小图容器范围的方块,两张内容相同而分辨率不同的图片
  • 了解获取元素位置和大小以及设置元素位置的知识
  • 了解鼠标事件中的“mouseover”、“mouseout”、“mousemove”
    事件以及事件对象的pageX 和pageY 属性(用于获取鼠标在页面中位置)

html

   <div class="magnifier">

        <div class="float-box"></div>



  </div>

css

.magnifier{position: relative;}
.small-box{position: relative;height: 350px;width: 350px;display:       inline-block; border:#ccc solid 1px; }
.small-box:hover{cursor: move;}
.small-box .float-box{background: rgba(245,138,25,0.4);position: absolute;top: 0;left: 0;}
.big-box{position: absolute;width: 400px;height: 400px;margin-left:10px;border:#999 solid 1px;z-index: 4;
overflow: hidden;}
.big-box img{position: absolute;top: 0;left: 0}

准备工作做完了,我们会看到这样的效果:

图片 6

图片我是在京东商城的网站上下载的,待会给出源码和图片文件,小图350*350,大图800*800,这里的比例不是1:2,没关系我们一样可以实现我们想要的效果

需要注意的几点:

  • 我将可移动方块的宽高放到JavaScript中设置,因为它的宽高涉及到一些计算,这是为了让html和css不掺杂计算的逻辑
  • 为了方便我将小图片容器的内容区域设置成和小图一样大,大图容器的宽高可以任意设置,只要比大图小就可以

然而我们大家都在想,现在没时间,我还要做xxxx事呢,反正多点两下鼠标而已。

4.submit()        #表单的提交

JavaScript实现
  • 我个人觉得用代码来演示计算过程更直观,所以我就把一些关键计算讲解和代码放在了一起
  • 这里我使用了jQuery,不熟悉jQuery的同学也不必担心,我用的都是些简单的函数,保证大家一看就懂。
  • 采用的是组件式的写法

是啊,点两下鼠标手快的一秒都不用,一般人这两个操作用2秒左右。

webdriver 中 clear(),send_keys(),click()
这几个方法比较常用,前面篇幅已经我们看到对send_keys(‘内容’)、click()已经使用过,下面我们看一下clear()和submit()的使用。

1.首先封装一个构造函数,将一些会频繁用到的DOM元素或常量保存为属性,并进行一些初始化的操作
var Magnifier=function(element){
    var $el            =this.$element       =$(element),//组件元素
        $smallBox      =this.$smallBox      =$el.find(".small-box"),
        $bigBox        =this.$bigBox        =$el.find(".big-box"),
        $floatBox      =this.$floatBox      =$el.find(".float-box"),
        $smallImg      =this.$smallImg      =$el.find(".small-box img"),
        $bigImg        =this.$bigImg        =$el.find(".big-box img"),

        smallImgHeight =this.smallImgHeight =$smallImg.height(),
        smallImgWidth  =this.smallImgWidth  =$smallImg.width(),
        scale          =this.scale          =$bigImg.width()/$smallImg.width();

    this.smallImgOffsetTop= $smallImg.offset().top;
    this.smallImgOffsetLeft=$smallImg.offset().left;

    $floatBox.height($bigBox.height()/$bigImg.height()*smallImgHeight);
    $floatBox.width($bigBox.width()/$bigImg.width()*smallImgWidth);
};

稍微复杂点的是$floatBox(后面都用这个变量名来指代半透明的小方块)的宽高计算公式,明白了示例图-1就很容易根据相似性来进行计算。

但是,我还是觉得不爽。

  • 方法:submit()
2.鼠标的移动带动方块的移动,在Magnifier的原型中添加moveFloatBox()方法

实现过程中涉及到几个问题

  • 如何让$floatBox跟着鼠标动?
  • 如何让$floatBox呆在容器中?
  • $floatBox的位置和大图的位置如何联系?

先来看效果示意图,

图片 7

示意图-2

图中$floatBox的宽高都是图片的一半,虚线正方形表示$floatBox的正中心(不是鼠标)可移动的范围。当鼠标在虚线范围内时,$floatBox随鼠标移动,鼠标在虚线范围外时,$floatBox只能在沿着X轴或Y轴方向移动,或者不能移动。
很明显,我需要借助鼠标移动事件来达到这个效果,下面实现的moveFloatBox()函数就是鼠标的mousemove事件的处理函数。

  Magnifier.prototype.moveFloatBox=function(event){
    var that=this,
        offsetTop=that.smallImgOffsetTop,
        offsetLeft=that.smallImgOffsetLeft,
        floatBoxHeight=that.$floatBox.height(),
        floatBoxWidth=that.$floatBox.width(),
        //下面是$floatBox中心点到虚线位置的距离
        top=event.pageY-that.smallImgOffsetTop-floatBoxHeight/2,
        left=event.pageX-offsetLeft-floatBoxWidth/2;

    //当鼠标在虚线外时,我们需要调整$floatBox中心点到虚线的距离
    if (top<0) {
        top=0;
    }
    else if(that.smallImgHeight-top<=floatBoxHeight){
        top=that.smallImgHeight-floatBoxHeight;
    }
    if(left<0){
        left=0;
    }
    else if (that.smallImgWidth-left<=floatBoxWidth) 
    {
        left=that.smallImgWidth-floatBoxWidth;
    }
    //用调整后的top,left属性设置$floatBox的位置,这比用鼠标移动的距离来计算更直接;
    that.$floatBox.offset({top:offsetTop+top,
        left:offsetLeft+left});
    //大图的位置也可以根据调整后的top,left来设置,所以返回这俩属性
    return {top:top,left:left};
  };

刚才所提到的几个疑问在代码片段中我都一一回答了,不明白的小伙伴请仔细研究一下代码。


    解释:查找到表单(from)直接调用submit即可

3.移动大图

$floatBox元素向左移动时,大图必须要往右移动才能展示出对应的部分,所以$floatBox和大图的移动方向是相反的。
根据moveFloatBox()返回的top,left结合大图和小图的尺寸比例,轻松得到大图的绝对定位位置。
下面是moveDetailImg()方法的内容

 Magnifier.prototype.moveDetailImg=function(position){
    var that=this,
        top=position.top*that.scale,
        left=position.left*that.scale;
    that.$bigImg.css("left",-1*(left)+"px");//相反方向
    that.$bigImg.css("top",-1*(top)+"px");
};

以上是废话,下面才是内容:

    实例:driver.find_element_by_id(“form1”).submit()

4.绑定鼠标事件
    $(".magnifier").each(function() {
        var m = new Magnifier(this);
        m.$smallBox.on("mouseover",function(event){
            m.$floatBox.show();
            m.$bigBox.show();
        });
        m.$smallBox.on("mousemove",function(event){
            var movedDistance=m.moveFloatBox(event);
            m.moveDetailImg(movedDistance);
        });
        m.$smallBox.on("mouseout",function(){
            m.$bigImg.css("left","0px");
            m.$bigImg.css("top","0px");
            m.$bigBox.hide();
            m.$floatBox.hide();
        });
    });

到这里图片放大镜就讲解完了。
完整的实现代码和图片下载请移步我的github

把下面的内容复制到记事本里面,然后保存到桌面,文件名写00.reg(这里一定要是reg类型的才行,像.reg.txt这种的是不行的)

  • 方法:clear() 
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer]
"NoInternetOpenWith"=dword:00000001
"NoFileAssociate"=dword:00000001

    解释:由于有些文本框内包含默认值,我们需要使用clear()清理再次输入

双击桌面上的00.reg ,点确定,到提示成功导入。

    实例:driver.find_element_by_id(“kw”).clear()

大功告成,忽然间觉得清爽了很多。

上面介绍的几种方法比较简单,下面介绍一些其他的模拟操作,比如单击,双击、右击,元素的拖拽等,如果使用这些模拟的时候,需要使用到另一个模块
ActionChains,这个模块基本可以满足我们对鼠标操作的需求。

加一张效果图:

使用ActionChains的时候我们需要在头上引入该模块

图片 8

from selenium.webdriver.common.action_chains import ActionChains

下面首先看一下ActionChains的执行原理,当调用ActionChains方法的时候不会立即执行,而是将所有的操作暂时存储在一个队列中,当调用perform()的方法时候,队列会按照放入的先后顺序依次执行。

这里我们先看个小示例

#-*- coding:utf-8 -*-
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get('http://cn.bing.com/')
driver.maximize_window()
searchElement = driver.find_element_by_id('sb_form_q').send_keys('selenium')
searchButtonElement = driver.find_element_by_id('sb_form_go')
ActionChainsDriver = ActionChains(driver).click(searchButtonElement)
# ActionChainsDriver.perform()   #此时我们不执行perform() 
time.sleep(5)
driver.quit()

此时没有执行perform(),我们可以看到虽然使用click()点击了搜索按钮,但是确实没有执行点击搜索过程。 

图片 9

下面我们看一下添加了perform()的执行结果

图片 10

此时我们已经可以看到执行了点击搜索按钮,执行了搜索操作。

下面我们来看一下ActionChains 提供了那些方法

  • click(on_element=None)                    #单击鼠标左键
  • click_and_hold(on_element=None)     #点击鼠标左键,按住不放
  • context_click(on_element=None)           #点击鼠标右键
  • double_click(on_element=None)            #双击鼠标左键
  • drag_and_drop(source, target)            
     #拖拽到某个元素然后松开
  • drag_and_drop_by_offset(source, xoffset, yoffset)        
     #拖拽到某个坐标然后松开
  • move_by_offset(xoffset, yoffset)            
    #鼠标移动到距离当前位置(x,y)
  • move_to_element(to_element)               #鼠标移动到某个元素
  • move_to_element_with_offset(to_element, xoffset, yoffset)
    #将鼠标移动到距某个元素多少距离的位置
  • release(on_element=None)                    
    #在某个元素位置松开鼠标左键
  • perform()                                            
    #执行链中的所有动作

下面我们来详细的介绍一下上面提到的方法,那么这个时候需要我们看一下AcitonChains的书写方法。

  • 链条式方法

    searchElement = driver.find_element_by_id(‘sb_form_q’).send_keys(‘selenium’)
    searchButtonElement = driver.find_element_by_id(‘sb_form_go’)
    ActionChains(driver).click(searchButtonElement).perform() #使用一行将所有的步骤写完

  • 分布式方法

    searchElement = driver.find_element_by_id(‘sb_form_q’).send_keys(‘selenium’)
    searchButtonElement = driver.find_element_by_id(‘sb_form_go’)
    ActionChainsDriver = ActionChains(driver).click(searchButtonElement) #分开两步进行书写
    ActionChainsDriver.perform()

 根据以上内容可以对ActionChains的鼠标的方法分为3大类,鼠标点击,鼠标的移动,通过鼠标对元素的拖拽、

1.鼠标的点击

  • 右击 —-> context_click(rightButtonElement)
  • 双击 —-> double_click(doubleButtonElement)
  • 单击 —-> click(buttonElement)
  • 按住左键  —-> click_and_hold(clickHoldElement)

我这边写了一个简单的页面,主要来模拟以上的操作,大家也可以找一些页面来试试下面的例子,也可以使用我的页面。

#-*- coding:utf-8 -*-
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get('file:///C:/Users/hunk/Desktop/demo_clicks.html')
driver.maximize_window()
# 首先我们需要获取到要操作的元素,然后再次进行操作
doubleButtonElement = driver.find_element_by_xpath('/html/body/form/input[2]')   #获取双击按钮元素
buttonElement = driver.find_element_by_xpath('/html/body/form/input[3]')         #获取单击按钮元素
rightButtonElement = driver.find_element_by_xpath('/html/body/form/input[4]')    #获取右击按钮元素
clickHoldElement = driver.find_element_by_xpath('/html/body/form/input[5]')      #获取按住不放按钮元素
'''内容开始的时候我们也介绍说明,当调用perform()方法时才会执行鼠标操作'''
#双击操作
ActionDoubleClick= ActionChains(driver).double_click(doubleButtonElement)
ActionDoubleClick.perform() 
time.sleep(3)
# 单击操作
ActionClick = ActionChains(driver).click(buttonElement)
ActionClick.perform()
time.sleep(3)
# 右击操作
ActionContextClick = ActionChains(driver).context_click(rightButtonElement)
ActionContextClick.perform()
time.sleep(3)
#按住不放左键
ActionClickHold = ActionChains(driver).click_and_hold(clickHoldElement)
ActionClickHold.perform()
time.sleep(3)
driver.quit()

下面是我们执行上面的代码的效果,是不是很神奇吧。

图片 11

 2.鼠标的移动

  • 鼠标移动到距离当前位置(x,y)—->  move_by_offset(xoffset,
    yoffset)
  • 鼠标移动到某个元素 —-> move_to_element(MoveElement)

 示例:

#-*- coding:utf-8 -*-
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get('file:///C:/Users/hunk/Desktop/text3.html')
driver.maximize_window()
#第一个操作:鼠标移动到某个元素
#为了演示,开始设置标签的颜色淡蓝色,当鼠标移到到该元素时标签颜色变为红色
MoveElement = driver.find_element_by_xpath('//*[@id="box1"]')   #鼠标移到到目标元素
time.sleep(3)
'''将鼠标移到MoveElement'''
Action = ActionChains(driver)

Action.move_to_element(MoveElement).perform()
time.sleep(5)
driver.save_screenshot('move_to_element.png')   #记录一下我们开始的坐标位置
'''x坐标为正数向右偏移,x坐标为负数向左偏移'''
'''y坐标为正数向下偏移,y坐标为负数向上偏移'''
#为了更好的显示我们效果,当鼠标移动到目标位置的时候,我们显示了鼠标的坐标,以后让当前的位置变成绿色
Action.move_by_offset(-311,-11).perform() #move_by_offset以鼠标当前的位置为中心进行偏移,移动到距离当前位置(x,y)
time.sleep(5)
driver.save_screenshot('move_by_offset.png')   #记录一下我们移动后的坐标位置
driver.quit()

根据我们前后保存的图片可以计算到我们移动的偏移是否正确,这个大家可以根据实际来计算一下。

以上代码执行的效果如下显示

图片 12

以上我们队鼠标的点击和移动讲解完成,下面我们看一下把点击和移动放在一起的效果,那就是对元素的拖拽。

鼠标的操作第三部分:拖拽

  • 将某个元素拖拽到某个元素然后松开 —-> rag_and_drop(source,
    target)
  • 拖拽到某个坐标然后松开 —->  drag_and_drop_by_offset(source,
    xoffset, yoffset) 

以上的两个方法具体的使用

#-*- coding:utf-8 -*-
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get('file:///C:/Users/hunk/Desktop/text3.html')
driver.maximize_window()
#第一个操作:鼠标移动到某个元素
#为了演示,开始设置标签的颜色淡蓝色,当鼠标移到到该元素时标签颜色变为红色
dragElement = driver.find_element_by_xpath('//*[@id="box1"]')   #获取被拖拽的元素
targetElement = driver.find_element_by_xpath('//*[@id="area1"]')   #获取被拖拽到的目标
Action = ActionChains(driver)
'''将【拖拽我吧!】元素拖拽到第一个对话框'''
Action.drag_and_drop(dragElement,targetElement).perform()   #将【拖拽我吧!】拖到第一个对话框
time.sleep(5)
'''将【拖拽我吧!】元素拖拽到距离当前位置(45,200),也就是拖拽到第二个对话框'''
'''由于第一次我们已经将元素拖拽到了第一个对话框,所以我们实际的拖拽是从第一个对话框拖拽到第二个对话框'''
Action.drag_and_drop_by_offset(dragElement,45,200).perform()
time.sleep(5)
driver.quit()

为了更好的让大家看到代码的实际效果,我这边将所有的操作结果制作成为动画

图片 13

 上面讲解的拖拽是selenium自己带的拖拽方法,我们是否可以讲鼠标的移动和点击生成一个新的拖拽

首先我们来思考一下如何实现拖拽?

我们需要选择一个元素然后按住鼠标左键到某个地方松开鼠标实现拖拽

#-*- coding:utf-8 -*-
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get('file:///C:/Users/hunk/Desktop/text3.html')
driver.maximize_window()
#第一个操作:鼠标移动到某个元素
#为了演示,开始设置标签的颜色淡蓝色,当鼠标移到到该元素时标签颜色变为红色
dragElement = driver.find_element_by_xpath('//*[@id="box1"]')   #获取被拖拽的元素
targetElement = driver.find_element_by_xpath('//*[@id="area3"]')   #获取被拖拽到的目标
Action = ActionChains(driver)
'''将【拖拽我吧!】元素拖拽到第三个对话框'''
#首先选择元素,按住不放,然后移动元素,最后松开鼠标,完成拖拽
Action.click_and_hold(dragElement).move_to_element(targetElement).release().perform()
time.sleep(5)
driver.quit()

效果:

图片 14

此时我们将鼠标的操作基本讲解完成了,实际过程中使用点击的操作比较多,移动和拖拽使用的比较少,也是我在13年做医疗自动化测试项目时,选择预约日期的时候使用了一次,后面的项目基本没有再次使用过。

内容中使用的测试页面大家可以通过

Author

发表评论

电子邮件地址不会被公开。 必填项已用*标注