Selenium Chrome驱动程序的getText()方法有时会返回空字符串。

55

我有一个有趣的问题,就是使用selenium chrome driver的getText()方法(Java)对一些元素返回空字符串,而对于其他具有相同xpath的元素则返回非空字符串。以下是页面的一部分:

<div __gwt_cell="cell-gwt-uid-223" style="outline-style:none;">
<div>Text_1</div>
<div>Text_2</div>
<div>Text_3</div>
<div>Text_4</div>
<div>Text_5</div>
<div>Text_6</div>
</div>

对于每个内部的 <div> 标签,我可以获得 getTagName()getLocation()isEnabled()isDisplayed() 方法的有效返回值。然而,getText() 方法在某些 <div> 上返回空字符串。

此外,我注意到如果我使用 Mac Chrome 驱动程序,则始终是“Text_5”返回空字符串;如果我使用 Windows Chrome 驱动程序,则始终是“Text_2”返回空字符串。但如果我使用 Firefox 驱动程序,则 getText() 方法可以从所有 <div> 中返回预期的文本。

有其他人遇到过这个问题吗?

在我的代码中,我使用类似下面的方法...

ArrayList<WebElement> list = (ArrayList<WebElement>) driver.findElements(By.xpath(“my xPath here”));
for (WebElement e: list) System.out.println(e.getText());

如下所建议,这是我正在使用的实际xPath。上面的页面片段涉及最后两个

//*[@class='gwt-DialogBox']//tr[contains(@class,'data-grid-table-row')]//td[contains(@class,'lms-assignment-selection-wizard-cell')]/div/div

2
该元素是否在屏幕上可见,还是不在视图中?如果元素在视口之外,“getText()”将返回一个空字符串。 - Faiz
10个回答

116

更新: textContent 属性是更好的选择,并且在大多数浏览器上得到支持。这篇博客文章详细解释了它们之间的区别: innerText vs. textContent

作为替代方案,innerText 属性将返回存在于 DOM 中的元素的文本内容。

element.getAttribute("innerText")

isDisplayed() 方法有时会在元素实际上没有隐藏,但超出了视口时出现问题;getText() 会返回这种元素的空字符串。

您还可以使用 JavaScript 滚动到元素并将其带入视口,方法如下:

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

然后 getText() 应该返回正确的值。

isDisplayed() 方法的详细信息可以在这个 SO 问题中找到:

Selenium WebDriver 的 isDisplayed() 方法是如何工作的


3
不错。getAttribute("innerText")的技巧起作用了。有趣的是,对于给定的元素(例如'<div>Text_2</div>'),isDisplayed()返回true,getText()返回空字符串,但getAttribute("innerText")返回'Text_2'。这似乎非常有效。在这种情况下,将元素滚动到视图中并没有真正发挥作用,但这在其他情况下肯定适用。非常感谢。 - JackhammersForWeeks
很好,getAttribute("innerText") 将完美地工作。+1分 - Ranjit Swain
5
“innerText”属性的技巧在我的情况下没有起作用。我正在使用Selenium与ZK应用程序。对我有用的解决方案是“textContent”属性或“innerHTML”属性,具体取决于我要访问的ZK组件。感谢您的回答,它节省了我很多时间来寻找自己的解决方案。 - CVi
5
请注意,当 innerText 失败时,value 对我有用。 - rath
谢谢你的详细回答,我想知道是否有文档可以找到像 “innerText” 这样的东西的列表。 - LoveJavaTwo
显示剩余2条评论

8
WebElement.getAttribute("value")应该可以帮助您!!

1
当getText()返回空字符串时,这个解决方案在使用火狐浏览器时对我有效。 - andyd

3
这并不是一个解决方案,所以我不知道它是否属于答案,但它太长了不能作为评论,并包含链接,所以我将其放在答案中。我也遇到过这个问题。经过一些挖掘,似乎当尝试获取屏幕上不可见元素的文本时会出现问题。(如@Faiz上面的评论所述。)如果元素没有滚动,或者您向下滚动并且元素靠近文档顶部并且在滚动后不再可见,则可能会发生这种情况。我看到您有一个FindElements()调用,该调用获取元素列表。至少有些元素可能是不可见的;您可以通过在列表中的每个元素上尝试boolean b = webElement.isDisplayed();并检查结果来检查此情况。 (请参见here,这是一个很长时间的讨论,但仍然没有解决方案。)
显然,这是一个故意的设计决定(参见此处);在不可见元素上使用gettext会返回空值。为什么他们如此坚定地要这样做,我不知道。已经提出了各种解决方法,包括在获取文本之前单击元素或滚动到它。 (请参阅上面链接中的示例代码。)我无法保证这些解决方法是否有效,但它们只是试图将元素带入视野,以便文本可用。不确定这对您的应用程序有多实用;对我来说并不是。由于某种原因,FirefoxDriver没有这个问题,所以我使用它。

很抱歉我不能给你一个更好的答案 - 也许如果你在问题页面提交一个错误报告,他们会发现很多人认为这是一个缺陷而不是一个功能,并改变功能。

祝你好运! bsg

编辑

请查看这个问题,以获取一个可能的解决方案。如果isDisplayed返回true,则不能完全按照给定的方式使用它,但是如果您知道哪个元素导致问题,或者如果文本通常不为空并且可以设置“如果字符串为空”条件来捕获它发生时,仍然可以尝试它。不幸的是,它并不适用于所有人。 新更新 我刚刚尝试了下面给出的答案,并且对我有效。所以谢谢,Faiz!

奇怪的是,isDisplayed() 对于该元素返回 true,但 getText() 返回一个空字符串。同样奇怪的是,在 Mac 上的 Chrome 驱动程序的结果与 Windows 上的 Chrome 驱动程序的结果不同。感谢您的评论,感谢您抽出时间。 - JackhammersForWeeks
这非常有趣。我实际上在phantomjs驱动程序中再次遇到了这个问题。 - bsg

2

element.getAttribute("innerText") 在我这里奏效了,而 getText() 则返回空值。


2

我的是Python,但核心逻辑类似:

  • webElement.text
  • webElement.get_attribute("innerText")
  • webElement.get_attribute("textContent")

完整代码:

def getText(curElement):
    """
    Get Selenium element text

    Args:
        curElement (WebElement): selenium web element
    Returns:
        str
    Raises:
    """
    # # for debug
    # elementHtml = curElement.get_attribute("innerHTML")
    # print("elementHtml=%s" % elementHtml)

    elementText = curElement.text # sometime NOT work

    if not elementText:
        elementText = curElement.get_attribute("innerText")

    if not elementText:
        elementText = curElement.get_attribute("textContent")

    # print("elementText=%s" % elementText)
    return elementText

叫它:

curTitle = getText(h2AElement)

希望这对你有所帮助。


使用“innerText”属性对我非常有效,谢谢,但是当使用getText()时失败的原因让我感到疑惑。 - Mideel
@Mideel 看起来只是一个 bug? - crifan

2

我最近遇到了类似的问题。

我需要检查滚动框中是否存在菜单选项卡“LIFE EVENTS”。问题在于有许多菜单选项卡,您需要向下滚动才能看到其余的菜单选项卡。因此,我的初始解决方案可以处理可见的菜单选项卡,但无法处理不可见的菜单选项卡。

我使用以下xpath将selenium指向整个滚动框的父元素。

Original Answer翻译成"最初的回答"

@FindBy(xpath = "//div[contains(@class, 'menu-tree')]")
protected WebElement menuTree;

然后我创建了一个WebElement列表,可以通过递增来遍历。

如果菜单选项卡可见,则解决方案有效并返回true。但是,如果菜单选项卡不可见,则返回false。

Original Answer翻译成"最初的回答"

public boolean menuTabPresent(String theMenuTab) {
    List<WebElement> menuTabs = new ArrayList<WebElement>();
    menuTabs = menuTree.findElements(By.xpath("//i/following-sibling::span"));

    for(WebElement e: menuTabs) {
        System.out.println(e.getText());
        if(e.getText().contains(theMenuTab)) {
            return true;
        }
    }
    return false;
}

我找到了2个解决方法,它们都同样有效。最初的回答。
    for(WebElement e: menuTabs) {
        scrollElementIntoView(e); //Solution 1
        System.out.println(e.getAttribute("textContent")); //Solution 2
        if(e.getAttribute("textContent").contains(theMenuTab)) {
            return true;
        }
    }
    return false;

解决方案1调用以下方法。在selenium运行时,结果会导致滚动条向下移动。翻译后的内容:

解决方案1调用以下方法,在selenium运行时会使滚动条向下移动。





protected void scrollElementIntoView(WebElement element) {
    ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true)", element);
}

解决方案2获取您指向的属性的文本内容(即使对于当前不可见的菜单选项),因此可以很好地完成.getText()在这种情况下无法完成的工作。

原始答案:最初的回答


2
for (int count=0;count<=sizeofdd;count++)
{       
   String GetInnerHTML=getddvalue.get(count).getAttribute("innerHTML");
}

在这里, 1. getddvalue是WebElement 2. sizeofdd是getddvalue的大小


1
如果您不关心isDisplayed或滚动位置,也可以编写以下内容。
String text = ((JavaScriptExecutor)driver).executeScript("return $(arguments[0]).text();", element);

或者不使用jQuery。
String text = ((JavaScriptExecutor)driver).executeScript("return arguments[0].innerText;", element);

这是页面上最好的答案,每次都能正常工作(JavaScript)! - JohnP2

0

关于getText(),我也遇到了一个问题并解决了:

WebElement errMsg;
errMsg = driver.findElement(By.xpath("//div[@id='mbr-login-error']"));
WebElement parent = driver.findElement(By.xpath("//form[@id='mbr-login-form']"));
List<WebElement> children = parent.findElements(By.tagName("div")); 
System.out.println("Size is: "+children.size());
//((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView(true);", children);
for(int i = 0;i<children.size();i++)
{
    System.out.println(i + " " + children.get(i).getText());
}
int indexErr = children.indexOf(errMsg);
System.out.println("index " + indexErr);
Assert.assertEquals(expected, children.get(indexErr).getText());

以上的解决方案都对我无效。


0

对我有用:

将字符串长度大于0作为xpath的谓词添加:

String text = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//span[string-length(text()) > 0]"))).getText();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接