Selenium/Python Unable to use `:contains()` in CSS_SELECTOR [duplicate] - python

This question already has answers here:
selenium.common.exceptions.InvalidSelectorException with "span:contains('string')"
(2 answers)
Closed 1 year ago.
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.

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:
Alter your selector to be class or ID based (easiest)
Create a Selenium utility to run a JS script that uses this jQuery selector; e.g. execute_script("jQuery(" + id + ":contains('" + text + "')", id, text)

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

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

How do I click on an item on my google search page with Selenium Python?

Good time of the day!
Faced with a seemingly simple problem,
But it’s been a while, and I’m asking for your help.
I work with Selenium on Python and I need to curse about
20 items on google search page by random request.
And I’ll give you an example of the elements below, and the bottom line is, once the elements are revealed,
Google generates new such elements
Problem:
Cannot click on the element. I will need to click on existing and then on new, generated elements in this block: click for open see blocks with element
Tried to click on xpath, having collected all the elements:
xpath = '//*[#id="qmCCY_adG4Sj3QP025p4__16"]/div/div/div[1]/div[4]'
all_elements = driver.find_element(By.XPATH, value=xpath)
for element in all_elements:
element.click()
sleep(2)
Important note!
id xpath has constantly changing and is generated by another on the google side
Tried to click on the class
class="r21Kzd"
Tried to click on the selector:
#qmCCY_adG4Sj3QP025p4__16 > div > div > div > div.wWOJcd > div.r21Kzd
Errors
This is when I try to click using xpath:
Message: no such element: Unable to locate element: {"method":"xpath","selector"://*[#id="vU-CY7u3C8PIrgTuuJH4CQ_9"]/div/div[1]/div[4]}
In other cases, the story is almost the same, the driver does not find the element and cannot click on it. Below I apply a scratch tag on which I need to click
screenshot tags on google search
Thanks for the help!
In case iDjcJe IX9Lgd wwB5gf are a fixed class name values of that element all you need is to use CSS_SELECTOR instead of CLASS_NAME with a correct syntax of CSS Selectors.
So, instead of driver.find_element(By.CLASS_NAME, "iDjcJe IX9Lgd wwB5gf") try using this:
driver.find_element(By.CSS_SELECTOR, ".iDjcJe.IX9Lgd.wwB5gf")
(dots before each class name, no spaces between them)

Change css element style with Python Selenium

I want to change the css element style using Python Selenium while doing automation to increase the height of the page. The html of the element is as follows:
<div style="overflow-y:scroll;overflow-x:hidden;height:150px;">
I know that I can use something like the code below to do this:
driver.execute_script("document.getElementById('id name').style.height = '2000px';")
or
driver.execute_script("document.getElementByClassName('class name').style.height = '2000px';")
But there is no id or class in the HTML (there's only style).
If no ID or class is present then please use CSS
driver.execute_script("document.getElementByCss('div[style='overflow-y:scroll']').style.height = '2000px';")
But you should check in HTML DOM for the mentioned CSS :
Please check in the dev tools (Google chrome) if we have unique entry in HTML DOM or not.
Steps to check:
Press F12 in Chrome -> go to element section -> do a CTRL + F -> then paste the CSS and see, if your desired element is getting highlighted with 1/1 matching node.
CSS you should check :
div[style='overflow-y:scroll']
or
div[style='overflow-y:scroll'][sytle$='height:150px;']
or
div[style='overflow-y:scroll;overflow-x:hidden;height:150px;']
Whichever has the unique entry put that in execute_script and you should be good to go after that.
Alternate way to do
element = driver.find_element_by_css_selector("div[style='overflow-y:scroll;overflow-x:hidden;height:150px;']")
driver.execute_script("arguments[0].setAttribute('style','overflow-y:scroll;overflow-x:hidden;height:2000px;')", element)

How to Handle Changing IDs In XPath? for example : [duplicate]

I'm using selenium with python,now I want to locate an element by part of its id name,what can I do?
For example,now I've already located a item by id name coption5 :
sixth_item = driver.find_element_by_id("coption5")
Is there anyway I can locate this element only by using coption?
To find the element which you have located with:
sixth_item = driver.find_element_by_id("coption5")
To locate this element only by using coption you can use can use either of the following Locator Strategies:
Using XPATH and starts-with():
sixth_item = driver.find_element_by_xpath("//*[starts-with(#id, 'coption')]")
Using XPATH and contains():
sixth_item = driver.find_element_by_xpath("//*[contains(#id, 'coption')]")
Using CSS_SELECTOR and ^ (wildcard of starts-with):
sixth_item = driver.find_element_by_css_selector("[id^='coption']")
Using CSS_SELECTOR and * (wildcard of contains):
sixth_item = driver.find_element_by_css_selector("[id*='coption']")
Reference
You can find a detailed discussion on dynamic CssSelectors in:
How to get selectors with dynamic part inside using Selenium with Python?
Java Selenium webdriver expression finding dynamic element by ccs that starts with and ends with
How to click a dynamic link with in a drupal 8 website using xpath/css selector while automating through Selenium and Python
Finding elements by CSS selector with ChromeDriver (Selenium) in Python

How to find element by part of its id name in selenium with python

I'm using selenium with python,now I want to locate an element by part of its id name,what can I do?
For example,now I've already located a item by id name coption5 :
sixth_item = driver.find_element_by_id("coption5")
Is there anyway I can locate this element only by using coption?
To find the element which you have located with:
sixth_item = driver.find_element_by_id("coption5")
To locate this element only by using coption you can use can use either of the following Locator Strategies:
Using XPATH and starts-with():
sixth_item = driver.find_element_by_xpath("//*[starts-with(#id, 'coption')]")
Using XPATH and contains():
sixth_item = driver.find_element_by_xpath("//*[contains(#id, 'coption')]")
Using CSS_SELECTOR and ^ (wildcard of starts-with):
sixth_item = driver.find_element_by_css_selector("[id^='coption']")
Using CSS_SELECTOR and * (wildcard of contains):
sixth_item = driver.find_element_by_css_selector("[id*='coption']")
Reference
You can find a detailed discussion on dynamic CssSelectors in:
How to get selectors with dynamic part inside using Selenium with Python?
Java Selenium webdriver expression finding dynamic element by ccs that starts with and ends with
How to click a dynamic link with in a drupal 8 website using xpath/css selector while automating through Selenium and Python
Finding elements by CSS selector with ChromeDriver (Selenium) in Python

How do I click a button using Selenium in Python?

I'm trying to crawl review data on an app from a Google Play website page using Python and Selenium. What I'm trying to do here is to click the "Full Review" button to see the entire text of each review.
But I keep running into these errors each time:
ElementNotInteractableException: Message: element not interactable
or
AttributeError: 'list' object has no attribute 'click'
or
NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".LkLjZd ScJHi OzU4dc "}
The element for the button is this:
<button class="LkLjZd ScJHi OzU4dc " jsaction="click:TiglPc" jsname="gxjVle">Full Review</button>
The xpath for the button is this:
//*[#id="fcxH9b"]/div[4]/c-wiz/div/div[2]/div/div[1]/div/div/div[1]/div[2]/div/div[26]/div/div[2]/div[2]/span[1]/div/button
And this is the code I'm using for xpath:
full_review = driver.find_elements_by_xpath('//*[#id="fcxH9b"]/div[4]/c-wiz/div/div[2]/div/div[1]/div/div/div[1]/div[2]/div/div[26]/div/div[2]/div[2]/span[1]/div/button')
full_review.click()
I can't find the button by class name, xpath or anything.
Could anyone help me figure out this problem? In addition, is it possible to find the element by jsname?
I would really appreciate if you could help.
Avoid using xpath whenever possible, it's the most brittle selector.
id > CSS > Xpath
For your button, this css selector should work:
button[jsname='gxjVle']
You'll probably need to specify the child as that probably won't be unique
Your XPath selector is a little bit flaky, you can simplify it to be something like:
//button[text()='Full Review']
You're using the wrong function, if you're looking for a single unique element you should be using WebDriver.find_element_by_xpath one, mind that element, not elements
It's better to use Explicit Wait just in case element is not immediately available in DOM (for example if you're testing application built using AJAX technology)
Assuming all above:
full_review = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Full Review']")))

Categories

Resources