【问题标题】:Selenium: Select all the elements on the page containing any textSelenium:选择页面上包含任何文本的所有元素
【发布时间】:2021-07-27 12:21:39
【问题描述】:

我想选择页面上包含任何文本的所有元素。
只有元素本身实际包含文本,而不是仅在其子元素中包含文本的父元素。
此 XPath 匹配包含任何非空文本的元素

//*[text() != ""]

不过这个

List<WebElement> list = driver.findElements(By.xpath("//*[text() != '']"));

给我一​​个包含文本本身或其子元素中的所有元素的列表。
我可以用类似这样的方法迭代这个list,以将实际包含文本的元素放入real列表中

List<WebElement> real = new ArrayList<>();
for(WebElement element : list){
    js = (JavascriptExecutor)driver;
    String text = js.executeScript("""
    return jQuery(arguments[0]).contents().filter(function() {
        return this.nodeType == Node.TEXT_NODE;
    }).text();
    """, element);
    if(text.length()>0){
        real.add(element);
}

但这是一种解决方法。
我想知道有没有办法让元素列表实际上包含任何直接或更优雅地执行此操作的文本?

【问题讨论】:

    标签: java selenium


    【解决方案1】:
        List<WebElement> elementsWithOwnText = new ArrayList<WebElement>();
        List<WebElement> allElements = driver.findElements(By.xpath("//*"));
        for (WebElement element: allElements) {
            List<WebElement> childElements = element.findElements(By.xpath(".//*"));
            String text = element.getText();
            if (childElements.size() == 0 && text.lenght() > 0) {
                elementsWithOwnText.add(element);
            }
        }
    

    注意org.openqa.selenium.StaleElementReferenceException。在循环 allElements 时,它们中的任何一个都可能不再附加到页面文档(动态内容 f.e.)。

    【讨论】:

    • 我不确定您的解决方案是否比我的更好。也许更糟。您正在获取整个页面上的所有元素,然后检查所有子元素,而我从仅包含文本的元素开始......
    • 唯一的区别是检查机制来验证元素本身是否包含文本。不是孩子。
    • 如果可能的话,我还要求直接获取所有这些元素。不适用于删除父元素的算法。
    • 对不起,您需要获取仅限父母或仅限儿童的文本吗?
    • 我想获取所有包含文本的元素。元素本身。只有实际包含文本的元素,而不是那些实际上仅在其子元素中包含文本的元素
    【解决方案2】:

    你可以试试这个: 它选择所有带有文本的叶子元素。

    List<WebElement> list = driver.findElements(By.xpath("//*[not(child::*) and text()]"));
            for (WebElement webElement : list)
                System.out.println(webElement.getText());
    

    【讨论】:

    • 看起来这就是我要找的。 XPath 本身,没有内部 for 循环。
    • 再想可能是错的。此 xpath 选择带有文本的叶元素,但您可以有一些带有实际文本的父元素。如果我没记错的话,您希望所有元素都带有实际文本。
    • 对....好吧,你能想到这样的解决方案吗?暂时离开验收,等待正确的解决方案。
    • 很抱歉,但它似乎无法撤消。我试过innertHTMLinnerTEXTouterHTMLouterTEXT....我尝试替换标签等...你也可能有一些像这样的html代码:&lt;p&gt;this is a &lt;em&gt; test &lt;/em&gt;&lt;/p&gt;&lt;h1&gt; this is &lt;br&gt; another&lt;/br&gt; example&lt;/h1&gt;你怎么决定什么是纯文本?我认为您应该获取文本并与它们一起工作。 Selenium 甚至不支持//text() xpath,因为它返回一个文本,而 Selenium 需要返回一个 WebElement...抱歉:(
    • 我明白了。这是完全可以预见的。我看到了类似的问题,但没有我要求的解决方案。所以我很抱歉,但我删除了接受。会在其他地方为你投票 :)
    【解决方案3】:

    在您找到所需的 xpath 之前,作为临时解决方案,我建议您也尝试以下迭代(尽管效率不如直接 xpath)。

    在我的例子中,用文本评估 700 个节点需要 1 分钟,并返回 152 个具有自己文本的元素:

    public static List<WebElement> getElementsWithText(WebDriver driver) {
        return driver.findElements(By.xpath("//*[normalize-space() != '']"))
                .stream().filter(element -> doesParentHaveText(element))
                .collect(Collectors.toList());
    }
    
    private static boolean doesParentHaveText(WebElement element) {
        try {
            String text = element.getText().trim();
            List<WebElement> children = element.findElements(By.xpath("./*"));
    
            for (WebElement child: children) {
                text = text.replace(child.getText(), "").trim();
            }
    
            return text.trim().replace("[\\n|\\t|\\r]", "").length() > 0;
        } catch (WebDriverException e) {
            return false; //in case something does wrong on reading text; you can change the return false with thrown error
        }
    }
    

    【讨论】:

    • 感谢您的回答。这仍然类似于我在问题中提到的内容以及回答 pburgr 的内容,但仍然感谢您提供额外的方法。
    【解决方案4】:

    这可能会有所帮助: source

    List<String> elements = driver.findElements(By.xpath("//a")).stream().map(productWebElement -> productWebElement.getText()).distinct().collect(Collectors.toList());
            
        // Print count of product found
        System.out.println("Total unique product found : " + elements.size());
            
        // Printing product names
        System.out.println("All product names are : ");
        elements.forEach(name -> System.out.println(name));
    

    【讨论】:

      猜你喜欢
      • 2021-10-03
      • 2012-05-18
      • 2010-11-15
      • 2023-03-22
      • 2019-03-27
      • 2013-11-15
      • 2019-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多