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

2024-06-05 19:29:42 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

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

我知道

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

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


Tags: 定位div元素示例numberbydriver页面
3条回答
 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]

第一行将类名为“fc day content”的所有元素放入一个列表中(还要注意它的elementsssssss如何带有S,这将按类名、按名称、按id或wahtever返回所有元素的列表)

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

结尾的[0]返回列表中的第一个项(如果您想要一个包含“15”的所有项的列表,则可以将其删除)

可以使用xpath:

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

对于这种情况,更喜欢使用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]

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

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

我不喜欢像TehTris那样做(find_elements_by_class_name加上Python循环来查找带有文本的元素),因为该方法需要在Selenium客户机和Selenium服务器之间进行一次往返,以获取找到的每个元素的类fc-day-contentplus1次往返。因此,如果页面上有15个元素与类fc-day-content在一起,那就是16次往返。如果你通过浏览器堆栈或Sauce实验室运行测试,那将大大降低速度。

我更喜欢避免使用@class='fc-day-content'的XPath表达式,因为只要向元素添加一个新类,这个表达式就会中断。也许您关心的元素现在只有一个CSS类,但是应用程序会改变。您可以使用XPath的contains()函数,但随后会遇到其他复杂问题,一旦您处理好所有事情,它就会变得有点笨拙。请参阅this answer了解如何可靠地使用它。

相关问题 更多 >