如何在Selenium Webdriver(Python)中找到包含特定文本的元素?


259

我正在尝试使用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)获取元素的文本而不包含子元素文本?


当前的答案对我不起作用。这个做了:sqa.stackexchange.com/a/2486
alejandro

Answers:


328

尝试以下方法:

driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")

3
感谢您的答复,这是我需要的50%(让我开始)。我到达的形式是“(// * [contains(text(),'“ + text +”')] | // * [@ value ='“ + text +”'))“,它将搜索给定的文本不仅在元素节点内部,而且在通过'value'属性(即<button value =“ My Button” />)设置了文本的输入元素内部。尽管要注意,该值必须严格匹配,而不仅仅是包含文本。
伊万·科谢列夫

9
另外值得一提的其他搜索引擎的用户:如果你正在寻找一个链接,也有find_element(s)_by_link_textfind_element(s)_by_partial_link_text方法
丹Passaro

3
如果文本是动态的怎么办?也就是说,可能包含引号。那不会破坏这个解决方案吗?
IcedD​​ante 2015年

3
搜索某些名称似乎可以解决这个问题。以以下示例为例:“ // * [contains(text(),'” + username +“'))]”如果username =“ O'Reilly”; 那么xpath将变为无效。有没有解决的办法?
坂本一沼2016年

当目标文本有多行时,它似乎不起作用。
肖恩

29

您可以尝试使用xpath:

'//div[contains(text(), "{0}") and @class="inner"]'.format(text)

谢谢...这样可以帮助区分内部和外部,但是实际上可以与xpath一起使用,我只是在遍历所有div时遇到了这个问题。我的xpath问题是我不知道如何使其不区分大小写?
josh 2012年

2
xpath 2.0具有小写功能,因此应该可以使用:'// div [contains(lower-case(text()),“ {0}”))'。format(text)
andrean

谢谢!虽然,我的理解是主要浏览器均不支持xpath 2.0 ...
josh 2012年

selenium使用浏览器自己的方法直接评估xpath表达式,因此它取决于您使用哪个浏览器使用selenium。通常只有6,7和8不应该支持xpath 2.0。
andrean 2012年

.format在日食中不被认可。它给与错误。任何想法,为什么?
2013年

16

您还可以将其与“页面对象模式”一起使用,例如:

试试这个代码:

@FindBy(xpath = "//*[contains(text(), 'Best Choice')]")
WebElement buttonBestChoice;

13

// *将寻找任何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')]")

5

有趣的是,几乎所有答案都围绕着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及以上的浏览器世界(🤞,但不会很快☹️发生的任何时间),我们可以有使用的功能lower-case()(但不完全区域识别),以及matches(对于正则表达式搜索,以案例-insensitive('i')标志)。


3

在您提供的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 + "']")

1
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"));

1

类似的问题:查找 <button>Advanced...</button>

也许这会给您一些想法(请将概念从Java转移到Python):

wait.until(ExpectedConditions.elementToBeClickable(//
    driver.findElements(By.tagName("button")).stream().filter(i -> i.getText().equals("Advanced...")).findFirst().get())).click();


-19

试试这个。非常简单:

driver.getPageSource().contains("text to search");

这对于硒网络驱动程序确实很有效。


9
如果文本是由JavaScript生成的,则无法使用。
palacsint 2014年

2
这是一种非常好的检查方法,因为您正在通过导线传输页面的全部内容。对于很小的页面,这是可以接受的,但是对于很大的页面,您正在传输文件的所有内容并在服务器端进行检查。更好的方法是使用xpath,javascript或css在客户端执行此操作。
thomas.han 2014年

我认为整个页面源已经需要通过导线传输,以便浏览器呈现它?
勒内·

3
Josh询问如何通过文本查找元素,而不是测试文本是否存在于页面源中。
塞德里克

1
对于仅需要在页面上找到静态文本的情况,此解决方案就足够了。(这对我来说很有帮助)。
2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.