0

When I try to use :contains in Selenium's By.CSS_SELECTOR, such as

presence = EC.presence_of_element_located((By.CSS_SELECTOR, ".btn:contains('Continue Shopping')"))

or

presence = EC.presence_of_element_located((By.CSS_SELECTOR, ".btn\:contains('Continue Shopping')"))

or

presence = EC.presence_of_element_located((By.CSS_SELECTOR, ".btn\\:contains('Continue Shopping')"))

the Python program crashes with the error

Exception: Message: invalid selector: An invalid or illegal selector was specified
  (Session info: chrome=95.0.4638.54)

Is it possible to use :contains in Selenium? The CSS selector

$('.btn:contains("Continue Shopping")')

works fine in Chrome's JS console.

Using Chrome 95.0.4638.54, ChromeDriver 95.0.4638.54, Python 3.10 on Ubuntu 20.04.

Athena Wisdom
  • 6,101
  • 9
  • 36
  • 60

3 Answers3

3

The selector :contains('text') is a jQuery selector, not a valid CSS selector like Selenium is expecting. I'm assuming the reason it works on the page via Chrome's DevTools console is because the page has jQuery defined on it.

Unfortunately, I do not believe you can directly select an element via its text using a CSS selector (link).

You have two options as far as I can see:

  1. Alter your selector to be class or ID based (easiest)
  2. Create a Selenium utility to run a JS script that uses this jQuery selector; e.g. execute_script("jQuery(" + id + ":contains('" + text + "')", id, text)
aspok
  • 285
  • 3
  • 10
  • Oh... is it possible convert `'.btn:contains("Continue Shopping")'` into an XPath selector? I can't seem to figure it out. If so, we can use `By.XPATH` in Selenium. – Athena Wisdom Nov 06 '21 at 15:51
1

As mentioned by Aspok your CSS locators are not a valid CSS locators.
To locate element based on it text you can use XPath locator, something like:

//*[contains(@class,'btn') and(contains(text(),'Continue Shopping'))]

In case btn is the only class name attribute of that element your XPath can be

//*[@class='btn' and(contains(text(),'Continue Shopping'))]
Prophet
  • 32,350
  • 22
  • 54
  • 79
0

As explained by @aspok, it is not a valid css selector.

In case you would like to have XPath for the same, and .btn is class and have text/partial text

Continue Shopping 

You can try the below XPath :

//*[contains(text(),'Continue Shopping')]

or

//*[contains(text(), 'Continue Shopping') and contains(@class, 'btn')]

Please check in the dev tools (Google chrome) if we have unique entry in HTML DOM or not.

xpath that you should check :

//*[contains(text(), 'Continue Shopping') and contains(@class, 'btn')]

Steps to check:

Press F12 in Chrome -> go to element section -> do a CTRL + F -> then paste the xpath and see, if your desired element is getting highlighted with 1/1 matching node.

Also, Just letting you know that, //* can be replaced by tag name, if you found multiple matching nodes.

cruisepandey
  • 28,520
  • 6
  • 20
  • 38