1

Hi I can't figure out how to get an element by CSS and matching with text. I know it can be done with Xpath but I'd rather use CSS.

<div class="button-face">
  <div class="button-face-caption"> Text I want to find 1</div>
</div>
<div class="button-face">
  <div class="button-face-caption"> Text I want to find 2</div>
</div>

So in by CSS would be something like...

driver.find_element_by_css('div.button-face-caption')

But how can add the text matching to that? i tried with contains and innerText and none seem to work.

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
trickymuffin
  • 143
  • 2
  • 7

3 Answers3

1

As you said it's supported in xpath:

This would be a solution with an xpath using contains and text()

driver.find_element_by_xpath('//div[@class="button-face-caption" and contains(text(),"Text I want to find")]')

The xpath being:

//div[@class="button-face-caption" and contains(text(),"Text I want to find")]

For css, look here: https://sqa.stackexchange.com/q/362/34209 which should allow us to use:

div:contains('Text I want to find')

Which would lead us to

driver.find_element_by_css("div:contains('Text I want to find')")

However this comes with a BIG caveat:

:contains() is not part of the current CSS3 specification so it will not work on all browsers, only ones that implemented it before it was pulled. (see w3.org/TR/css3-selectors)

DMart
  • 2,401
  • 1
  • 14
  • 19
  • ```driver.find_element_by_css_selector("div:contains('No, I need to create an account')").click() InvalidSelectorException: Message: An invalid or illegal selector was specified ``` :( – trickymuffin Jan 14 '21 at 22:21
  • which browser? As I stated, it's not actually valid CSS. I would just use xpath. – DMart Jan 15 '21 at 03:56
0

As workaround you can create your own function

def find_by_css(selector, text=''):
    return [element for element in driver.find_elements_by_css_selector(selector) if text in element.text][0]

Then you can call it as

find_by_css('div.button-face-caption')  # search only by CSS-selector

or

find_by_css('div.button-face-caption', 'Text I want to find 2')  # search by CSS + text
JaSON
  • 4,843
  • 2
  • 8
  • 15
0

As per the following discussions:

The :contains pseudo-class isn't in the CSS Spec and is not supported by either Firefox or Chrome (even outside WebDriver).


Solution

You need to consider the ancestor of the <div class="button-face"> element and traverse down. Let us assume that both the <div class="button-face"> are with in a parent <div class="class">:

<div class="class">
    <div class="button-face">
      <div class="button-face-caption"> Text I want to find 1</div>
    </div>
    <div class="button-face">
      <div class="button-face-caption"> Text I want to find 2</>
    </div>
</div>

So to identify the element with text as:

  • Text I want to find 1:

    div.class div:first-child > div.button-face-caption
    
  • Text I want to find 2:

    div.class div:nth-child(2) > div.button-face-caption
    

References

You can find a couple of relevant detailed discussions in:

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352