Jan Kwiatkowski
Jan Kwiatkowski

Reputation: 111

Selenium not clicking element, when in a loop

The code is working itself, but when thrown to loop not working anymore.

driver.get("https://www.esky.pl/okazje/16578/WMI-EDI-FR")
i = 1
departure_date_clickable = False
while departure_date_clickable == False:
    try:
        time.sleep(5)
        xpath ="/html/body/div[4]/div[3]/div/div[1]/div[1]/div[2]/div/div[4]/div/div[{}]".format(i)
        find_ele = driver.find_element_by_xpath(xpath)
        find_ele.click()
        print("Departure:Found clickable date on " + str(i))
        departure_date_clickable = True
    except WebDriverException:
        print("Departure date not clickable, checking next day")
        i += 1
        continue

I expect to click first element able to be clicked from the calendar. But for some reason it's problem for selenium when in loop.

Code that's working:

xpath = "/html/body/div[4]/div[3]/div/div[1]/div[1]/div[2]/div/div[4]/div/div[{}]".format("4")
find_ele = driver.find_element_by_xpath(xpath)
time.sleep(2)
find_ele.click()

Upvotes: 0

Views: 2280

Answers (5)

Fiona Pye
Fiona Pye

Reputation: 28

I had the same problem in R while using selenium, I found that running the command to click twice sequentially within the loop works. When the click was only present once it seemed to highlight the element, but not click on it.

While the language is different, the logic might hold. I have provided the code below in a kind of pseudo form so the logic can be seen.

The loop would iterate over different webpages within a list (represented by 'list') with the same element (represented by '[xpath]') to be clicked in each webpage in turn.

library(RSelenium)  # load package

#  set up the driver
fprof <-getFirefoxProfile('[pathtoprofile]', useBase = TRUE)
rd <- rsDriver(browser = "firefox", port = 4567L, 
               extraCapabilities = fprof
)

ffd <- rd$client

for (i in 1:length(list)){
  
    ffd$open()  # open the browser
    ffd$navigate(list[i])  # navigate to page
    Sys.sleep(10)  # wait

    ffd$findElement("xpath", '[xpath]')$clickElement()  # click element first time
    ffd$findElement("xpath", '[xpath]')$clickElement()  # click element second time

    Sys.sleep(5)  # wait

    ffd$close()  # close the browser

}

Upvotes: 1

SeleniumUser
SeleniumUser

Reputation: 4177

Please find below solution, There are few issues observed while iterating through a list element. Kindly note if you want to select any specific departure date then you need to put that condition in the for loop. At the moment as per your above code we are just click all departure dates

from selenium.common.exceptions import WebDriverException
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.support.ui import WebDriverWait as Wait
from selenium.webdriver.common.action_chains import ActionChains

driver = webdriver.Chrome('C:\New folder\chromedriver.exe')

driver.maximize_window()

driver.get("https://www.esky.pl/okazje/16578/WMI-EDI-FR")
i = 1
departure_date_clickable = False
while departure_date_clickable == False:
    try:

        xpath = WebDriverWait(driver, 15).until(EC.presence_of_all_elements_located((By.XPATH, "//div[@id='departure-calendar']//div[@class='month-days']/div/div")))
        for value in xpath:
            value.click()
            departure_date_clickable = True


    except WebDriverException:

Upvotes: 1

Sers
Sers

Reputation: 12255

You can get all departure days with offer using:

driver.find_elements_by_css_selector("#departure-calendar .cell-day.number.offer")

For arrival calendar:

driver.find_elements_by_css_selector("#arrival-calendar .cell-day.number.offer")

Code below click on each day with offer in departure calendar and print the date:

driver.get("https://www.esky.pl/okazje/16578/WMI-EDI-FR")

departure_days = driver.find_elements_by_css_selector("#departure-calendar .cell-day.number.offer")

for departure_day in departure_days:
    departure_day.click()
    # print selected date
    print(departure_day.get_attribute("data-qa-date"))

Upvotes: 0

JeffC
JeffC

Reputation: 25597

If you are just looking for the first available date, you can use the CSS selector below

div.cell-day.offer

Your code would look like

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

driver.get("https://www.esky.pl/okazje/16578/WMI-EDI-FR")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.cell-day.offer"))).click()

Upvotes: 0

KILLtheWEEZEL
KILLtheWEEZEL

Reputation: 268

I recommend identifying clickable divs by a class attribute unique to those divs. It looks like all the "clickable" links have a class called "offer" so you could add an if else condition to check each element for that class. I also added a termination condition to your loop since there are 35 divs in the block.

driver.get("https://www.esky.pl/okazje/16578/WMI-EDI-FR")
i = 1
departure_date_clickable = False
while departure_date_clickable == False and i <= 35:
    try:
        time.sleep(1)
        xpath ="/html/body/div[4]/div[3]/div/div[1]/div[1]/div[2]/div/div[4]/div/div[{}]".format(i)
        find_ele = driver.find_element_by_xpath(xpath)
        if "offer" in find_ele.get_attribute("class").split(" "):
            find_ele.click()
            print("Departure:Found clickable date on " + str(i))
            departure_date_clickable = True
        else:
            raise error()
    except:
        print("Departure date not clickable, checking next day")
        i += 1
        continue

Upvotes: 1

Related Questions