如何在不包含子元素文本的情况下获取Selenium WebDriver中的元素文本(通过Python api)?

jos*_*osh 37 html python selenium selenium-webdriver

<div id="a">This is some
   <div id="b">text</div>
</div>
Run Code Online (Sandbox Code Playgroud)

获得"这是一些"并非易事.例如,这会返回"This is some text":

driver.find_element_by_id('a').text
Run Code Online (Sandbox Code Playgroud)

一般来说,如何在不包含其子项文本的情况下获取特定元素的文本?

(我在下面提供了一个答案,但是如果有人能提出一个不那么可怕的解决方案,那么问题会保持开放).

Lou*_*uis 26

这是一般解决方案:

def get_text_excluding_children(driver, element):
    return driver.execute_script("""
    return jQuery(arguments[0]).contents().filter(function() {
        return this.nodeType == Node.TEXT_NODE;
    }).text();
    """, element)
Run Code Online (Sandbox Code Playgroud)

传递给函数的元素可以是从find_element...()方法中获得的元素(即它可以是WebElement对象).

或者如果你没有jQuery或者不想使用它,你可以用以下代码替换上面函数的主体:

return self.driver.execute_script("""
var parent = arguments[0];
var child = parent.firstChild;
var ret = "";
while(child) {
    if (child.nodeType === Node.TEXT_NODE)
        ret += child.textContent;
    child = child.nextSibling;
}
return ret;
""", element) 
Run Code Online (Sandbox Code Playgroud)

我实际上是在测试套件中使用此代码.

  • @josh,我不同意这一点...... Seleniums方法是用来模拟用户POV的交互,而jQuery则不是.是的,您可以同时使用两者来抓取元素,但一般情况下,您需要执行javascript的情况相对较少. (2认同)

Deb*_*anB 6

在您共享的 HTML 中:

<div id="a">This is some
   <div id="b">text</div>
</div>
Run Code Online (Sandbox Code Playgroud)

文本This is some位于文本节点内。以结构化方式描述文本节点

<div id="a">
    This is some
   <div id="b">text</div>
</div>
Run Code Online (Sandbox Code Playgroud)

这个用例

要使用Selenium客户端This is some文本节点提取和打印文本,您有以下两种方法:

  • 使用splitlines():您可以识别父元素即<div id="a">,提取innerHTML然后使用splitlines()如下:

  • Using execute_script(): 也可以使用execute_script()可以在当前窗口/框架中同步执行JavaScript的方法如下:

    • 使用xpathfirstChild

      parent_element = driver.find_element_by_xpath("//div[@id='a']")
      print(driver.execute_script('return arguments[0].firstChild.textContent;', parent_element).strip())
      
      Run Code Online (Sandbox Code Playgroud)
    • 使用xpathchildNodes[n]

      parent_element = driver.find_element_by_xpath("//div[@id='a']")
      print(driver.execute_script('return arguments[0].childNodes[1].textContent;', parent_element).strip())
      
      Run Code Online (Sandbox Code Playgroud)


jos*_*osh 5

使用:

def get_true_text(tag):
    children = tag.find_elements_by_xpath('*')
    original_text = tag.text
    for child in children:
        original_text = original_text.replace(child.text, '', 1)
    return original_text
Run Code Online (Sandbox Code Playgroud)

  • 不过,这运行得慢得令人厌恶……必须有更好的方法吗? (3认同)