51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 734|回复: 0
打印 上一主题 下一主题

[转贴] Selenium 如何获取鼠标指向的元素?

[复制链接]
  • TA的每日心情
    无聊
    5 天前
  • 签到天数: 941 天

    连续签到: 3 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2022-3-11 10:57:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    有一个同学在Gne的群里面咨询如何通过Selenium获取当前鼠标指向的元素,在我讲了方法以后,他过了两天又来问:

    那么,我今天就来写一篇文章,具体说说应该怎么操作。
      这个方法的核心,是借助JavaScript的事件(event)来获取鼠标所在的元素。然后再把这个元素传递给Selenium。我们先来第一步,不考虑Selenium,只使用JavaScript,如何获取当前鼠标指向的元素呢?
      我们首先需要知道在JavaScript中的一个事件句柄,叫做window.onmousemove。默认情况下,它的值是null:


    我们可以把它的值修改成一个函数,这个函数接收一个event参数,这样当鼠标在网页上移动的时候,这个函数就会被调用。而event参数是一个对象,这个对象有两个属性.clientX和.clientY,分别表示鼠标相当于网页的横坐标和纵坐标:
    1. function track_mouse(event){
    2.    var x = event.clientX, y = event.clientY
    3.    console.log('当前鼠标所在位置的坐标:x=' +  x + 'y=' + y)
    4.   }
    复制代码
    运行效果如下图所示:

    你执行命令以后,只要在页面上移动鼠标,你就会在控制台看到大量的坐标被打印出来。
      接下来,既然你有了当前鼠标所在位置的坐标,那么你只需要根据坐标查询到这个元素是什么就可以了。在JavaScript中,有一个函数叫做document.elementFromPoint,就能实现这个效果:

    1.  function track_mouse(event){
    2.    var x = event.clientX, y = event.clientY
    3.    var element = document.elementFromPoint(x, y)
    4.     if (!element) {
    5.     return // 当前位置没有元素
    6.    }
    7.     return element
    8.   }
    复制代码
    那么,如何把这个参数返回给Selenium呢?其实也非常简单,我们设置一个全局变量window.hovered_element,然后把当前鼠标对应的元素赋值给它。然后在Selenium中,使用.execute_script获取window.hovered_element就可以了。
      我们先来看看完整的JavaScript:
    1. window.hovered_element = null
    2.   function track_mouse(event){
    3.    var x = event.clientX, y = event.clientY
    4.    var element = document.elementFromPoint(x, y)
    5.     if (!element) {
    6.         window.hovered_element = null
    7.     return // 当前位置没有元素
    8.    }
    9.     window.hovered_element = element
    10.   }
    11.   window.onmousemove = track_mouse
    复制代码
     然后我们再来看看Selenium中的Python代码:
    1. import time
    2.   from selenium.webdriver import Chrome
    3.   driver = Chrome('./chromedriver')
    4.   driver.get('https://www.kingname.info/')
    5.   js = '''
    6.   window.hovered_element = null
    7.   function track_mouse(event){
    8.    var x = event.clientX, y = event.clientY
    9.    var element = document.elementFromPoint(x, y)
    10.     if (!element) {
    11.         window.hovered_element = null
    12.     return // 当前位置没有元素
    13.    }
    14.     window.hovered_element = element
    15.   }
    16.   window.onmousemove = track_mouse
    17.   '''
    18.   driver.execute_script(js)
    19.   while True:
    20.       element = driver.execute_script('return window.hovered_element')
    21.       if element:
    22.           print(f'当前鼠标所在的标签为:{element.tag_name}, 其中的文本内容为:{element.text}')
    23.       time.sleep(1)
    复制代码
    运行效果如下图所示:

    获取到了当前鼠标所在的元素的标签和标签里面的文字。
      到这里,这个同学需要的功能已经完全实现了。
      但可能有聪明的同学会发现,他这个需求是有问题的。我们能看到至少有三个问题:
      因为window.onmousemove太灵敏了,它的采样时间是毫秒级别的,鼠标稍稍移动一点点就会生成一个事件。但是,一个元素的区域是很大的,在一个元素内部移动鼠标,其实根本没有必要更新window.hovered_element。
      在Selenium里面,是通过while True每1秒查询一次window.hovered_element,虽然我们已经降低了频率,但大家从上面的图中可以看到,还是会获取到很多重复的数据。这是由于有一些元素非常大,我们鼠标如果在上面慢慢移动,时间会超过1秒,那么Selenium就会重复获取到数据。
      由于window.onmousemove的采样时间间隔很小,所以我们可以近似把鼠标的移动看做是连续的移动。因此,这段代码会记录鼠标轨迹路径上面的每一个元素。但实际上,我们并不会对网页上所有的内容都感兴趣,我们只会对特定的内容感兴趣。因此,获取当前鼠标所在位置的元素,其实是一个伪需求,它根本没有什么实际上用处,因为噪声太大了,无用的数据太多了!
      实际上,我觉得真正的需求应该是这样的:如果鼠标在网页上面某个元素停留时间超过5秒,那么获取这个元素。
      但这样做太费时间了。每次都要等5秒,岂不是带薪摸鱼?那需求能不能改成获取当前鼠标点击的元素呢?如果你实践一下,你会发现,当你点击一个链接的时候,网页自动就跳转到另一个页面去了,并不能获取到你需要的数据。


    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?(注-册)加入51Testing

    x
    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-5-5 21:16 , Processed in 0.063596 second(s), 24 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表