<div id="a">This is some
<div id="b">text</div>
</div>
获取“这是一些”并非易事。例如,这会返回“这是一些文字”:
driver.find_element_by_id('a').text
一般来说,如何获取特定元素的文本而不包含其子文本?
(我在下面提供了一个答案,但是如果有人能提出一个不那么可怕的解决方案,我会保留这个问题。)
答案 0 :(得分:20)
以下是一般解决方案:
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)
传递给函数的元素可以是从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)
我实际上是在测试套件中使用此代码。
答案 1 :(得分:5)
在您共享的HTML中:
<div id="a">This is some
<div id="b">text</div>
</div>
文本This is some
在text node中。以结构化方式描绘text node:
<div id="a">
This is some
<div id="b">text</div>
</div>
要使用Selenium的python客户端从文本节点提取并打印文本 This is some
,您有两种方法如下:
使用splitlines()
:您可以标识父元素,即<div id="a">
,提取innerHTML
,然后按如下所示使用splitlines()
:
使用 xpath :
print(driver.find_element_by_xpath("//div[@id='a']").get_attribute("innerHTML").splitlines()[0])
使用 xpath :
print(driver.find_element_by_css_selector("div#a").get_attribute("innerHTML").splitlines()[0])
使用execute_script()
:您也可以使用execute_script()
方法,该方法可以在当前窗口/帧中同步执行JavaScript,如下所示:
使用 xpath 和 firstChild :
parent_element = driver.find_element_by_xpath("//div[@id='a']")
print(driver.execute_script('return arguments[0].firstChild.textContent;', parent_element).strip())
使用 xpath 和 childNodes [n] :
parent_element = driver.find_element_by_xpath("//div[@id='a']")
print(driver.execute_script('return arguments[0].childNodes[1].textContent;', parent_element).strip())
答案 2 :(得分:4)
您不必进行替换,您可以获取子文本的长度并从总长度中减去该值,并切成原始文本。那应该快得多。
答案 3 :(得分:2)
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
答案 4 :(得分:1)
不幸的是,Selenium只能与Elements节点一起使用,不能与Text节点一起使用。
如果您尝试使用诸如get_element_by_xpath
之类的函数来定位文本节点,Selenium将抛出InvalidSelectorException
。
一种解决方法是使用Selenium捕获相关的HTML,然后使用HTML解析库(例如BeautifulSoup)来更优雅地处理文本节点。
import bs4
from bs4 import BeautifulSoup
inner_html = driver.find_elements_by_css_selector('#a')[0].get_attribute("innerHTML")
inner_soup = BeautifulSoup(inner_html, 'html.parser')
outer_html = driver.find_elements_by_css_selector('#a')[0].get_attribute("outerHTML")
outer_soup = BeautifulSoup(outer_html, 'html.parser')
从那里开始,有几种方法可以搜索文本内容。您必须进行试验,以了解哪种方法最适合您的用例。
这里有一个简单的单线可能就足够了:
inner_soup.find(text=True)
如果这不起作用,则可以使用.contents()遍历元素的子节点,并检查其对象类型。
BeautifulSoup具有four types of elements,而您感兴趣的是NavigableString类型,它是由Text节点产生的。相比之下,Elements的类型为Tag。
contents = inner_soup.contents
for bs4_object in contents:
if (type(bs4_object) == bs4.Tag):
print("This object is an Element.")
elif (type(bs4_object) == bs4.NavigableString):
print("This object is a Text node.")
请注意,BeautifulSoup不支持Xpath表达式。如果需要这些,则可以使用一些解决方法in this thread。