ChatGPT解决这个技术问题 Extra ChatGPT

使用 Selenium 将元素滚动到视图中

Selenium 1.x 或 2.x 中是否有任何方法可以滚动浏览器窗口,以便浏览器可以看到由 XPath 标识的特定元素? Selenium 中有一个 focus 方法,但它似乎并没有在 FireFox 中物理滚动视图。有人对如何做到这一点有任何建议吗?

我需要这个的原因是我正在测试页面上元素的点击。不幸的是,除非元素可见,否则该事件似乎不起作用。我无法控制单击元素时触发的代码,因此我无法对其进行调试或修改,因此,最简单的解决方案是将项目滚动到视图中。

如果没有其他方法适合您,您可以尝试这个 hacky:stackoverflow.com/a/53771434/7093031
3 种方法JavascriptExecutor js = (JavascriptExecutor) driver; js.executeScript("window.scrollBy(0,250)", "”); Actions action = new Actions(driver); action.moveToElement(element).perform(); WebElement element = driver.findElement(By.<locator>)); element.sendKeys(Keys.DOWN);

i
iliketocode

在滚动方面尝试了很多事情,但下面的代码提供了更好的结果。

这将滚动直到元素出现在视图中:

WebElement element = driver.findElement(By.id("id_of_element"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(500); 

//do anything you want with the element

当您的页面上可能有一个带有 position: fixed 的元素并且它掩盖了 Selenium 想要点击的元素时,这是一个很好的解决方案。这些固定元素通常位于底部,因此设置 scrollIntoView(true) 会将其很好地移动到视口的顶部。
基于最新版本的 selenium (2.53),现在这是一个很好的辅助解决方案。 Selenium 并不总是将元素滚动到视图中,所以这肯定会派上用场。
如果您滚动到的对象在您当前所在的位置下方,则将 true 传递给 scrollIntoView,如果您正在滚动到的对象在您当前所在的位置上方,则传递 false。我很难弄清楚这一点。
为什么需要线程睡眠? executeScript 应该是同步的
@riccardo.tasso 可能已实现睡眠以处理目标应用程序的未知数。如果它具有动态滚动,或者在滚动后加载页面下一位的单页应用程序,以及其他可能性。从经验来看,Selenium 经常破坏我公司的网站,因为自动化操作发生的速度比 Javascript 完成的速度快,因此传递了一个不完整的数据模型。有些地方可能认为这是一个错误,但有人告诉我“没有人可以调用这样的场景,所以它不是一个真正的错误。”这就是生活。
s
supervacuo

您可以使用 org.openqa.selenium.interactions.Actions 类移动到元素。

爪哇:

WebElement element = driver.findElement(By.id("my-id"));
Actions actions = new Actions(driver);
actions.moveToElement(element);
actions.perform();

Python:

from selenium.webdriver.common.action_chains import ActionChains
ActionChains(driver).move_to_element(driver.sl.find_element_by_id('my-id')).perform()

如果 WebElement 不在视口中,这会起作用吗?
@Dominik:Selenium 如何将鼠标移动到屏幕外的元素?显然它必须首先将元素滚动到视图中,然后将鼠标移动到它。我测试了它。此代码适用于 Firefox Webdriver 2.48,但有一个错误:当页面中有 iframe 时,滚动在 iframe 中无法正常工作,而 element.LocationOnScreenOnceScrolledIntoView 滚动正确。 (虽然文档说这个命令只返回一个位置,但它也会滚动!)
seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/… 处的文档现在明确指出“将鼠标移动到元素的中间。元素滚动到视图中,并且使用 getBoundingClientRect 计算其位置。”
上面的代码是“官方方式”Java Selenium 希望你将一个元素滚动到视口中,但是在尝试了很多事情之后,JS 实现对我来说似乎更可靠。 This method 尤其如此。
对我不起作用:-|改为使用 stackoverflow.com/a/23902068/661414
L
Liam
JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("javascript:window.scrollBy(250,350)");

你可能想试试这个。


谢谢。在 Selenium 的自动滚动导致另一个元素遮挡我需要单击的元素的情况下,我需要使用此方法。我能够滚动任意数量以使元素在视口中可见,而不会被遮挡。
这只适用于 Firefox,Chrome 和 IE 不支持这种方法
这就是为什么您将 js.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(0,-100);", e); 用于 IE 和 Firefox,而将 js.ExecuteScript("arguments[0].scrollIntoViewIfNeeded(true);", e); 用于 Chrome。简单的。
((JavascriptExecutor) driver).executeScript("javascript:window.scrollBy(0,250)"); 这在 Chrome 中有效。唯一对我有用的解决方案。与第一个评论者的情况相同,我在底部有一个固定元素,它一直遮挡我需要单击的元素。
i
iliketocode

如果您想使用 Selenium webdriver 在 Firefox 窗口上滚动,其中一种方法是在 Java 代码中使用 JavaScript。向下滚动(到网页底部)的 JavaScript 代码如下:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollTo(0, Math.max(document.documentElement.scrollHeight, document.body.scrollHeight, document.documentElement.clientHeight));");

D
DevDave

定位任何元素和 sending down keys(或上/左/右)似乎也有效。我知道这有点小题大做,但我也不太喜欢使用 JavaScript 来解决滚动问题。

例如:

WebElement.sendKeys(Keys.DOWN);

这不亚于使用 js,它确实是最简单的事情。我发现这主要是 IE 的一个问题,其中单击尝试将元素滚动到视图中,但并没有完全实现。如果使用正确的 try/catch/loop 场景,使用 {PGUP} 的解决方案同样优雅。
你救了我的一天!谢谢
在我的情况下,向下页面是有效的。这是一个不错的 hack(与所有 js hack 相比)。
谢谢@DevDave! C# 中的等效项:var elem = driver.FindElement(By.Id("element_id")); elem.SendKeys(Keys.PageDown);
i
iliketocode

在 Selenium 中,我们需要借助 JavaScript 执行器来滚动到元素或滚动页面:

je.executeScript("arguments[0].scrollIntoView(true);", element);

在上面的语句中,element 是我们需要滚动的确切元素。我尝试了上面的代码,它对我有用。

我有一个完整的帖子和视频:

http://learn-automation.com/how-to-scroll-into-view-in-selenium-webdriver/


@Mukesh otwani 上面的代码将向下滚动,但是如何在不使用其中定义的任何像素的情况下向上滚动。
P
Peter Mortensen
webElement = driver.findElement(By.xpath("bla-bla-bla"));
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", webElement);

如需更多示例,请参阅 go here。全部都是俄语,但 Java 代码是跨文化的 :)


我能理解为什么这个解决方案有 -1 吗?
因为它只适用于 Firefox。没有其他浏览器支持这种方法。
如果有人需要上述文件的俄语翻译,我们很乐意提供帮助。
M
Mohsin Awan

您可以使用此代码段滚动:

C#

var element = Driver.FindElement(By.Id("element-id"));
Actions actions = new Actions(Driver);
actions.MoveToElement(element).Perform();

你有它


A
Ahmed Ashour

这对我有用:

IWebElement element = driver.FindElements(getApplicationObject(currentObjectName, currentObjectType, currentObjectUniqueId))[0];
 ((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", element);

A
Ashley Frieze

我发现我的元素的边界矩形不正确,导致浏览器滚动到屏幕外。但是,以下代码对我来说效果很好:

private void scrollToElement(WebElement webElement) throws Exception {
    ((JavascriptExecutor)webDriver).executeScript("arguments[0].scrollIntoViewIfNeeded()", webElement);
    Thread.sleep(500);
}

这应该是官方的回答。它完美无缺!
这是唯一正确的答案。如果应用程序具有固定的页眉和页脚,则只有此解决方案有效。谢谢你。
P
Peter Mortensen

使用驱动程序发送诸如 pagedown 或 downarrow 键之类的键以将元素显示在视图中。我知道这是一个过于简单的解决方案,可能并不适用于所有情况。


这是无稽之谈。您可能必须在一个大页面上发送十几页。它很慢而且不可靠。
是的。我同意。但我确实说过“并非在所有情况下都适用”
在可查看的页面中找到一些已知的 element 并发送 PageDown element.SendKeys(Keys.PageDown); 对我有用。
我建议使用 Alt 键,这样您就不会滚动页面并使用 try/except (Python) 子句来处理尝试将键发送到某些元素时可能发生的错误。
R
Robbie Wareham

根据我的经验,当页面上有多个可滚动部分(这很常见)时,Selenium Webdriver 不会在单击时自动滚动到元素。

我正在使用 Ruby,对于我的 AUT,我必须对 click 方法进行猴子修补,如下所示;

class Element

      #
      # Alias the original click method to use later on
      #
      alias_method :base_click, :click

      # Override the base click method to scroll into view if the element is not visible
      # and then retry click
      #
      def click
        begin
          base_click
        rescue Selenium::WebDriver::Error::ElementNotVisibleError
          location_once_scrolled_into_view
          base_click
        end
      end

'location_once_scrolled_into_view' 方法是 WebElement 类的现有方法。

我感谢您可能没有使用 Ruby,但它应该会给您一些想法。


我在 module Capybara :: module Node 中声明了上述内容,我需要调用 native.location_once_scrolled_into_view 而不仅仅是 location_once_scrolled_into_view 。我还拯救了 ::Selenium::WebDriver::Error::UnknownError ,这是我在 Firefox 44.0.2 中经常遇到的。但我发现这个解决方案不够灵活,最终将 <Element>.native.location_once_scrolled_into_view 调用放入验收测试本身,然后在需要时立即调用 page.execute_script('window.scrollByPages(-1)')
Watir 具有委托给 Selenium 的 location_once_scrolled_into_view 的方法 Element#scroll_into_view。但两者都与 Selenium 的默认行为没有什么不同,因此溢出元素仍然会阻碍我们尝试单击的任何内容。
P
Peter Mortensen

用于将元素滚动到视图中的 Ruby 脚本如下所示。

$driver.execute_script("arguments[0].scrollIntoView(true);", element)
sleep(3)
element.click

A
Ahmed Ashour

有时我也遇到了使用 Selenium 滚动的问题。所以我使用 javaScriptExecuter 来实现这一点。

向下滚动:

WebDriver driver = new ChromeDriver();
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.scrollBy(0, 250)", "");

或者,也

js.executeScript("scroll(0, 250);");

向上滚动:

js.executeScript("window.scrollBy(0,-250)", "");

或者,

js.executeScript("scroll(0, -250);");

L
Lukasz

这是使用 JavaScript 的重复解决方案,但添加了等待元素。

否则,如果正在对元素执行某些操作,则可能会出现 ElementNotVisibleException

this.executeJavaScriptFunction("arguments[0].scrollIntoView(true);", elementToBeViewable);
WebDriverWait wait = new WebDriverWait(getDriver(), 5);
wait.until(ExpectedConditions.visibilityOf(elementToBeViewable));

?? <- 什么意思?
A
AutomatedTester

Selenium 2 尝试滚动到该元素,然后单击它。这是因为 Selenium 2 不会与元素交互,除非它认为它是可见的。

滚动到元素是隐式发生的,因此您只需要找到该项目然后使用它。


这是如何回答这个问题的?
对我来说似乎不是这样。对于看不见的元素,我收到“元素不可点击”错误
@DevDave我有同样的问题,除了在我的情况下,selenium 不对元素执行点击操作,也没有例外。我以前没有这个问题,我不知道是什么原因造成的。
隐式滚动因浏览器而异。我在页面中间的弹出菜单中测试了一个元素。使用 Ruby gem selenium_webdriver 2.43,我发现 chromium-browser 37(我相信 Internet Explorer)确实将菜单项滚动到视图中并单击它。但是 Firefox 32 似乎根本不滚动,然后失败并显示“元素当前不可见,因此可能无法与之交互”。
这个答案是错误的。根据 Selenium 2.0 WebElement.click() 的规范,需要元素可见才能点击它。它不会代表您滚动。
c
cf stands with Monica

我用这种方式滚动元素并单击:

List<WebElement> image = state.getDriver().findElements(By.xpath("//*[contains(@src,'image/plus_btn.jpg')]"));

for (WebElement clickimg : image)
{
  ((JavascriptExecutor) state.getDriver()).executeScript("arguments[0].scrollIntoView(false);", clickimg);
  clickimg.click();
}

在我的例子中,scrollIntoView(false) 有效,但 scrollIntoView(true) 没有。 Either can work,这取决于您的场景。
我的情况恰恰相反——真有效,假失败,但仅限于点击。它确实正确滚动为假,这是我更喜欢的,但无论出于何种原因,Selenium 仍然看不到它的点击。使用真正的卷轴一切都太高了,但至少它有效。
用户发送键尽可能地输入而不是单击 - 如果浏览器不是 100% 缩放,它可以避免出现问题。
o
omnomnom
def scrollToElement(element: WebElement) = {
  val location = element.getLocation
  driver.asInstanceOf[JavascriptExecutor].executeScript(s"window.scrollTo(${location.getX},${location.getY});")
}

P
Peter Mortensen

对我有用的是在浏览器窗口底部的元素上使用 Browser.MoveMouseToElement 方法。它奇迹般地在 Internet Explorer、Firefox 和 Chrome 中运行。

我选择它而不是 JavaScript 注入技术只是因为它感觉不那么 hacky。


这是哪种编程语言?
A
Ahmed Ashour

您可能想要访问页面 Scroll Web elements and Web page- Selenium WebDriver using Javascript

public static void main(String[] args) throws Exception {

    // TODO Auto-generated method stub
    FirefoxDriver ff = new FirefoxDriver();
    ff.get("http://toolsqa.com");
    Thread.sleep(5000);
    ff.executeScript("document.getElementById('text-8').scrollIntoView(true);");
}

@AbhishekBedi 我记得 Chrome 也支持它。您可能遇到过任何具体问题吗?
D
David Clarke

如果您认为其他答案太 hacky,这个答案也是,但不涉及 JavaScript 注入。

当按钮离开屏幕时,它会中断并滚动到它,所以重试它...¯\_(ツ)_/¯

try
{
    element.Click();
}
catch {
    element.Click();
}

这个。这太糟糕了,我什至不能......不要浪费尝试以这种方式捕获所有内容,您可以通过准备任何其他答案来构建更好的代码
s
sp324

在大多数情况下滚动此代码都可以使用。

WebElement element = driver.findElement(By.xpath("xpath_Of_Element"));                 
js.executeScript("arguments[0].click();",element);

f
frianH

JAVA

尝试使用 x y 位置滚动到元素,并将 JavascriptExecutor 与此参数一起使用:"window.scrollBy(x, y)"

导入后:

import org.openqa.selenium.WebElement;
import org.openqa.selenium.JavascriptExecutor;

首先,您需要获取元素的 x y 位置。

//initialize element
WebElement element = driver.findElement(By.id("..."));

//get position
int x = element.getLocation().getX();
int y = element.getLocation().getY();

//scroll to x y 
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(" +x +", " +y +")");

k
kiranjith

我不确定这个问题是否仍然相关,但在参考 https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView 中的 scrollIntoView 文档之后。

最简单的解决方案是

executor.executeScript("arguments[0].scrollIntoView({block: \"center\",inline: \"center\",behavior: \"smooth\"});",element);

这会将元素滚动到页面的中心。


M
Masih Jahangiri

Javascript

解决方法很简单:

const element = await driver.findElement(...)
await driver.executeScript("arguments[0].scrollIntoView(true);", element)
await driver.sleep(500);

d
djangofan

Selenium 的默认行为是滚动,因此元素几乎不会出现在视口顶部的视图中。此外,并非所有浏览器都具有完全相同的行为。这是非常不满意的。如果您像我一样录制浏览器测试的视频,您想要的是让元素滚动到视图中并垂直居中。

这是我的 Java 解决方案:

public List<String> getBoundedRectangleOfElement(WebElement we)
{
    JavascriptExecutor je = (JavascriptExecutor) driver;
    List<String> bounds = (ArrayList<String>) je.executeScript(
            "var rect = arguments[0].getBoundingClientRect();" +
                    "return [ '' + parseInt(rect.left), '' + parseInt(rect.top), '' + parseInt(rect.width), '' + parseInt(rect.height) ]", we);
    System.out.println("top: " + bounds.get(1));
    return bounds;
}

然后,滚动,你这样称呼它:

public void scrollToElementAndCenterVertically(WebElement we)
{
    List<String> bounds = getBoundedRectangleOfElement(we);
    Long totalInnerPageHeight = getViewPortHeight(driver);
    JavascriptExecutor je = (JavascriptExecutor) driver;
    je.executeScript("window.scrollTo(0, " + (Integer.parseInt(bounds.get(1)) - (totalInnerPageHeight/2)) + ");");
    je.executeScript("arguments[0].style.outline = \"thick solid #0000FF\";", we);
}

缺少 getViewPortHeight 函数...假设您正在获取目标元素的高度
P
Peter Mortensen

我一直在使用 ADF 组件进行测试,如果使用延迟加载,您必须有一个单独的滚动命令。如果对象未加载并且您尝试使用 Selenium 找到它,Selenium 将引发 element-not-found 异常。


P
Peter Mortensen

如果没有任何效果,请在单击之前尝试此操作:

public void mouseHoverJScript(WebElement HoverElement) {

    String mouseOverScript = "if(document.createEvent){var evObj = document.createEvent('MouseEvents');evObj.initEvent('mouseover', true, false); arguments[0].dispatchEvent(evObj);} else if(document.createEventObject) { arguments[0].fireEvent('onmouseover');}";
    ((JavascriptExecutor) driver).executeScript(mouseOverScript, HoverElement);
}

P
Peter Mortensen

在 Java 中,我们可以使用 JavaScript 进行滚动,如以下代码所示:

driver.getEval("var elm = window.document.getElementById('scrollDiv'); if (elm.scrollHeight > elm.clientHeight){elm.scrollTop = elm.scrollHeight;}");

您可以为“elm.scrollTop”变量分配所需的值。


A
Ahmed Ashour

一个解决方案是:

public void javascriptclick(String element)
{
    WebElement webElement = driver.findElement(By.xpath(element));
    JavascriptExecutor js = (JavascriptExecutor) driver;

    js.executeScript("arguments[0].click();", webElement);
    System.out.println("javascriptclick" + " " + element);
}