问题:如何在Selenium Webdriver(Python)中找到包含特定文本的元素?
我正在尝试使用Selenium(使用Python接口并在多个浏览器上)测试复杂的javascript接口。我有许多形式的按钮:
<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中(通过Python api)获取元素的文本而不包含子元素文本?
回答 0
尝试以下方法:
driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")
回答 1
您可以尝试使用xpath:
'//div[contains(text(), "{0}") and @class="inner"]'.format(text)
回答 2
您还可以将其与“页面对象模式”一起使用,例如:
试试这个代码:
@FindBy(xpath = "//*[contains(text(), 'Best Choice')]")
WebElement buttonBestChoice;
回答 3
// *将寻找任何HTML标记。如果某些文本对于Button和div标签是公用的,并且// *是类别,则将无法按预期工作。如果需要选择任何特定内容,则可以通过声明HTML Element标签来获取。喜欢:
driver.find_element_by_xpath("//div[contains(text(),'Add User')]")
driver.find_element_by_xpath("//button[contains(text(),'Add User')]")
回答 4
有趣的是,几乎所有答案都围绕着xpath的功能contains()
,而忽略了它区分大小写的事实-与OP的要求相反。
如果您需要不区分大小写,则可以在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及以上的浏览器世界(🤞,但不会很快☹️发生的任何时间),我们可以有使用的功能'i'
)标志)。
回答 5
在您提供的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>
在这些情况下,您有2个选择:
您可以使用
contains()
确定第一个参数字符串是否包含第二个参数字符串并返回boolean 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 + "']")
回答 6
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"));
回答 7
类似的问题:查找 <button>Advanced...</button>
也许这会给您一些想法(请将概念从Java转移到Python):
wait.until(ExpectedConditions.elementToBeClickable(//
driver.findElements(By.tagName("button")).stream().filter(i -> i.getText().equals("Advanced...")).findFirst().get())).click();
回答 8
使用driver.find_elements_by_xpath并匹配正则表达式匹配函数,以按元素的文本区分大小写。
driver.find_elements_by_xpath("//*[matches(.,'My Button', 'i')]")
回答 9
试试这个。非常简单:
driver.getPageSource().contains("text to search");
这对于硒网络驱动程序确实很有效。