使用Selenium WebDriver获取网页的屏幕位置

使用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

有没有一种方法可以通过SeleniumWebDriver获得HTML窗口(页面主体)的屏幕坐标


您可以这样尝试:

   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