3

An "Agree with the terms" button appears on https://www.sreality.cz/hledani/prodej/domy I am trying to go through that with a .click() using Selenium and Python. The button element is:

<button data-testid="button-agree" type="button" class="scmp-btn scmp-btn--default w-button--footer sm:scmp-ml-sm md:scmp-ml-md lg:scmp-ml-dialog">Souhlasím</button>

My approach is:

driver = webdriver.Chrome()
driver.implicitly_wait(20)

driver.get("https://www.sreality.cz/hledani/prodej/domy")

button = driver.find_element_by_css_selector("button[data-testid='button-agree']")
button.click()

Any idea what to change to make it work? Thanks! :)

Mr.Slow
  • 490
  • 1
  • 1
  • 16
  • 2
    you can not access it as it is not on the page source, but inside the #shadow-root (closed). https://stackoverflow.com/questions/71282237/how-to-click-button-inside-shadow-root-closed-using-selenium-and-python – Ajeet Verma Apr 12 '23 at 07:58
  • There must be a way.. Possibly using a PyShadow? – Mr.Slow Apr 14 '23 at 21:32

2 Answers2

3

Check the below working workaround solution:

driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("https://www.sreality.cz/hledani/prodej/domy")
driver.maximize_window()

# Below line creates instance of ActionChains class 
action = ActionChains(driver)
# Below line locates and stores an element which is outside the shadow-root
element_outside_shadow = driver.find_element(By.XPATH, "//div[@class='szn-cmp-dialog-container']")
# Below 2 lines clicks on the browser at an offset of co-ordinates x=5 and y=5
action.move_to_element_with_offset(element_outside_shadow, 5, 5)
action.click()
# Below 2 lines presses TAB key 9 times so that pointer moves to "Souhlasím" button and presses ENTER key once
action.send_keys(Keys.TAB * 9).perform()
action.send_keys(Keys.ENTER).perform()

Imports required:

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

NOTE:

  1. This is a workaround solution, as there is no direct selenium solution to handle it.
Shawn
  • 4,064
  • 2
  • 11
  • 23
  • Thanks, I will try. I also found out that workpin solutions could be: to locate and access a closest parent element and the perform an action with Tab button. – Mr.Slow Apr 19 '23 at 12:32
  • 2
    This solution worked perfectly. Thanks for posting. Definitely worth an upvote. – Life is complex Apr 19 '23 at 12:48
  • 1
    @Mr.Slow. There are some videos on [SelectorsHub's YouTube](https://www.youtube.com/@SelectorsHub) channel on dealing with shadow root elements. – Life is complex Apr 19 '23 at 12:52
  • @Mr.Slow - Yes, locating the element just outside `#shadow-root(closed)` and clicking it did not work for some reason. Locate the element and click little away from the element by offset, and then press TAB button works. Try it. – Shawn Apr 19 '23 at 13:02
2

Your code looks correct, but the issue might be related to the timing of the click you want to execute. Page may take longer to load and you have to click the button after it is ready to be clicked. Try to use this code instead:

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(20)

driver.get("https://www.sreality.cz/hledani/prodej/domy")

wait = WebDriverWait(driver, 10)
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-testid='button-agree']")))
button.click()

We are using the WebDriverWait class to wait for the button to be clickable before clicking on it. The EC.element_to_be_clickable method checks if the element is both visible and enabled, so we are sure we can click on it. We are using a timeout of 10 seconds for the wait, but you can adjust it.

The idea came from this post: Wait for element to be clickable using python and Selenium

Deborisz
  • 196
  • 2