提问人:josh 提问时间:9/8/2012 最后编辑:Benjamin Loisonjosh 更新时间:6/22/2023 访问量:872290
如何在 Selenium WebDriver (Python) 中找到包含特定文本的元素?
How do I find an element that contains specific text in Selenium WebDriver (Python)?
问:
我正在尝试使用 Selenium 测试一个复杂的 JavaScript 接口(使用 Python 接口,并跨多个浏览器)。我有许多表格的按钮:
<div>My Button</div>
我希望能够根据“我的按钮”(或不区分大小写的部分匹配项,例如“我的按钮”或“按钮”)搜索按钮。
我发现这非常困难,以至于我觉得我错过了一些明显的东西。到目前为止,我拥有的最好的事情是:
driver.find_elements_by_xpath('//div[contains(text(), "' + text + '")]')
但是,这是区分大小写的。我尝试的另一件事是遍历页面上的所有 div,并检查 element.text 属性。但是,每次您遇到以下情况时:
<div class="outer"><div class="inner">My Button</div></div>
div.outer 也有“我的按钮”作为文本。为了解决这个问题,我试图查看div.outer是否是div.inner的父级,但我不知道该怎么做(element.get_element_by_xpath('..')返回元素的父级,但它测试不等于div.outer)。
此外,遍历页面上的所有元素似乎真的很慢,至少使用 Chrome 网络驱动程序是这样。
想法?
我在这里问(并回答)了一个更具体的版本:如何在 Selenium WebDriver 中获取元素的文本,而不包含子元素文本?
答:
您可以尝试如下所示的 XPath 表达式:
'//div[contains(text(), "{0}") and @class="inner"]'.format(text)
评论
.format
在我的日食中无法识别。它给出和错误。任何想法,为什么?
请尝试以下操作:
driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")
评论
find_element(s)_by_link_text
find_element(s)_by_partial_link_text
试试这个。这很简单:
driver.getPageSource().contains("text to search");
这在 Selenium WebDriver 中确实对我有用。
评论
您也可以将它与页面对象模式一起使用,例如:
请尝试以下代码:
@FindBy(xpath = "//*[contains(text(), 'Best Choice')]")
WebElement buttonBestChoice;
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(), 'YourTextHere')]")));
assertNotNull(driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")));
String yourButtonName = driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")).getAttribute("innerText");
assertTrue(yourButtonName.equalsIgnoreCase("YourTextHere"));
使用 driver.find_elements_by_xpath and matches 正则表达式匹配功能,通过其文本对元素进行不区分大小写的搜索。
driver.find_elements_by_xpath("//*[matches(.,'My Button', 'i')]")
评论
matches()
是 XPath 2.0 的功能,遗憾的是浏览器仅支持 1.0。
* 将查找任何 HTML 标签。如果某些文本对于 Button 和 div 标签是通用的,并且如果 //* 是类别,它将无法按预期工作。如果您需要选择任何特定的,那么您可以通过声明 HTML 元素标签来获取它。喜欢:
driver.find_element_by_xpath("//div[contains(text(),'Add User')]")
driver.find_element_by_xpath("//button[contains(text(),'Add User')]")
评论
有趣的是,几乎所有的答案都围绕着XPath的函数,忽略了它是区分大小写的事实 - 与OP的要求相反。contains()
如果你需要不区分大小写,这是可以在 XPath 1.0(当代浏览器支持的版本)中实现的,尽管它并不漂亮 - 通过使用 translate()
函数。它通过使用转换表将源字符替换为其所需的形式。
构造一个包含所有大写字符的表将有效地将节点的文本转换为其 lower() 形式 - 允许不区分大小写的匹配(这里只是特权):
[
contains(
translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
'my button'
)
]
# will match a source text like "mY bUTTon"
完整的 Python 调用:
driver.find_elements_by_xpath("//*[contains(translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZЙ', 'abcdefghijklmnopqrstuvwxyzй'), 'my button')]")
当然,这种方法有其缺点 - 如给定的那样,它仅适用于拉丁文本;如果要覆盖 Unicode 字符 - 则必须将它们添加到翻译表中。我已经在上面的示例中做到了这一点 - 最后一个字符是西里尔符号。"Й"
如果我们生活在一个浏览器支持 XPath 2.0 及更高版本(🤞但不会很快☹️发生)的世界里,我们可以使用函数 lower-case()(
但尚未完全感知区域设置)和匹配
(对于正则表达式搜索,带有不区分大小写的 () 标志)。'i'
类似问题:查找<button>Advanced...</button>
也许这会给你一些想法(请将概念从 Java 转移到 Python):
wait.until(ExpectedConditions.elementToBeClickable(//
driver.findElements(By.tagName("button")).stream().filter(i -> i.getText().equals("Advanced...")).findFirst().get())).click();
在您提供的 HTML 中:
<div>My Button</div>
文本是 并且周围没有空格,因此您可以轻松使用,如下所示:My Button
innerHTML
text()
my_element = driver.find_element_by_xpath("//div[text()='My Button']")
注意:
text()
选择上下文节点的所有文本节点子节点
带有前导/尾随空格的文本
如果相关文本在开头包含空格:
<div> My Button</div>
或最后:
<div>My Button </div>
或两端:
<div> My Button </div>
在这些情况下,您有两种选择:
您可以使用
contains()
函数来确定第一个参数字符串是否包含第二个参数字符串并返回布尔值 true 或 false,如下所示:my_element = driver.find_element_by_xpath("//div[contains(., 'My Button')]")
您可以使用
normalize-space()
函数,该函数从字符串中去除前导和尾随空格,将空格字符序列替换为单个空格,并返回生成的字符串,如下所示:driver.find_element_by_xpath("//div[normalize-space()='My Button']")
变量文本的 XPath 表达式
如果文本是变量,则可以使用:
foo= "foo_bar"
my_element = driver.find_element_by_xpath("//div[.='" + foo + "']")
评论
只需使用这个:
driver.find_elements_by_xpath('//*[text() = "My Button"]')
在 Selenium 中,4 已弃用。请参阅文档,https://selenium-python.readthedocs.io/locating-elements.htmlfind_element_by_xpath
这里有两个选项:
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
service = Service('D:\\Path\\to\\geckodriver.exe')
driver = webdriver.Firefox(service=service)
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//*[contains(text(), 'My Button')]")))
或
element = driver.find_element(By.XPATH, "//*[contains(text(), 'My Button')]")
包含的文本
若要查找文本(显示在 HTML 页面中)包含特定文本的元素,可以使用以下 XPath 表达式:
driver.find_element(By.XPATH, "//*[contains(text(), 'text_to_be_contained')]")
- '*',选择文档中的所有元素,而不考虑标签名称。如果要在特定标签类型中进行搜索,可以将星号 (*) 替换为特定标签名称。
- [contains(text(), 'text_to_be_contained')] 是检查文本是否包含指定文本 ('text_to_be_contained') 的条件。这将匹配其 text 属性包含指定文本的元素,即使它是较大文本值的一部分。
- “text_to_be_contained”,应该是您要查找的文本
包含的属性
若要查找属性包含特定文本的元素,可以使用以下 XPath 表达式:
//*[contains(@attribute_name, 'text_to_be_contained')]
- 将“attribute_name”替换为要在其中搜索的属性的实际名称,例如:class、name、href、value 或任何其他属性
文本/属性相等
若要查找文本或属性与特定文本完全匹配的元素,可以使用以下 XPath 表达式: 对于文本
正文:
//*[text()='exact_text']
对于属性:
//*[@attribute_name='exact_text']
- “exact_text”,应该是您要查找的文本
注意:所有方法均区分大小写
评论