-1

I am currently dabbling in Python in combination with Selenium. I can't get any further at one point.

Enclosed you can see three screenshots. At https://www.easycredit.de I already click on the button (1). After that I get to the next page. I would like to click this button (2) now. In Screenshot 3 you can see the location in the source code.

# link to Chromedriver
browser = webdriver.Chrome('/usr/local/bin/chromedriver')

button = browser.find_element(By.CLASS_NAME, 'econ-button btn  btn-primary')
button.click()

The error:

NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":".econ-button btn  btn-primary"}
  (Session info: chrome=104.0.5112.79)

Here are my questions:

  1. hy does it not work with this code?
  2. How do you find out with which procedure it works best in a case like this?
  3. How do you choose whether to identify an element by XPATH, ID etc.?

Screenshot 1 Screenshot 2 Screenshot 3

Thanks

Prophet
  • 32,350
  • 22
  • 54
  • 79
edstrinova
  • 101
  • 1
  • 7
  • Your website contains `shadow DOM` or also called as `shadow root`, which could not be located with regular selenium ways. You need to first open the `shadow root` and then access the elements. Here is a thread that could guide you in shadow roots. https://stackoverflow.com/questions/36141681/does-anybody-know-how-to-identify-shadow-dom-web-elements-using-selenium-webdriv – Anand Gautam Aug 16 '22 at 15:05

2 Answers2

2

econ-button btn btn-primary are actually 3 class names.
By.CLASS_NAME gets only single class name parameter.
To work with locators containing multiple class names you can use By.XPATH or By.CSS_SELECTOR.
As for me both the above methods are good, each of them having several cons and pros.
So, here you can use

browser.find_element(By.CSS_SELECTOR, 'button.econ-button.btn.btn-primary')

Or

browser.find_element(By.XPATH, "//button[@class='econ-button btn  btn-primary']")

Generally, you can use By.CSS_SELECTOR or By.XPATH. No need to utilize By.ID or By.CLASS_NAME since they are actually internally immediately translated to By.CSS_SELECTOR or By.XPATH :)
Some people preferring to use By.CSS_SELECTOR while others prefer By.XPATH.
As I mentioned previously, each of the above 2 methods having cons and pros.
For example you can locate elements by their texts with XPath only. XPath supports locating parent element based on their child nodes.
On the other hand XPath will not work so good on Firefox driver while it works perfectly on Chrome driver etc.
UPD The locator for the second nein radio button can be:

"//label[.//input[@data-econ-property='kreditdaten-beduerfnisfragen-flexibilitaetGewuenscht'][@value='radio3']]"  

So, Selenium click can be done with

browser.find_element(By.XPATH, "//label[.//input[@data-econ-property='kreditdaten-beduerfnisfragen-flexibilitaetGewuenscht'][@value='radio3']]").click()

And so on with other buttons

Prophet
  • 32,350
  • 22
  • 54
  • 79
  • This is working. Thank you! Can you please check the website again and give me a hint how to click the radio buttons? In the code there is a "::before" and the element ist called "" – edstrinova Aug 17 '22 at 17:29
  • 1
    I can help you with this too, no problem. But It would be better if you accept the answer here and open a new question for this issue since this is actually a new question. Also, I can't currently understand what radio button are you asking about, there are several radio buttons there, so to give unique locator / solution i need more information. – Prophet Aug 17 '22 at 18:02
  • Just the first radio button is activated from beginning. All others are not selected and I want to select all of them with "nein". – edstrinova Aug 17 '22 at 18:06
  • 1
    OK, I have added the second radio button locator / click command. You need to learn how to find effective locators. There are a lot of tutorials for that – Prophet Aug 17 '22 at 18:19
0

The element Zu den finanziellen Angaben is a dynamic element. So to click element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following locator strategies:

  • Using CSS_SELECTOR:

    WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.econ-button.btn.btn-primary[value='Zu den finanziellen Angaben']"))).click()
    
  • Using XPATH:

    WebDriverWait(browser, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[@class='econ-button btn  btn-primary' and @value='Zu den finanziellen Angaben']"))).click()
    
  • Note: You have to add the following imports :

    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Thank you. I will try this but the code from Prophet is also working and a bit more easy. Why do you think the way with WebDriverWait is better? – edstrinova Aug 17 '22 at 17:31
  • @edstrinova using `WebDriverWait` is needed in most cases since after many actions it takes some time to elements to be loaded, rearranged and fully rendered before you will be able to click them. – Prophet Aug 17 '22 at 18:04