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


207

Selenium 1.x或2.x中是否可以滚动浏览器窗口,以使XPath标识的特定元素位于浏览器的视野中?Selenium中有一个聚焦方法,但是在FireFox中似乎并没有实际滚动视图。有人对此有任何建议吗?

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


如果没有其他适合您的方法,您可以尝试使用此工具:stackoverflow.com/a/53771434/7093031
YB原因

Answers:


214

关于滚动已经尝试了很多事情,但是下面的代码提供了更好的结果。

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

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

6
当您position: fixed的页面上可能有一个元素并且遮盖了Selenium要单击的元素时,这是一个很好的解决方案。这些固定元素通常位于底部,因此设置可以scrollIntoView(true)将其很好地移动到视口的顶部。
Mandible79

3
基于最新版本的硒(2.53),这现在是一个很好的帮助方案。Selenium并不总是将元素滚动到视图中,因此这绝对派上用场。
Zoidberg '16

20
如果要滚动到的对象位于当前位置下方,则传递true给;scrollIntoView如果要滚动到的对象位于当前位置false上方,则传递给。我很难弄清楚这一点。
Big Money

2
为什么需要线程睡眠?executeScript应该是同步的
riccardo.tasso

1
@ riccardo.tasso可能已实施睡眠来处理目标应用程序的未知情况。如果它具有动态滚动,或者是单页应用程序,则在滚动后会加载页面的下一部分,还有其他可能性。从经验上来讲,Selenium经常破坏我公司的站点,因为自动操作发生的速度比Javascript不能完成的速度快,因此传递了不完整的数据模型。有些地方可能认为它是一个错误,但是有人告诉我“没有人可以调用这种情况,所以它不是真正的错误。” 这就是生活。
Solonotix

157

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

Java:

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

蟒蛇:

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

7
如果WebElement不在查看端口中,则可以正常工作吗?
virusrocks

9
@Dominik:Selenium如何将鼠标移动到屏幕之外的元素?显然,它必须首先将元素滚动到视图中,然后将鼠标移到该元素上。我测试了 这段代码可在Firefox Webdriver 2.48上运行,但是存在一个错误:当页面中有iframe时,如果element.LocationOnScreenOnceScrolledIntoView正确滚动,则iframe中的滚动将无法正常进行。(尽管文档说此命令仅返回一个位置,但它也会滚动!)
Elmue 2015年

7
seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/…上的文档 现在清楚地声明“将鼠标移到元素的中间。该元素被滚动到视图中,并且其位置使用getBoundingClientRect。”
乔治·潘塔兹

5
上面的代码是“官方方式”,Java Selenium希望您将元素滚动到视口中,但是在尝试了许多事情之后,JS实现对我来说似乎更可靠。 这种方法尤其如此。
Miwa

2
没有为我工作:-| 使用stackoverflow.com/a/23902068/661414代替。
勒基普

28
JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("javascript:window.scrollBy(250,350)");

您可能想尝试一下。


1
谢谢。在Selenium的自动滚动导致另一个元素使我需要单击的元素模糊的情况下,我需要使用此方法。我能够滚动任意数量,以使该元素在视口中可见,而不会被遮挡。
Daniel Richnak 2012年

这仅在FIrefox中有效,Chrome和IE不支持此方法
病毒

这就是为什么要js.ExecuteScript("arguments[0].scrollIntoView(true);" + "window.scrollBy(0,-100);", e);用于IE,Firefox和js.ExecuteScript("arguments[0].scrollIntoViewIfNeeded(true);", e);Chrome。简单。
IamBatman

((JavascriptExecutor) driver).executeScript("javascript:window.scrollBy(0,250)");这在Chrome中有效。唯一对我有效的解决方案。与第一个评论者相同,我在底部有一个固定的元素,该元素使我需要单击的元素变得晦涩。


15

如果要使用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));");

10

定位任何元素并发送向下键(或向上/向左/向右)似乎也可以。我知道这有点麻烦,但是我也不是很想使用JavaScript解决滚动问题。

例如:

WebElement.sendKeys(Keys.DOWN);

这与使用js一样不失为一种技巧,这确实是最简单的事情。我发现这主要是IE的问题,在该问题中,单击会尝试将元素滚动到视图中,但并没有完全实现。如果使用正确的try / catch / loop方案,则使用{PGUP}的解决方案也一样优雅。
jibbs 2015年

你救了我的一天!谢谢
Jesko R. 16-3-4

在我看来,下一页是可行的。这是一个不错的技巧(相对于所有js技巧)。
akostadinov

谢谢@DevDave!C#中的等效项:var elem = driver.FindElement(By.Id("element_id")); elem.SendKeys(Keys.PageDown);
Watth

9
webElement = driver.findElement(By.xpath("bla-bla-bla"));
((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", webElement);

有关更多示例,请转到此处。全部使用俄语,但是Java代码是跨文化的:)


我能理解为什么此解决方案的值为-1吗?
josephnvu

因为它仅适用于Firefox。没有其他浏览器支持此方法。
韦恩·艾伦

如果有人需要上述文件的俄文翻译,我们将竭诚为您服务。
僧侣

8

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

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

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

我对此有完整的帖子和视频:

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


@Mukesh otwani上面的代码将向下滚动,但是abt如何向上滚动而不使用其中定义的任何像素。

6

您可以使用以下代码片段进行滚动:

C#

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

你有它


6

这为我工作:

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

5

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

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


19
这如何回答问题?
reinierpost 2012年

57
似乎对我来说不是这样。对于
看不见的

5
@DevDave我有同样的问题,除了我自己的情况,硒不对元素执行单击操作,也没有例外。我以前没有遇到过问题,也不知道是什么原因造成的。
Zeinab Abbasimazar 2013年

5
隐式滚动在浏览器之间有所不同。我在页面中间的弹出菜单中对元素进行了测试。使用Ruby gem selenium_webdriver 2.43,我发现铬浏览器37(我相信Internet Explorer)确实确实将菜单项滚动到视图中并单击了它。但是Firefox 32似乎根本没有滚动,然后失败并显示“元素当前不可见,因此可能无法与之交互”。
skierpage 2014年

9
这个答案是错误的。根据Selenium 2.0的规范,WebElement.click()元素必须可见才能单击。它不会代表您滚动。
吉利2014年

5

使用驱动程序发送键,例如pagedowndownarrow键,以使该元素可见。我知道这太简单了,可能无法在所有情况下都适用。


1
这是无稽之谈。您可能必须在大页面上向下发送许多页面。它缓慢且不可靠。
Elmue

2
是。我同意。但我确实说过“并非在所有情况下都适用”
Ganesh S

element在可见页面中找到一些已知内容并发送PageDown element.SendKeys(Keys.PageDown);对我有用。
Gokul

我建议您使用Alt键,这样您就不会滚动页面并使用try / except(Python)子句来处理尝试将键发送给某些元素时可能发生的错误。
Alex K.

4

根据我的经验,当页面上有多个可滚动部分时,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)')在需要时立即进行处理。
Al Chou

Watir具有Element#scroll_into_view委托给Selenium的方法location_once_scrolled_into_view。但是两者都与Seleniums的默认行为没有什么不同,因此溢出元素仍然会阻碍我们尝试单击的任何内容。
akostadinov


2

有时我还遇到了使用硒滚动的问题。因此,我使用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);");

2

如果您认为其他答案太过分了,那么这个答案也不错,但是不涉及JavaScript注入。

当按钮不在屏幕上时,它会断裂并滚动到它,因此请重试...。

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

2

这是JavaScript的重复解决方案,但增加了waiting元素。

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

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

?? <-是什么意思?

1

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

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)没有。哪种方法都可以,取决于您的情况。
rsenna 2014年

我的情况恰恰相反-正确,错误失败,但仅限于点击。它确实会正确滚动以显示错误,这是我喜欢的,但是无论出于何种原因,Selenium仍然无法单击它。使用true滚动会使所有内容都过高,但至少可以正常工作。
比尔·希勒曼

用户sendkey尽可能输入而不是单击-如果浏览器未达到100%缩放比例,则可以避免出现问题。
Zunair

1
def scrollToElement(element: WebElement) = {
  val location = element.getLocation
  driver.asInstanceOf[JavascriptExecutor].executeScript(s"window.scrollTo(${location.getX},${location.getY});")
}

1

您可能要访问页面 使用Javascript Scroll Web元素页面和Selenium WebDriver页面

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也支持它。您可能遇到任何特定的问题?
virusrocks

1

在大多数情况下,滚动此代码将起作用。

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

1

爪哇

尝试滚动到元素利用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 +")");


0

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函数...假设您正在采用目标元素的高度
Shubham Jain

0

这是我使用PHP webDriver for Selenium的方法。它适用于Selenium独立服务器2.39.0 + https://github.com/Element-34/php-webdriver + Firefox 25.0

$element=$session->welement("xpath", "//input[@value='my val']");
$element->click();
$element=$session->welement("xpath", "//input[@value='ma val2']");
$element->location_in_view(); // < -- this is the candy
$element->click();

注意:我使用Element34 PHP-webdriver的自定义版本。但是核心没有任何变化。我只是使用我的“元素”而不是“元素”。但这对所涉案件没有影响。该驱动程序作者说:“允许几乎所有API调用都是WebDriver协议本身定义的直接转换。” 因此,使用其他编程语言应该没有问题。

在我的设置中,仅单击不起作用。它将进行滚动而不是单击,因此我不得不单击两次而不调用“ location_in_view()”。

注意:此方法适用于可查看的元素,例如类型按钮的输入。

看一眼: http //code.google.com/p/selenium/wiki/JsonWireProtocol#/session/ sessionId/element/ id/location

JsonWireProtocol#的描述建议使用location + moveto,因为location _in_view是内部方法。


0

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

我选择它而不是JavaScript注入技术,只是因为它的hacky少了。


这是哪种编程语言?
akostadinov

0

我一直在使用ADF组件进行测试,如果使用了延迟加载,则必须有单独的滚动命令。如果未加载该对象,而您尝试使用Selenium来找到它,则Selenium将抛出一个找不到元素的异常。


0

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

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);
}

0

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

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

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


0

一个解决方案是:

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);
}

0

这段代码为我工作:

JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("javascript:window.scrollBy(250, 350)");

为我工作。Dart WebDriver实施尚无操作。
君特Zöchbauer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.