如何在python selenium中按类名及其文本定位元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26370554/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:24:55  来源:igfitidea点击:

How to locate an element by class name and its text in python selenium

pythonselenium

提问by Nro

Hi I am trying to locate an element by its class name and the text that it contains

嗨,我正在尝试通过元素的类名和它包含的文本来定位元素

<div class="fc-day-number">15</div>

there are a bunch of fc-day-numberon the page with different values, I need the one with for example 15.

fc-day-number页面上有一堆不同的值,我需要一个,例如 15。

I do

我愿意

driver.find_element_by_class_name("fc-day-content") 

but I also need it to be equal to 15 and I am stuck here, please help.

但我也需要它等于 15 并且我被困在这里,请帮忙。

采纳答案by Richard

You can use xpath:

您可以使用 xpath:

driver.find_element_by_xpath("//div[@class='fc-day-content' and text()='15']")

回答by TehTris

 fc_day_contents = driver.find_elements_by_class_name("fc-day-content")
 the_one_you_want = [x for x in fc_day_contents if "15" == x.text][0]

first line puts all elements with class name "fc-day-content" in a list ( also notice how its elementSSSSSSSSS with an S, this returns a list of all elements by_class_name, by_name, by_id or wahtever)

第一行将所有类名为“fc-day-content”的元素放在一个列表中(还要注意它的 elementSSSSSSSS 是如何带 S 的,这将返回所有元素的列表 by_class_name、by_name、by_id 或 wahtever)

second line, goes through each element and looks to see if it has the text "15" as its text, and returns it as a (probably smaller) list

第二行,遍历每个元素并查看它是否将文本“15”作为其文本,并将其作为(可能较小的)列表返回

the [0] at the end of it, returns the first item in the list (you can remove it, if you want a list of all the ones that are "15" )

[0] 在它的末尾,返回列表中的第一项(你可以删除它,如果你想要一个包含所有 "15" 的列表)

回答by Louis

For things like this, prefer to use JavaScript:

对于这样的事情,更喜欢使用 JavaScript:

els = driver.execute_script("""
return Array.prototype.slice.call(document.getElementsByClassName("fc-day-content"))
    .filter(function (x) { return x.textContent === "15"; });
""")
assert len(els) == 1
el = els[0]

What this does is get all elements that have the class fc-day-contentas the class. (By the way, your question uses fc-day-contentand fc-day-number. Unclear which one you're really looking for but it does not matter in the grand scheme of things.) The call to Array.prototype.slicecreates an array from the return value of getElementsByClassNamebecause this method returns an HTMLCollectionand thus filteris not available on it. Once we have the array, run a filterto narrow it to the elements that have 15for text. This array of elements is returned by the JavaScript code. The assert is to make sure we don't unwittingly get more than one element, which would be a surprise. And then the element is extracted from the list.

这样做是获取所有具有该类的元素fc-day-content作为类。(顺便说一句,您的问题使用fc-day-contentand fc-day-number。不清楚您真正要寻找的是哪个,但在总体方案中无关紧要。) 调用Array.prototype.slice从 of 的返回值创建一个数组,getElementsByClassName因为此方法返回一个HTMLCollection,因此filter不可用。一旦我们有了数组,运行 afilter将它缩小到具有15文本的元素。这个元素数组由 JavaScript 代码返回。断言是为了确保我们不会在不知不觉中获得多个元素,这将是一个惊喜。然后从列表中提取元素。

(If you care about IE compatibility, textContentis not available before IE 9. If you need support for IE 8 or earlier, you might be able to get by with innerTextor innerHTMLor you could check that the element holds a single text node with value 15.)

(如果您关心 IE 兼容性,textContent在 IE 9 之前不可用。如果您需要对 IE 8 或更早版本的支持,您可以使用innerTextinnerHTML或者您可以检查该元素是否包含一个值为 的单个文本节点15。)

I prefer not to do it like TehTris does (find_elements_by_class_nameplus a Python loop to find the one with the text) because that method takes 1 round-trip between Selenium client and Selenium server to get all the elements of class fc-day-contentplus1 round-trip perelement that was found. So if you have 15 elements on your page with the class fc-day-content, that's 16 round-trips. If you run a test through Browser Stack or Sauce Labs, that's going to slow things down considerably.

我不喜欢像 TehTris 那样做(find_elements_by_class_name加上一个 Python 循环来查找文本中的那个),因为该方法需要在 Selenium 客户端和 Selenium 服务器之间进行 1 次往返以获取类的所有元素fc-day-content加上每个元素1 次往返那个被发现了。因此,如果您的页面上有 15 个带有 class 的元素fc-day-content,那就是 16 次往返。如果您通过浏览器堆栈或 Sauce Labs 运行测试,这将大大减慢速度。

And I prefer to avoid an XPath expression with @class='fc-day-content'because as soon as you add a new class to your element, this expression breaks. Maybe the element you care about has just one CSS class nowbut applications change. You could use XPath's contains()function but then you run into other complications, and once you take care of everything, it becomes a bit unwieldy. See this answerfor how to use it robustly.

我更喜欢避免使用 XPath 表达式,@class='fc-day-content'因为只要向元素添加新类,该表达式就会中断。也许您关心的元素现在只有一个 CSS 类,但应用程序发生了变化。您可以使用 XPath 的contains()功能,但随后会遇到其他复杂情况,一旦您处理完所有事情,它就会变得有点笨拙。请参阅此答案以了解如何稳健地使用它。