当前位置: 首页 > 科技观察

每日一技能:Selenium如何获取鼠标指向的元素?

时间:2023-03-17 16:40:46 科技观察

有同学在Gne组问如何通过Selenium获取当前鼠标指向的元素。我说明了方法后,过两天他又问:嗯,我今天写一篇文章,具体说说怎么做。该方法的核心是利用JavaScript事件(event)获取鼠标所在的元素。然后将此元素传递给Selenium。我们先迈出第一步,不管Selenium,只用JavaScript,如何获取鼠标当前指向的元素?我们首先需要知道JavaScript中的一个事件处理函数,叫做window.onmousemove。默认情况下,它的值为null:我们可以将它的值改为一个接收事件参数的函数,这样当鼠标在网页上移动时,就会调用这个函数。event参数是一个对象,这个对象有两个属性.clientX和.clientY,分别代表鼠标相当于网页的横坐标和纵坐标:functiontrack_mouse(event){varx=event.clientX,y=event.clientYconsole.log('当前鼠标位置的坐标:x='+x+'y='+y)}运行效果如下图:执行命令后,将鼠标移到页面,你会在控制台看到大量的坐标被打印出来。接下来,既然有了当前鼠标位置的坐标,那么只需要根据坐标查询元素是什么就可以了。在JavaScript中,有一个叫做document.elementFromPoint的函数,可以实现这样的效果:element){return//当前位置没有元素}returnelement}那么,如何将这个参数返回给Selenium呢?其实很简单,我们设置一个全局变量window.hovered_element,然后将当前鼠标对应的元素赋值给它。然后在Selenium中,使用.execute_script获取window.hovered_element即可。让我们先来看看完整的JavaScript:.hovered_element=nullreturn//当前位置没有元素}window.hovered_element=element}window.onmousemove=track_mouse然后我们看Selenium中的Python代码:importtimefromselenium.webdriverimportChromedriver=Chrome('./chromedriver')driver.get('https://www.kingname.info/')js='''window.hovered_element=nullfunctiontrack_mouse(event){varx=event.clientX,y=event.clientYvarelement=document.elementFromPoint(x,y)if(!element){window.hovered_element=nullreturn//当前位置没有元素}window.hovered_element=element}window.onmousemove=track_mouse'''driver.execute_script(js)而True:元素=驱动程序。execute_script('returnwindow.hovered_element')ifelement:print(f'鼠标当前所在的标签为:{element.tag_name},文本内容为:{element.text}')time.sleep(1)线条效果如下图所示:获取鼠标当前所在元素的标签和标签中的文字。到这里,这位同学所需要的功能已经完全实现了。但是有些聪明的同学可能会发现他的需求是有问题的。我们至少可以看出三个问题:由于window.onmousemove过于敏感,它的采样时间是毫秒级的,鼠标稍微移动一下就会产生一个事件。但是一个元素的面积很大,在元素内部移动鼠标根本不需要更新window.hovered_element。在Selenium中,window.hovered_element通过whileTrue每1秒查询一次。虽然我们降低了频率,但是从上图可以看出,还是会得到很多重复的数据。这是因为有些元素非常大。如果我们的鼠标在上面移动缓慢,需要1秒以上,Selenium会反复获取数据。由于window.onmousemove的采样时间间隔很小,我们可以将鼠标的移动近似为连续移动。因此,这段代码会记录鼠标轨迹路径上的每一个元素。但实际上,我们并不对网页上的所有内容感兴趣,我们只对特定的内容感兴趣。所以获取当前鼠标位置的元素其实是一个伪需求。根本没有实际用处,因为噪音太大,无用数据太多!其实我觉得真正的需求应该是这样的:如果鼠标在网页的某个元素上停留超过5秒,那么获取这个元素。但是这样做太费时间了。每次都等5秒,这不是付费钓鱼吗?需求可以改成获取当前鼠标点击的元素吗?如果你实践一下,你会发现当你点击一个链接时,网页会自动跳转到另一个页面,而你无法获取到你需要的数据。