使用Selenium WebDriver获取网页的屏幕位置
有没有一种方法可以通过SeleniumWebDriver获得HTML窗口(页面主体)的屏幕坐标使用Selenium WebDriver获取网页的屏幕位置,selenium,selenium-webdriver,Selenium,Selenium Webdriver,有没有一种方法可以通过SeleniumWebDriver获得HTML窗口(页面主体)的屏幕坐标 您可以这样尝试: WebDriver driver=new FirefoxDriver(); driver.get("http://www.google.com"); JavascriptExecutor js=(JavascriptExecutor) driver; Double i= (Double) js.executeScript("var element = docu
您可以这样尝试:
WebDriver driver=new FirefoxDriver();
driver.get("http://www.google.com");
JavascriptExecutor js=(JavascriptExecutor) driver;
Double i= (Double) js.executeScript("var element = document.getElementById('hplogo');var position = element.getBoundingClientRect();return position.left");
System.out.print(i);
看过几次,还没有从WebDriver中找到一个优雅的解决方案(他们有一个参数,看起来在他们的ILocatable设置中支持,但该方法尚未实现) 我所做的是使用UIAutomation获取windows AutomationElement,并使用treewalker查找窗口的实际对象-缺点是我注意到浏览器偶尔会更新其窗口,因此条件必须每隔一段时间更改一次以适应 下面是一些示例代码(我在这里删除了一些公司代码,因此在我这方面更加优雅,但这应该适用于C#)
公共静态矩形GetAbsCoordinates(此IWebElement元素)
{
var-driver=GetDriver(元素);
变量句柄=GetIntPtrHandle(驱动程序);
var ae=AutomationElement.FromHandle(句柄);
AutomationElement文档=空;
var caps=((RemoteWebDriver)driver).Capabilities;
var browserName=caps.browserName;
开关(浏览器名称)
{
“狩猎”一案:
变量条件=(新的AndCondition(新的属性条件)(AutomationElement.ControlTypeProperty,ControlType.Pane),
新属性条件(AutomationElement.ClassNameProperty,“SearchableWebView”);
doc=ae.FindFirst(TreeScope.conditions,条件);
打破
案例“firefox”:
doc=ae.FindFirst(TreeScope.subjects,新属性条件(AutomationElement.ControlTypeProperty,ControlType.Document));
打破
案例“铬”:
doc=ae.FindFirst(TreeScope.subjects,新属性条件(AutomationElement.NameProperty,“Chrome旧窗口”);
如果(doc==null)
{
doc=ae.FindFirst(TreeScope.subjects,新属性条件(AutomationElement.NameProperty,“谷歌浏览器”);
如果(doc==null)
抛出新异常(“无法找到包含浏览器窗口的元素”);
doc=doc.FindFirst(TreeScope.subjects,新属性条件(AutomationElement.ControlTypeProperty,ControlType.Document));
}
打破
“internet explorer”案例:
doc=ae.FindFirst(TreeScope.subjects,new和condition(newpropertyCondition,AutomationElement.ControlTypeProperty,ControlType.Pane),
新属性条件(AutomationElement.ClassNameProperty,“TabWindowClass”);
打破
}
如果(doc==null)
抛出新异常(“无法找到包含浏览器窗口的元素”);
var iWinLeft=(int)doc.Current.BoundingRectangle.Left;
var iWinTop=(int)doc.Current.BoundingRectangle.Top;
var coords=((ILocatable)元素);
var rect=新矩形(iWinLeft+coords.LocationInDom.X,iWinTop+coords.LocationInDom.Y,element.Size.Width,element.Size.Height);
返回矩形;
}
公共静态IWebDriver GetDriver(此IWebElement e)
{
返回((IWrapsDriver)e);
}
公共静态IntPtr GetIntPtrHandle(此IWebDriver驱动程序,int-timeoutSeconds=Timeout)
{
var end=DateTime.Now.AddSeconds(timeoutSeconds);
while(DateTime.Now
hmmm,我无法直接向询问chrome的用户发表评论,因此我必须在此处添加另一条评论
基本上,对于UIAutomation,您需要一个名为inspect的工具(在8.1SDK中免费提供)。像uispy这样的旧工具可能也能工作
基本上,您可以启动chrome,然后启动inspector工具—您可以查看树状结构,然后向下导航到包含DOM的文档。在工具中启用亮显以简化此操作
Chrome在树控件的布局中看起来是非常动态的——我不得不对它进行几次修改,以适应我所看到的控件。如果您使用与我不同的版本-基本上在树中找到文档窗口并查看与之相关的所有控件模式-这就是我将传递到PropertyCondition中的内容,以了解如何搜索控件。Intellisense应该为您提供不同的查询内容,例如AutomationElement.NameProperty。这就是我的例子——我注意到在winXP机器上运行chrome与在win8机器上运行chrome之间存在差异。。。因此需要检查null
就像我之前说过的——这并不优雅,如果它内置在Selenium中,那就太棒了(我想他们有更好的方法来确定DOM区域的坐标)。。。我认为这对迁移到Selenium网格的人来说也是一个问题(就像我正在做的那样)-据我所知,使用它我不知道你是否可以通过一堆支持的dll将Selenium传输到远程机器。。。至少没有很多黑客
如果它仍然不适合你-给我一个关于操作系统的具体想法,Chrome版本,我会尝试看一看,并给出确切的属性匹配。很不幸,如果你摆弄自己,也许是最好的,因为这些东西不是静态的。我快速浏览了一下chrome,你可能会在以下方面有更好的运气
public static Rectangle GetAbsCoordinates(this IWebElement element)
{
var driver = GetDriver(element);
var handle = GetIntPtrHandle(driver);
var ae = AutomationElement.FromHandle(handle);
AutomationElement doc = null;
var caps = ((RemoteWebDriver) driver).Capabilities;
var browserName = caps.BrowserName;
switch (browserName)
{
case "safari":
var conditions = (new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "SearchableWebView")));
doc = ae.FindFirst(TreeScope.Descendants, conditions);
break;
case "firefox":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
break;
case "chrome":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Chrome Legacy Window"));
if (doc == null)
{
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));
if (doc == null)
throw new Exception("unable to find element containing browser window");
doc = doc.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
}
break;
case "internet explorer":
doc = ae.FindFirst(TreeScope.Descendants, new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "TabWindowClass")));
break;
}
if (doc == null)
throw new Exception("unable to find element containing browser window");
var iWinLeft = (int) doc.Current.BoundingRectangle.Left;
var iWinTop = (int)doc.Current.BoundingRectangle.Top;
var coords = ((ILocatable) element).Coordinates;
var rect = new Rectangle(iWinLeft + coords.LocationInDom.X, iWinTop + coords.LocationInDom.Y, element.Size.Width, element.Size.Height);
return rect;
}
public static IWebDriver GetDriver(this IWebElement e)
{
return ((IWrapsDriver)e).WrappedDriver;
}
public static IntPtr GetIntPtrHandle(this IWebDriver driver, int timeoutSeconds = Timeout)
{
var end = DateTime.Now.AddSeconds(timeoutSeconds);
while(DateTime.Now < end)
{
// Searching by AutomationElement is a bit faster (can filter by children only)
var ele = AutomationElement.RootElement;
foreach (AutomationElement child in ele.FindAll(TreeScope.Children, Condition.TrueCondition))
{
if (!child.Current.Name.Contains(driver.Title)) continue;
return new IntPtr(child.Current.NativeWindowHandle);;
}
}
return IntPtr.Zero;
}
doc = win.Find.ByConditions(new PropertyCondition(AutomationElement.ClassNameProperty, "Chrome_RenderWidgetHostHWND"));
public static Rectangle GetAbsCoordinates(IWebDriver driver, IWebElement element)
{
var handle = GetIntPtrHandle(driver);
var ae = AutomationElement.FromHandle(handle);
AutomationElement doc = null;
var caps = ((RemoteWebDriver)driver).Capabilities;
var browserName = caps.BrowserName;
switch (browserName)
{
case "safari":
var conditions = (new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "SearchableWebView")));
doc = ae.FindFirst(TreeScope.Descendants, conditions);
break;
case "firefox":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
break;
case "chrome":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Chrome Legacy Window"));
if (doc == null)
{
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));
if (doc == null)
throw new Exception("unable to find element containing browser window");
doc = doc.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
}
break;
case "internet explorer":
doc = ae.FindFirst(TreeScope.Descendants, new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "TabWindowClass")));
break;
}
if (doc == null)
throw new Exception("unable to find element containing browser window");
var iWinLeft = (int)doc.Current.BoundingRectangle.Left;
var iWinTop = (int)doc.Current.BoundingRectangle.Top;
var coords = ((ILocatable)element).Coordinates;
var rect = new Rectangle(iWinLeft + coords.LocationInDom.X, iWinTop + coords.LocationInDom.Y, element.Size.Width, element.Size.Height);
return rect;
}
public static IntPtr GetIntPtrHandle(this IWebDriver driver, int timeoutSeconds = 20)
{
var end = DateTime.Now.AddSeconds(timeoutSeconds);
while (DateTime.Now < end)
{
// Searching by AutomationElement is a bit faster (can filter by children only)
var ele = AutomationElement.RootElement;
foreach (AutomationElement child in ele.FindAll(TreeScope.Children, Condition.TrueCondition))
{
if (!child.Current.Name.Contains(driver.Title)) continue;
return new IntPtr(child.Current.NativeWindowHandle); ;
}
}
return IntPtr.Zero;
}
WebElement htmlElement = driver.findElement(By.tagName("html"));
Point viewPortLocation = ((Locatable) htmlElement).getCoordinates().onScreen();
int x = viewPortLocation.getX();
int y = viewPortLocation.getY();
java.lang.UnsupportedOperationException: Not supported yet.
at org.openqa.selenium.remote.RemoteWebElement$1.onScreen(RemoteWebElement.java:342)
Rectangle rec = new Rectangle(element.getLocation(), element.getSize());
public static long getScrollYPosition() {
WebDriver driver = DriverFactory.getCurrentDriver();
JavascriptExecutor jse = (JavascriptExecutor) driver;
Long scrollYPos = (Long) jse.executeScript("return window.scrollY;");
return scrollYPos;
}
long scrollPosition = getScrollYPosition();
long elemYPositionOnScreen = (long) elem.getLocation().getY() - scrollPosition;
${verticalWindow}= Execute Javascript return window.scrollY;
${verticalElement} = Get Vertical Position /xpath
${hasScrolled} = Evaluate (${verticalElement} - ${verticalWindow}) == 0