考虑:
<div id="a">This is some
<div id="b">text</div>
</div>
获得“这是一些”是很重要的。 例如,这会返回“这是一些文本”:
driver.find_element_by_id('a').text
如何以一般方式获取特定元素的文本而不包含其子元素的文本?
这是一个通用解决方案:
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)
我实际上在测试套件中使用此代码。
在您共享的 HTML 中:
<div id="a">This is some
<div id="b">text</div>
</div>
文本
This is some
位于文本节点内。以结构化方式描述文本节点:
<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])
使用css_selector:
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())
用途:
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
您无需更换。您可以获取子文本的长度,从总长度中减去该长度,然后切片到原始文本中。 这应该会快得多。
不幸的是,Selenium 仅适用于 Elements,而不是 Text 节点。
如果您尝试使用像
get_element_by_xpath
这样的函数来定位文本节点,Selenium 将抛出 InvalidSelectorException
。
一种解决方法是使用 Selenium 获取相关 HTML,然后使用像 Beautiful Soup 这样可以更优雅地处理文本节点的 HTML 解析库。
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() 循环遍历元素的子节点并检查它们的对象类型。
Beautiful Soup 有四种类型的元素,您感兴趣的是 NavigableString 类型,它是由文本节点生成的。相比之下,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.")
请注意,Beautiful Soup 不支持 XPath 表达式。如果您需要这些,那么您可以使用一些解决方法在此问题中。