在Selenium中显示当前光标位置
有没有办法显示当前光标的位置或者类似的东西?我有一个动作链,它应该在某个对象的确切位置点击,但我想我选错了坐标。我使用的是Firefox的webdriver。下面是我的脚本:
from selenium import webdriver
import time
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Firefox()
driver.get("http://www.mysite/")
elem = driver.find_element_by_xpath('//div[@id="player"][1]/object[@type="application/x-shockwave-flash"]')
action_chains = ActionChains(driver)
action_chains.move_to_element_with_offset(elem, 660, 420).perform()
action_chains.click().perform()
time.sleep(10)
driver.close()
5 个回答
我没有找到直接改变分辨率的方法,因为我们无法使用任何定位器来做到这一点。
关于你提到的JWPlayer,我相信可能有一些JavaScript代码可以用来改变分辨率。你可以使用Selenium的JavascriptExecutor来运行这段JavaScript代码,从而模拟分辨率的变化,不过这不是通过点击鼠标来实现的。
WebDriver driver = new ChromeDriver();
if (driver instanceof JavascriptExecutor) {
((JavascriptExecutor) driver).executeScript(YOUR_JAVA_SCRIPT_STRING);
}
我注意到你提到不想使用任何原生的JWPlayer API。我认为这可能是唯一的解决办法。
作为一个刚接触selenium的新手,我发现理解它无法对flash对象进行点击有点困难。对我来说,唯一的解决办法就是使用sikuli-script
。
我在GitHub上找到了这个项目:https://github.com/kevlened/sikuli_cpython。这个项目可以让我们在纯python中使用用jython写的sikuli脚本,所以我想我可以写一些sikuli脚本,并把它们和selenium测试结合起来。
是啊,这个问题真让人头疼。
这个方法可以让你看到鼠标的位置,通过在鼠标上画一个红点来实现:

首先,暂时在你的网页上添加以下CSS:
// TODO: Remove me after you've figured out where the mouse is moving to.
.dot {
background: red;
position: absolute;
width: 2px;
height: 2px;
z-index: 10000;
}
接着,在你的代码中,在调用 *.moveTo()
方法之前,添加一个暂停,这样你就可以在浏览器的控制台中插入代码。这个代码是用JavaScript写的(JS / webdriver.io),但在任何语言中都很容易添加:
// Other test stuff...
console.log("This gives you 10 seconds to inject the code..."); // <-- Add this and the next line
browser.pause(10000);
browser.moveTo(...gawdKnowsWhere);
现在,当你看到测试命令行控制台等待10秒时,打开Chrome或Firefox的开发者工具(按F12),然后把这个代码片段粘贴到浏览器的“控制台”标签中:
(function() {
"use strict";
document.onmousemove = handleMouseMove;
function handleMouseMove(event) {
var dot, eventDoc, doc, body, pageX, pageY;
event = event || window.event; // IE-ism
// If pageX/Y aren't available and clientX/Y
// are, calculate pageX/Y - logic taken from jQuery
// Calculate pageX/Y if missing and clientX/Y available
if (event.pageX == null && event.clientX != null) {
eventDoc = (event.target && event.target.ownerDocument) || document;
doc = eventDoc.documentElement;
body = eventDoc.body;
event.pageX = event.clientX +
(doc && doc.scrollLeft || body && body.scrollLeft || 0) -
(doc && doc.clientLeft || body && body.clientLeft || 0);
event.pageY = event.clientY +
(doc && doc.scrollTop || body && body.scrollTop || 0) -
(doc && doc.clientTop || body && body.clientTop || 0 );
}
// Add a dot to follow the cursor
dot = document.createElement('div');
dot.className = "dot";
dot.style.left = event.pageX + "px";
dot.style.top = event.pageY + "px";
document.body.appendChild(dot);
}
})();
现在,去找那个红点吧。无论鼠标移动到哪里,它都无法点击,因为现在有一个红色的方块挡住了。不过至少你可以看到鼠标试图去哪里。
看不到红点?
这里有一些小建议:
- 在CSS中通过修改宽度和高度来让红点变大。
- 移动你的鼠标在屏幕上,看看所有的红点。当你移动鼠标时,它们有出现吗?
- 确保你可以在你预期的位置画出红点。可能是层级不够高等等。
如果你只是想确认Selenium是否点击了正确的元素,而不是直接用click()
去点击那个元素的话:
actions.move_to_element(my_element).click().perform()
可以用context_click()
来操作:
actions.move_to_element(my_element).context_click().perform()
Selenium会对你的元素进行右键点击,这样就会在你鼠标的右下角显示出一个右键菜单。等你看到这个菜单的位置,就能知道Selenium是不是点击了正确的元素。
我有一个不透明的HTML5画布,需要在不同的位置检查工具提示的值,真是麻烦!经过一番折腾,我学到了几个重要的事情:
move_to_element_by_offset
在2.42版本之前有问题。你可以查看这个链接了解更多:https://code.google.com/p/selenium/issues/detail?id=4215即使更新后,
move_to_element_by_offset
仍然有点古怪。我改用了ActionChains move_to_element
的悬停(默认是移动到元素的中心)和第二个ActionChains
结合move_by_offset
。现在你已经到位了,重新请求位置敏感的元素。在我的例子中,就是一个工具提示对象。这个
selenium.webdriver.remote.element
会有.location['x']
和.location['y']
这两个属性,帮助你检查位置是否正确。
以下是一些在执行perform
的ActionChain悬停后,获取光标位置时不管用的东西,省得大家浪费时间:
.location['x']
和.location['y']
在你传给move_to_element
的元素上。这些值不会被ActionChains
更新。- selenium.webdriver.remote.webdriver的
switch_to_active_element
;我不太清楚哪些元素算“活动”,但它并没有把我们的工具提示视为活动元素,返回的坐标是[0, 0]。 - selenium.webdriver.remote.webdriver的
get_window_position
;文档有点模糊,但这个功能确实是获取窗口的位置,而不是光标的位置。