Home > other >  Selenium/Python Unable to use `:contains()` in CSS_SELECTOR
Selenium/Python Unable to use `:contains()` in CSS_SELECTOR

Time:11-07

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.

CodePudding user response:

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)

CodePudding user response:

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'))]

CodePudding user response:

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.

  • Related