【问题标题】:Clicking at coordinates without identifying element单击坐标而不识别元素
【发布时间】:2011-07-21 11:33:34
【问题描述】:

作为我对登录功能的 Selenium 测试的一部分,我想通过识别其坐标并指示 Selenium 单击这些坐标来单击按钮。这将在不识别元素本身的情况下完成(通过 id、xpath 等)。

我知道还有其他更有效的方法来运行点击命令,但我希望专门使用这种方法来最好地匹配用户体验。谢谢。

【问题讨论】:

    标签: selenium selenium-rc


    【解决方案1】:

    一种方法可以做到这一点。使用 ActionChains API,您可以将鼠标移动到包含元素上,调整一些偏移量(相对于该元素的中间)以将“光标”放在所需的按钮(或其他元素)上,然后单击该位置。以下是在 Python 中使用 webdriver 的方法:

    from selenium import webdriver
    from selenium.webdriver.common.action_chains import ActionChains
    browser = webdriver.Chrome()
    elem = browser.find_element_by_selector(".some > selector")
    ac = ActionChains(browser)
    ac.move_to_element(elem).move_by_offset(x_offset, y_offset).click().perform()
    

    你们很快就会驳回这个问题。有许多原因可能需要单击特定位置而不是元素。在我的例子中,我有一个带有覆盖元素的 SVG 条形图,可以捕获所有点击。我想模拟点击其中一个栏,但由于覆盖在那里 Selenium 无法点击元素本身。这种技术对于图像映射也很有价值。

    【讨论】:

    • 如另一个答案中所述,您可以通过这种方式单击元素内的某个位置。这不是 OP 要求的,但它适用于另一个用例。
    • 您在代码的第一行中识别一个元素,OP 明确询问如何在不识别元素的情况下执行此操作。
    • 但这不是可以点击页面中的任意点吗? ActionChains(browser).move_to_element(find_element_by_tag_name('html')).move_by_offset(x, y).click().perform()?
    • 我刚刚尝试了我之前评论中的想法;不起作用。显然,为 <html> 元素生成的 click() 事件不会将点击事件沿 dom 传播到实际元素。
    • @RossPatterson 但这是网络,总是有 some 元素。 F.e. document.body 或 document.head 等。所以总有一种方法可以根据某个元素单击某个坐标。 OP 可能意味着不选择特定的深层嵌套元素。总有任何人都可以访问的根元素。
    【解决方案2】:

    在 C# API 中,您使用操作

    var element = driver.FindElement(By...);
    new Actions(driver).moveToElement(element).moveByOffset(dx, dy).click().perform();
    

    虽然最好尽可能只使用简单的 Id、CSS、Xpath 选择器。但该功能在需要时存在(即单击某些地理位置的元素以获得功能)。

    【讨论】:

    • 确实,您可以通过这种方式单击元素内的某个位置。这不是 OP 要求的,但它适用于另一个用例。
    • 是的,你也可以得到一个Flash游戏的xy然后使用偏移量来点击一个自定义按钮,因为flash通常是固定的px尺寸。
    • 上面的代码只有在鼠标没有被触摸的情况下才会起作用,要重置鼠标坐标需要另外执行moveToElement(element, 0, 0)。代码将是下一个: var element = driver.FindElement(By...); new Actions(driver).moveToElement(element, 0, 0).moveByOffset(dx, dy).click().perform();
    【解决方案3】:

    我第一次使用 JavaScript 代码,效果非常好,直到网站没有点击。

    所以我找到了这个解决方案:

    首先,为 Python 导入 ActionChains 并激活它:

    from selenium.webdriver.common.action_chains import ActionChains
    actions = ActionChains(driver)
    

    要点击会话中的特定点,请使用:

    actions.move_by_offset(X coordinates, Y coordinates).click().perform()
    

    注意:上面的代码只有在鼠标没有被触摸的情况下才有效,重置鼠标坐标使用这个:

    actions.move_to_element_with_offset(driver.find_element_by_tag_name('body'), 0,0))
    

    完整:

    actions.move_to_element_with_offset(driver.find_element_by_tag_name('body'), 0,0)
    actions.move_by_offset(X coordinates, Y coordinates).click().perform()
    

    【讨论】:

      【解决方案4】:

      这可以使用java 中的Actions 类来完成

      使用以下代码 -

      new Actions(driver).moveByOffset(x coordinate, y coordinate).click().build().perform(); 
      

      注意: Selenium 3 不支持 Actions 类的 geckodriver

      另外,请注意 x 和 y 坐标是相对于当前鼠标位置的值。假设鼠标坐标从(0,0)开始,如果你想使用绝对值,你可以使用上面的代码点击它后立即执行下面的操作。

      new Actions(driver).moveByOffset(-x coordinate, -y coordinate).perform();

      【讨论】:

      • 理想情况下,这应该是最新版本的 selenium 的答案。
      【解决方案5】:

      如果您可以选择在 Selenium 中使用 commercial 插件,那么这可能的:假设您的按钮位于坐标 x=123, y=456。然后可以使用Helium点击这些坐标处的元素,如下:

      from helium.api import *
      # Tell Helium about your WebDriver instance:
      set_driver(driver)
      click(Point(123, 456))
      

      (我是 Helium 的作者之一。)

      【讨论】:

        【解决方案6】:

        这适用于我在 Java 中单击坐标而不考虑任何元素。

        Actions actions = new Actions(driver);
        actions.moveToElement(driver.findElement(By.tagName("body")), 0, 0);
        actions.moveByOffset(xCoordinate, yCoordinate).click().build().perform();
        

        第二行代码会将光标重置到浏览器视图的左上角,最后一行将单击作为参数提供的 x,y 坐标。

        【讨论】:

          【解决方案7】:

          在 Selenium Java 中,您可以使用 Javascript 进行尝试:

          WebDriver driver = new ChromeDriver();
          
          if (driver instanceof JavascriptExecutor) {
          	((JavascriptExecutor) driver).executeScript("el = document.elementFromPoint(x-cordinate, y-cordinate); el.click();");
          }

          【讨论】:

            【解决方案8】:

            动作链可能有点挑剔。您也可以通过执行 javascript 来实现。

            self.driver.execute_script('el = document.elementFromPoint(440, 120); el.click();')
            

            【讨论】:

              【解决方案9】:

              我使用了上面列出的许多 Actions 类,但我发现如果我需要从我使用 Firefox Add-On Measurit 获取相对坐标的元素中找到一个相对位置,这很有帮助。 例如:

                      IWebDriver driver = new FirefoxDriver();
                      driver.Url = @"https://scm.commerceinterface.com/accounts/login/?next=/remittance_center/";
                      var target = driver.FindElement(By.Id("loginAsEU"));
                      Actions builder = new Actions(driver);            
                      builder.MoveToElement(target , -375  , -436).Click().Build().Perform();
              

              我通过单击一个元素然后向后拖动直到到达我需要单击的点得到了 -375、-436。 MeasureIT 说我刚刚减去的坐标。在上面的示例中,我在页面上唯一可点击的元素是“loginAsEu”链接。所以我从那里开始。

              【讨论】:

                【解决方案10】:
                    WebElement button = driver.findElement(By.xpath("//button[@type='submit']"));
                    int height = button.getSize().getHeight();
                    int width = button.getSize().getWidth();
                    Actions act = new Actions(driver);
                    act.moveToElement(button).moveByOffset((width/2)+2,(height/2)+2).click();
                

                【讨论】:

                • 您可能希望在您的代码帖子中加上解释为什么它符合查询者的请求。
                • 这是 nodeJS 吗?您如何获得 [Actions] 库?
                【解决方案11】:
                import pyautogui
                from selenium import webdriver
                
                driver = webdriver.Chrome(chrome_options=options)
                driver.maximize_window() #maximize the browser window
                driver.implicitly_wait(30)
                driver.get(url)
                height=driver.get_window_size()['height']
                
                #get browser navigation panel height
                browser_navigation_panel_height = driver.execute_script('return window.outerHeight - window.innerHeight;')
                
                act_y=y%height
                scroll_Y=y/height
                
                #scroll down page until y_off is visible
                try:
                    driver.execute_script("window.scrollTo(0, "+str(scroll_Y*height)+")")
                except Exception as e:
                    print "Exception"
                #pyautogui used to generate click by passing x,y coordinates
                pyautogui.FAILSAFE=False
                pyautogui.moveTo(x,act_y+browser_navigation_panel_height)
                pyautogui.click(x,act_y+browser_navigation_panel_height,clicks=1,interval=0.0,button="left")
                

                这对我有用。希望,这对你们有用:)...

                【讨论】:

                • 欢迎来到 SO!虽然这可能会回答问题,但在描述所涉及的步骤时添加链接和其他数据来支持您的答案会增加可信度。
                【解决方案12】:

                我使用 AutoIt 来做到这一点。

                using AutoIt;
                AutoItX.MouseClick("LEFT",150,150,1,0);//1: click once, 0: Move instantaneous
                
                1. 专业版:
                  • 简单
                  • 不管鼠标移动
                2. 缺点:
                  • 由于坐标是基于屏幕的,因此如果应用缩放,应注意一些事项。
                  • 驱动器不知道应用程序何时完成单击结果操作。应该有一个等待期。

                【讨论】:

                  【解决方案13】:

                  补充一下,因为我为此苦苦挣扎了一段时间。这些是我采取的步骤:

                  1. 找到您需要点击的坐标。在您的控制台中使用以下代码,它将显示并提醒您需要的坐标。
                  document.onclick = function(e)
                  {
                      var x = e.pageX;
                      var y = e.pageY;
                      alert("User clicked at position (" + x + "," + y + ")")
                  };
                  
                  1. 确保元素在屏幕上实际可见,然后使用动作链单击它
                  WebDriverWait(DRIVER GOES HERE, 10).until(EC.element_to_be_clickable(YOUR ELEMENT LOCATOR GOES HERE)) 
                          actions = ActionChains(DRIVER GOES HERE)
                          actions.move_by_offset(X, Y).click().perform() 
                  

                  【讨论】:

                    【解决方案14】:

                    如果此页面上提到的所有其他方法都失败并且您使用的是 python,我建议您使用mouse module 以更原生的方式来代替。代码很简单

                    import mouse
                    mouse.move("547", "508")
                    mouse.click(button='left')
                    

                    你也可以使用keyboard module来模拟键盘动作

                    import keyboard
                    keyboard.write('The quick brown fox jumps over the lazy dog.')
                    

                    要查找鼠标的坐标,可以使用下面的 JavaScript 代码。

                    document.onclick=function(event) {
                        var x = event.screenX ;
                        var y = event.screenY;
                        console.log(x, y) 
                    }
                    

                    如果你不喜欢 screenX,你可以使用 pageX 或 clientX。更多关于here

                    附:我遇到了一个阻止与 JavaScript/DOM/Selenium 进行编程交互的网站。这可能是一种机器人预防机制。但是,他们无法禁止操作系统操作。

                    【讨论】:

                      【解决方案15】:

                      Selenium::WebDriver 具有PointerActions 模块,其中包括许多您可以在不指定元素的情况下链接和/或触发的操作,例如。 move_to_locationmove_by。见detailed specs here。如您所见,您只能使用实际坐标。我确信这个接口是在其他语言/库中实现的。

                      我的简短回复可能会与这里的一些其他 cmets 相呼应,但我只是想提供一个链接以供参考。

                      【讨论】:

                        【解决方案16】:

                        如果你能看到页面的源代码,通过它的 id 或 NAME 属性来引用按钮总是最好的选择。例如,您的“登录”按钮如下所示:

                         <input type="submit" name="login" id="login" />
                        

                        在这种情况下是最好的方法

                        selenium.click(id="login");
                        

                        只是出于好奇 - 这不是 HTTP 基本身份验证吗?在这种情况下,也许看看这个: http://code.google.com/p/selenium/issues/detail?id=34

                        【讨论】:

                        • 谢谢,但这不是我要找的。我知道 selenium 可以通过 id 简单地单击一个按钮。但是,我希望尽可能地模拟用户体验,因此想在我上面解释的方法中单击按钮。
                        【解决方案17】:

                        Selenium 不会让你这样做。

                        【讨论】:

                        • 是否有其他测试框架可以做到这一点?或者也许是 Selenium 的用户扩展?感谢您的回复。
                        • 您的建议通常是测试 Web 应用程序的一个坏主意,原因比评论中的要多。既然你这么执着,那你肯定有充分的理由,但我一时不知所措。无论如何,你必须寻找一个比 Selenium 简单得多的系统,它可能专注于测试原生应用程序。对于 Windows,这通常意味着 AutoIt (autoitscript.com/site/autoit)。
                        • 我认为这是误导,可以使用 Actions(见下文)。
                        • @ChrisRaastad OP 说“点击这些坐标。这将在不实际识别元素本身的情况下完成(通过 id、xpath 等)”。我坚持我的答案。
                        • @user3374242 不,moveToElement() 完全符合原始发帖人的意愿:通过坐标以外的其他方式识别元素。差不多 6 年后,我仍然不明白为什么 OP 会想要这样,但 Selenium 仍然不可能。
                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2013-01-19
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2021-05-18
                        • 2020-01-01
                        相关资源
                        最近更新 更多