inginging
inginging

Reputation: 1

How to click on specific dates with a calendar using Selenium and Python

I'm trying to read data from a website that contains multiple dropdown menus and tables using Selenium. Here's the link: "https://markets.ft.com/data/funds/tearsheet/historical?s=NL0006294175:EUR".

I need to change the date range, suppose that I want to see the prices of this stock from 1st January to 5th January, so I click on the 2 little calendars. Selecting and clicking on a certain date from the table on the left is ok, I manage to do it using xpaths and css selectors without problems.

However clicking on a date from the table on the right is really hard and I don't understand why. Python is always displaying errors like:

selenium.common.exceptions.ElementNotVisibleException: Message: element not interactable

Here's my code:

driver.get(r'https://markets.ft.com/data/etfs/tearsheet/historical?s=O9P:SES:USD')
driver.find_element_by_css_selector("body > div.o-grid-container.mod-container > div:nth-child(2) > section.mod-main-content > div:nth-child(1) > div > h2 > span").click()
driver.find_element_by_css_selector("body > div.o-grid-container.mod-container > div:nth-child(2) > section.mod-main-content > div:nth-child(1) > div > div > div.mod-ui-filter-overlay.clearfix.mod-filter-ui-historical-prices-overlay > div.mod-ui-overlay.mod-ui-filter-overlay__form > div > form > fieldset > span > div.mod-ui-date-picker.mod-filter-ui-historical-prices-overlay__date--from > div.mod-ui-date-picker__input-container > i").click()
driver.find_element_by_xpath('//*[@title="Next month"]').click()
driver.find_element_by_xpath("//*[@aria-label='1 Jan, %d']" %(y)).click()  #The click on the table on the left works
driver.find_element_by_css_selector("body > div.o-grid-container.mod-container > div:nth-child(2) > section.mod-main-content > div:nth-child(1) > div > div > div.mod-ui-filter-overlay.clearfix.mod-filter-ui-historical-prices-overlay > div.mod-ui-overlay.mod-ui-filter-overlay__form > div > form > fieldset > span > div.mod-ui-date-picker.mod-filter-ui-historical-prices-overlay__date--to > div.mod-ui-date-picker__input-container > i").click() 
time.sleep(2)
driver.find_element_by_xpath("//*[@aria-label='5 Jan, %d']" %(y)).click()   #this does not work, the element is not interactable

I also tried to use ActionChains and WebDriverWait but nothing works. I suspect that the problem is that the two tables are really similar and selenium is trying to access the first table even after it is not visible anymore, but I really don't know how to fix that.

Do you know if there's a way to click on a date in the second table?

Thanks in advance.

Upvotes: 0

Views: 3705

Answers (4)

S.Kalra
S.Kalra

Reputation: 91

You can try below code for the calendar events.

driver.findElement(By.xpath("//div[contains(@class, 'date--from')]")).click();
driver.findElement(By.xpath("//div[contains(@class, 'date--from')]//div[contains(@class,'picker__nav--next')]")).click();
driver.findElement(By.xpath("//div[contains(@class, 'date--from')]//div[@aria-label='1 Jan, 2019']")).click();
driver.findElement(By.xpath("//div[contains(@class, 'date--to')]")).click();
driver.findElement(By.xpath("//div[contains(@class, 'date--to')]//div[contains(@class,'picker__nav--next')]")).click();
driver.findElement(By.xpath("//div[contains(@class, 'date--to')]//div[@aria-label='5 Jan, 2019']")).click();

If it doesn't work, you can use some wait after calendar click to let the calendar be open.

Upvotes: 1

undetected Selenium
undetected Selenium

Reputation: 193088

To see the prices of this stock from 1st January to 5th January before clicking you need to induce WebDriverWait for the desired element to be clickable and you can use the following solution:

  • Code Block:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    options = webdriver.ChromeOptions()
    options.add_argument("start-maximized")
    options.add_argument("disable-infobars")
    options.add_argument("--disable-extensions")
    driver= webdriver.Chrome(chrome_options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get(r'https://markets.ft.com/data/etfs/tearsheet/historical?s=O9P:SES:USD')
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//span[@class='mod-ui-filter-overlay__filter-toggle']"))).click()
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='mod-ui-date-picker mod-filter-ui-historical-prices-overlay__date--from']//i[@class='mod-icon mod-icon--calendar']"))).click()
    driver.find_element_by_xpath("//div[@class='mod-ui-date-picker mod-filter-ui-historical-prices-overlay__date--from']//div[@title='Next month']").click()
    driver.find_element_by_xpath("//div[@class='mod-ui-date-picker mod-filter-ui-historical-prices-overlay__date--from']//div[@aria-label='1 Jan, 2019']").click()
    WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[@class='mod-ui-date-picker mod-filter-ui-historical-prices-overlay__date--to']//i[@class='mod-icon mod-icon--calendar']"))).click()
    driver.find_element_by_xpath("//div[@class='mod-ui-date-picker mod-filter-ui-historical-prices-overlay__date--to']//div[@aria-label='5 Jan, 2019']").click()
    
  • browser Snapshot:

Calander_Clicks

Upvotes: 0

ewwink
ewwink

Reputation: 19154

there are 2 problem, when you click first date there will be overlapped element that prevent to click second input, you need to wait until this element removed, the you need to select second input date it can be done by using xpath (//the_xpath_selector)[2]

driver.get(r'https://markets......')
driver.find_element_by_css_selector('h2 span[data-mod-action="toggle-filter"]').click()
# 4 input, index 1 and 3 are hidden
inputDate = driver.find_elements_by_css_selector('.mod-ui-date-picker input')
inputDate[0].click()
driver.find_element_by_xpath('//*[@title="Next month"]').click()
driver.find_element_by_xpath("//*[@aria-label='1 Jan, %d']" %(y)).click() 
# wait until the element removed
wait.until(
    lambda d: len(d.find_elements_by_css_selector('.mod-ui-loading__overlay')) == 0
)
inputDate[2].click()
# select second date piker "[2]"
driver.find_element_by_xpath("(//*[@aria-label='5 Jan, %d'])[2]" %(y)).click()

Upvotes: 0

cullzie
cullzie

Reputation: 2755

The problem is that there are 2 elements which match the selector you have mentioned on that page. Simplest way to check is to open your browser console and go through your case manually.

You need a way to distinguish between the two. In order to get a clear xpath you should only have one of the date pickers open at a time. Then you could use something like the following to get a match.

//div[contains(@class,'picker--opened')]//*[@aria-label='5 Jan, 2019']

Upvotes: 0

Related Questions