python-3.xselenium-webdriverwebdriverwebdriverwaitexpected-condition

How to click on a button continuously until another element appears using Selenium Python?


I have a website which has a button "show more", which one can click as often as one likes. At some point, there will be a <span> with same name and as soon as I see that one, I want to stop clicking the button.

Unfortunately, when clicking the button, it takes some moments until everything is expanded and the button is visible again. During that moment, the tag "aria-busy="true" is set.

So at the moment, my code works but I wait 10 seconds until I hit the button again. That is far too long, but of course, if I set this too low, the operation can fail.

My current code is this:

# Params: url, button-class, span_label
waiting_time = 10
options = Options()
driver = webdriver.Chrome(options=options)
driver.get(url)
wait = WebDriverWait(driver, waiting_time)
button = wait.until(
    EC.element_to_be_clickable((By.CLASS_NAME, button-class))
)
while True:
    try:
        button.click()
        wait.until(EC.visibility_of_element_located((By.XPATH, span_label)))
        logging.debug("Found last block, continue")
        break  # Exit the loop if the span element is found
    except TimeoutException:
        continue  # Continue clicking the button if the span element is not found within the timeout

content = driver.page_source
driver.quit()

I already use WebDriverWait, but that one does not do implicit wait for me. Also, I have the feeling that this looping approach is quite bad.

So my question is: Is there more efficient and better code for clicking the button until the span appears?


Solution

  • To continue clicking on the show more button untill the <span> appears you can induce WebDriverWait for the invisibility_of_element_located() of the <span> and then induce WebDriverWait for the element_to_be_clickable() as follows:

    while True:
        try:
            wait.until(EC.invisibility_of_element_located((By.XPATH, span_label)))
            wait.until(EC.element_to_be_clickable((By.CLASS_NAME, button-class)).click()
            continue # Continue clicking the button if the span element is not found within the timeout
        except TimeoutException:
            logging.debug("Found the span, break")
            break
    
    content = driver.page_source
    driver.quit()
    

    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