Python Selenium + Datepicker Click - python

I have been banging my head around trying to get the price of a room like this for example by clicking the first available (green) datepicker checkin input and then clicking the first available datepicker checkout input so the price for the minium period is generated.
My code is a mess so i would really appreciate if someone could post a cleaner code to achieve that.
I am using Python selenium + scrapy although something in Java for example would still help.
UPDATE:
here is the code:
def availability(self, doc):
url = doc['url'] + '#calendar'
self.driver.get(url)
is_active = True
# We want to the availability/price for each day in a month.
availabilities = []
# wait for the check in input to load
wait = WebDriverWait(self.driver, 10)
try:
elem = wait.until(
EC.visibility_of_element_located(
(By.CSS_SELECTOR, ".dates-group input[name=startDateInput]")
)
)
except TimeoutException:
pass
else:
elem.click() # open calendar
# wait for datepicker to load
wait.until(
EC.visibility_of_element_located(
(By.CSS_SELECTOR, '.ui-datepicker:not(.loading)'))
)
days = self.driver.find_elements_by_css_selector(
"#ui-datepicker-div tr td"
)
for cell in days:
day = cell.text.strip()
if not day:
continue
if "full-changeover" not in cell.get_attribute("class"):
available = False
else:
available = True
self.logger.warning('CELL "%s"', cell)
self.logger.warning('DAY "%s"', day)
self.logger.warning('available "%s"', available)
# The first iteration was to list the availability, now we want to
# click the first available element to get the price
for cell in days:
day = cell.text.strip()
if not day:
continue
if "full-changeover" in cell.get_attribute("class"):
self.logger.warning('CLICK IT "%s"', day)
self.driver.implicitly_wait(10)
x = self.driver.find_element_by_xpath("//table/tbody/tr/td/a[text()=" + day + "]")
self.driver.implicitly_wait(10)
x.click() # Element not found in the cache issue here
# import ipdb; ipdb.set_trace()
# self.logger.warning('CELL "%s"', cell)
# self.logger.warning('DAY "%s"', day)
# self.logger.warning('available "%s"', available)
# elem.click() # close checkin calendar
# Now lets click on the checkout input to get the price and minimum
# number of days. We probably don't have to wait for the checkout
# because its already loaded but you never know.
try:
elem = wait.until(
EC.visibility_of_element_located(
(By.CSS_SELECTOR,
".dates-group input[name=endDateInput]")
)
)
except TimeoutException:
pass
else:
# elem.click() # open calendar in checkout input
# wait for datepicker to load
wait.until(
EC.visibility_of_element_located(
(By.CSS_SELECTOR, '.ui-datepicker:not(.loading)'))
)
days = self.driver.find_elements_by_css_selector(
"#ui-datepicker-div tr td"
)
for cell in days:
day = cell.text.strip()
if not day:
continue
# This is the first available date to checkout
if "full-changeover" in cell.get_attribute("class"):
self.logger.warning('CLICK IT "%s"', available)
import ipdb; ipdb.set_trace()
# Here we would get the generated price
self.logger.warning('CELL "%s"', cell)
self.logger.warning('DAY "%s"', day)
self.logger.warning('available "%s"', available)
import ipdb; ipdb.set_trace()
return {'availabilities': availabilities, 'is_active': is_active}
Thanks

One tricky thing about this calendar is that you first need to hover a particular day and then relocate the active day and click it. Here is a working implementation that selects the first available start and end dates and prints the calculated price:
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.maximize_window()
wait = WebDriverWait(driver, 10)
url = 'https://www.homeaway.pt/arrendamento-ferias/p1418427a?uni_id=1590648'
driver.get(url)
# pick start date
start_date = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".quotebar-container input[name=startDateInput]")))
start_date.click()
first_available_date = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ui-datepicker-div td.full-changeover > a")))
ActionChains(driver).move_to_element(first_available_date).perform()
driver.find_element_by_css_selector("#ui-datepicker-div td.full-selected.full-changeover > a").click()
# pick end date (TODO: violates DRY principle, refactor!)
end_date = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".quotebar-container input[name=endDateInput]")))
end_date.click()
first_available_date = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#ui-datepicker-div td.full-changeover > a")))
ActionChains(driver).move_to_element(first_available_date).perform()
driver.find_element_by_css_selector("#ui-datepicker-div td.full-selected.full-changeover > a").click()
# get the calculated price
price = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".price-quote .price-total")))
print(price.text)
driver.close()
At the moment, it selects 20/04/2016 and 23/04/2016 and prints 180€.
Hope that helps.

Related

scraping with selenium cant click on clickable text

I am trying to scrape some data from yahoo finance, for each stock, I want to get the historical data. Taking the Apple stock. I should go to https://finance.yahoo.com/quote/AAPL/history?p=AAPL and choose "MAX" from "Time Period". so
I believe the script I wrote so far is getting the date element, but somehow clicking on it to be able to choose "MAX" is not working.
here is my whole script:
# using linux here
project_path = os.getcwd()
driver_path = project_path + "/" + "chromedriver"
yahoo_finance = "https://finance.yahoo.com/quote/"
driver = webdriver.Chrome(driver_path)
def get_data(symbol='AAPL'):
stock_history_link = yahoo_finance + symbol + '/history?p=' + symbol
driver.get(stock_history_link)
date_picker = '//div[contains(#class, "D(ib)") and contains(#class, "Pos(r)") and contains(#class, "Cur(p)")' \
'and contains(#class, "O(n):f")]'
try:
print("I am inside")
date_picker_2 = "//div[#class='Pos(r) D(ib) O(n):f Cur(p)']"
date_picker_element = driver.find_element_by_xpath(date_picker_2)
print("date_picker_element: ", date_picker_element)
date_picker_element.click()
try:
print("I will be waiting for the date")
my_dropdown = WebDriverWait(driver, 100).until(
EC.presence_of_element_located((By.ID, 'dropdown-menu'))
)
print(my_dropdown)
print("I am not waiting anymore")
except TimeoutException as e:
print("wait timed out")
print(e)
except WebDriverException:
print("Something went wrong while trying to pick the max date")
if __name__ == '__main__':
try:
get_data()
except:
pass
# finally:
# driver.quit()
To click the button with Max just open it up and target it.
driver.get("https://finance.yahoo.com/quote/AAPL/history?p=AAPL")
wait = WebDriverWait(driver, 10)
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[#class='C($linkColor) Fz(14px)']"))).click()
wait.until(EC.element_to_be_clickable((By.XPATH, "//button[#data-value='MAX']"))).click()
Element:
<button class="Py(5px) W(45px) Fz(s) C($tertiaryColor) Cur(p) Bd Bdc($seperatorColor) Bgc($lv4BgColor) Bdc($linkColor):h Bdrs(3px)" data-value="MAX"><span>Max</span></button>
Imports:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
You have the wrong xpath for the date_picker_2:
date_picker_2 = '//*[#id="Col1-1-HistoricalDataTable-Proxy"]/section/div[1]/div[1]/div[1]/div/div/div/span'
Using requests:
import requests
import datetime
end = int(datetime.datetime.strptime(datetime.date.today().isoformat(), "%Y-%m-%d").timestamp())
url = f"https://finance.yahoo.com/quote/AAPL/history?period1=345427200&period2={end}&interval=1d&filter=history&frequency=1d&includeAdjustedClose=true"
requests.get(url)
Gets you to the same end page.

trying to close popover - python - selenium - Glassdoor

Trying to close a popover while scraping Glassdoor for jobs [It keeps popping up from time to time - need to close it every time].. I've tried quite a few things
Tried closing it by looking for the close button. Please help !
driver.find_element_by_class_name("SVG_Inline modal_closeIcon").click()
Tried looking for a ElementClickInterceptedException when the bot couldn't click on the next company, and everywhere else there was a click
element = WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.CLASS_NAME, "SVG_Inline-svg modal_closeIcon-svg")))
element.click()
This is the website:
https://www.glassdoor.co.uk/Job/web-developer-jobs-SRCH_KO0,13.htm
This is the complete code:
from selenium.common.exceptions import NoSuchElementException, ElementClickInterceptedException, StaleElementReferenceException
from selenium import webdriver
import time
import pandas as pd
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def get_jobs(keyword, num_jobs, verbose, place):
'''Gathers jobs as a dataframe, scraped from Glassdoor'''
#Initializing the webdriver
options = webdriver.ChromeOptions()
#Uncomment the line below if you'd like to scrape without a new Chrome window every time.
#options.add_argument('headless')
#Change the path to where chromedriver is in your home folder.
#driver = webdriver.Chrome(executable_path="/Users/omersakarya/Documents/GitHub/scraping-glassdoor-selenium/chromedriver", options=options)
driver = webdriver.Chrome()
driver.set_window_size(1120, 1000)
url = "https://www.glassdoor.co.uk/Job/web-developer-jobs-SRCH_KO0,13.htm"
driver.get(url)
jobs = []
time.sleep(3)
driver.find_element_by_id("onetrust-accept-btn-handler").click()
time.sleep(3)
while len(jobs) < num_jobs: #If true, should be still looking for new jobs.
job_buttons = driver.find_elements_by_class_name("jl") #jl for Job Listing. These are the buttons we're going to click.
try:
for job_button in job_buttons:
if len(jobs) >= num_jobs:
break
print("Progress: {}".format("" + str(len(jobs)) + "/" + str(num_jobs)))
job_button.click()
collected_successfully = False
while not collected_successfully:
try:
company_name = driver.find_element_by_xpath('.//div[#class="employerName"]').text
location = driver.find_element_by_xpath('.//div[#class="location"]').text
job_title = driver.find_element_by_xpath('.//div[contains(#class, "title")]').text
job_description = driver.find_element_by_xpath('.//div[#class="jobDescriptionContent desc"]').text
collected_successfully = True
except:
time.sleep(5)
try:
#salary_estimate = driver.find_element_by_xpath('.//span[#class="gray salary"]').text
salary_estimate = driver.find_element_by_xpath('//*[#id="HeroHeaderModule"]/div[3]/div[1]/div[4]/span').text
except NoSuchElementException:
salary_estimate = -1 #You need to set a "not found value. It's important."
try:
rating = driver.find_element_by_xpath('.//span[#class="rating"]').text
except NoSuchElementException:
rating = -1 #You need to set a "not found value. It's important."
#Printing for debugging
if verbose:
print("Job Title: {}".format(job_title))
print("Salary Estimate: {}".format(salary_estimate))
print("Job Description: {}".format(job_description[:500]))
print("Rating: {}".format(rating))
print("Company Name: {}".format(company_name))
print("Location: {}".format(location))
#Going to the Company tab...
#clicking on this:
#<div class="tab" data-tab-type="overview"><span>Company</span></div>
try:
driver.find_element_by_xpath('.//div[#class="tab" and #data-tab-type="overview"]').click()
try:
#<div class="infoEntity">
# <label>Headquarters</label>
# <span class="value">San Francisco, CA</span>
#</div>
headquarters = driver.find_element_by_xpath('.//div[#class="infoEntity"]//label[text()="Headquarters"]//following-sibling::*').text
except NoSuchElementException:
headquarters = -1
try:
size = driver.find_element_by_xpath('.//div[#class="infoEntity"]//label[text()="Size"]//following-sibling::*').text
except NoSuchElementException:
size = -1
try:
founded = driver.find_element_by_xpath('.//div[#class="infoEntity"]//label[text()="Founded"]//following-sibling::*').text
except (NoSuchElementException, StaleElementReferenceException):
founded = -1
try:
type_of_ownership = driver.find_element_by_xpath('.//div[#class="infoEntity"]//label[text()="Type"]//following-sibling::*').text
except NoSuchElementException:
type_of_ownership = -1
try:
industry = driver.find_element_by_xpath('.//div[#class="infoEntity"]//label[text()="Industry"]//following-sibling::*').text
except NoSuchElementException:
industry = -1
try:
sector = driver.find_element_by_xpath('.//div[#class="infoEntity"]//label[text()="Sector"]//following-sibling::*').text
except NoSuchElementException:
sector = -1
try:
revenue = driver.find_element_by_xpath('.//div[#class="infoEntity"]//label[text()="Revenue"]//following-sibling::*').text
except NoSuchElementException:
revenue = -1
try:
competitors = driver.find_element_by_xpath('.//div[#class="infoEntity"]//label[text()="Competitors"]//following-sibling::*').text
except NoSuchElementException:
competitors = -1
except (NoSuchElementException,ElementClickInterceptedException,StaleElementReferenceException): #Rarely, some job postings do not have the "Company" tab.
if NoSuchElementException:
time.sleep(1)
headquarters = -1
size = -1
founded = -1
type_of_ownership = -1
industry = -1
sector = -1
revenue = -1
competitors = -1
else:
driver.find_element_by_class_name("selected").click()
driver.find_element_by_class_name("SVG_Inline modal_closeIcon").click()
element = WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.CLASS_NAME, "SVG_Inline-svg modal_closeIcon-svg")))
element.click()
pass
if verbose:
print("Headquarters: {}".format(headquarters))
print("Size: {}".format(size))
print("Founded: {}".format(founded))
print("Type of Ownership: {}".format(type_of_ownership))
print("Industry: {}".format(industry))
print("Sector: {}".format(sector))
print("Revenue: {}".format(revenue))
print("Competitors: {}".format(competitors))
print("####################################################")
jobs.append({"Job Title" : job_title,
"Salary Estimate" : salary_estimate,
"Job Description" : job_description,
"Rating" : rating,
"Company Name" : company_name,
"Location" : location,
"Headquarters" : headquarters,
"Size" : size,
"Founded" : founded,
"Type of ownership" : type_of_ownership,
"Industry" : industry,
"Sector" : sector,
"Revenue" : revenue,
"Competitors" : competitors})
#You might
#time.sleep(0.5)
except (ElementClickInterceptedException, StaleElementReferenceException):
alertObj = driver.switch_to.alert
alertObj.accept()
alertObj.dismiss()
driver.find_element_by_class_name("selected").click()
driver.find_element_by_class_name("SVG_Inline modal_closeIcon").click()
element = WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.CLASS_NAME, "SVG_Inline-svg modal_closeIcon-svg")))
element.click()
pass
#add job to jobs
#Clicking on the "next page" button
# try:
# driver.find_element_by_xpath('.//li[#class="page"]//a').click()
# except NoSuchElementException:
# print("Scraping terminated before reaching target number of jobs. Needed {}, got {}.".format(num_jobs, len(jobs)))
# break
# time.sleep(5)
try:
driver.find_element_by_xpath('.//li[#class="next"]//a').click()
except (ElementClickInterceptedException):
#print("Scraping terminated before reaching target number of jobs. Needed {}, got {}.".format(num_jobs, len(jobs)))
driver.find_element_by_class_name("selected").click()
driver.find_element_by_class_name("SVG_Inline modal_closeIcon").click()
element = WebDriverWait(driver, 3).until(EC.presence_of_element_located((By.CLASS_NAME, "SVG_Inline-svg modal_closeIcon-svg")))
element.click()
element.text
pass
#break
return pd.DataFrame(jobs) #This line converts the dictionary object into a pandas DataFrame.
df = gs.get_jobs(keyword, num_jobs, False, place)
Trying to get rid of this:
enter image description here
[Screenshot of the element I need to close and continue with the loop][2]

In selenium how to find out the exact number of XPATH links with different ids?

With Python3 and selenium I want to automate the search on a public information site. In this site it is necessary to enter the name of a person, then select the spelling chosen for that name (without or with accents or name variations), access a page with the list of lawsuits found and in this list you can access the page of each case.
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
from selenium.common.exceptions import TimeoutException, NoSuchElementException
from selenium.webdriver.common.keys import Keys
import time
import re
Name that will be searched
name = 'JOSE ROBERTO ARRUDA'
Create path, search start link, and empty list to store information
firefoxPath="/home/abraji/Documentos/Code/geckodriver"
link = 'https://ww2.stj.jus.br/processo/pesquisa/?aplicacao=processos.ea'
processos = []
Call driver and go to first search page
driver = webdriver.Firefox(executable_path=firefoxPath)
driver.get(link)
Position cursor, fill and click
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#idParteNome'))).click()
time.sleep(1)
driver.find_element_by_xpath('//*[#id="idParteNome"]').send_keys(name)
time.sleep(6)
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#idBotaoPesquisarFormularioExtendido'))).click()
Mark all spelling possibilities for searching
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#idBotaoMarcarTodos'))).click()
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#idBotaoPesquisarMarcados'))).click()
time.sleep(1)
Check how many pages of data there are - to be used in "for range"
capta = driver.find_element_by_xpath('//*[#id="idDivBlocoPaginacaoTopo"]/div/span/span[2]').text
print(capta)
paginas = int(re.search(r'\d+', capta).group(0))
paginas = int(paginas) + 1
print(paginas)
Capture routine
for acumula in range(1, paginas):
# Fill the field with the page number and press enter
driver.find_element_by_xpath('//*[#id="idDivBlocoPaginacaoTopo"]/div/span/span[2]/input').send_keys(acumula)
driver.find_element_by_xpath('//*[#id="idDivBlocoPaginacaoTopo"]/div/span/span[2]/input').send_keys(Keys.RETURN)
time.sleep(2)
# Captures the number of processes found on the current page - qt
qt = driver.find_element_by_xpath('//*[#id="idDivBlocoMensagem"]/div/b').text
qt = int(qt) + 2
print(qt)
# Iterate from found number of processes
for item in range(2, qt):
# Find the XPATH of each process link - start at number 2
vez = '//*[#id="idBlocoInternoLinhasProcesso"]/div[' + str(item) + ']/span[1]/span[1]/span[1]/span[2]/a'
print(vez)
# Access the direct link and click
element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, vez)))
element.click()
# Run tests to get data
try:
num_unico = driver.find_element_by_xpath('//*[#id="idProcessoDetalhesBloco1"]/div[6]/span[2]/a').text
except NoSuchElementException:
num_unico = "sem_numero_unico"
try:
nome_proc = driver.find_element_by_xpath('//*[#id="idSpanClasseDescricao"]').text
except NoSuchElementException:
nome_proc = "sem_nome_encontrado"
try:
data_autu = driver.find_element_by_xpath('//*[#id="idProcessoDetalhesBloco1"]/div[5]/span[2]').text
except NoSuchElementException:
data_autu = "sem_data_encontrada"
# Fills dictionary and list
dicionario = {"num_unico": num_unico,
"nome_proc": nome_proc,
"data_autu": data_autu
}
processos.append(dicionario)
# Return a page to click on next process
driver.execute_script("window.history.go(-1)")
# Close driver
driver.quit()
In this case I captured the number of link pages (3) and the total number of links (84). So my initial idea was to do the "for" three times and within them split the 84 links
The direct address of each link is in XPATH (//*[#id="idBlocoInternoLinhasProcesso"]/div[41]/span[1]/span[1]/span[1]/span[2]/a) which I replace with the "item" to click
For example, when it arrives at number 42 I have an error because the first page only goes up to 41
My problem is how to go to the second page and then restart only "for" secondary
I think the ideal would be to know the exact number of links on each of the three pages
Anyone have any ideas?
Code below is "Capture routine":
wait = WebDriverWait(driver, 20)
#...
while True:
links = wait.until(EC.presence_of_all_elements_located((By.XPATH, "//span[contains(#class,'classSpanNumeroRegistro')]")))
print("links len", len(links))
for i in range(1, len(links) + 1):
# Access the direct link and click
.until(EC.element_to_be_clickable((By.XPATH, f"(//span[contains(#class,'classSpanNumeroRegistro')])[{i}]//a"))).click()
# Run tests to get data
try:
num_unico = driver.find_element_by_xpath('//*[#id="idProcessoDetalhesBloco1"]/div[6]/span[2]/a').text
except NoSuchElementException:
num_unico = "sem_numero_unico"
try:
nome_proc = driver.find_element_by_xpath('//*[#id="idSpanClasseDescricao"]').text
except NoSuchElementException:
nome_proc = "sem_nome_encontrado"
try:
data_autu = driver.find_element_by_xpath('//*[#id="idProcessoDetalhesBloco1"]/div[5]/span[2]').text
except NoSuchElementException:
data_autu = "sem_data_encontrada"
# Fills dictionary and list
dicionario = {"num_unico": num_unico,
"nome_proc": nome_proc,
"data_autu": data_autu
}
processos.append(dicionario)
# Return a page to click on next process
driver.execute_script("window.history.go(-1)")
# wait.until(EC.presence_of_element_located((By.CLASS_NAME, "classSpanPaginacaoImagensDireita")))
next_page = driver.find_elements_by_css_selector(".classSpanPaginacaoProximaPagina")
if len(next_page) == 0:
break
next_page[0].click()
You can try run the loop until next button is present on the screen. the logic will look like this,
try:
next_page = driver.find_element_by_class_name('classSpanPaginacaoProximaPagina')
if(next_page.is_displayed()):
next_page.click()
except NoSuchElementException:
print('next page does not exists')

how to wait for one drop down list to be processed before moving to the next one?

Having an issue with drop down menus in my selenium (python). In this page, what happens is that when selecting a drop down option, it will process the selection, making the other options not selectable until that process is finished. I'm trying to say in my script to wait until a drop down list has processed it's option before moving onto the next one, but it's just hanging. How can I get it to wait for the option to be processed in one drop down menu before moving to the next drop down?
Below is what I've attempted:
#Meal details
try:
pax_one_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown"))
pax_one_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn")))
pax_one_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn"))
pax_one_ib_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown")))
pax_two_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown"))
pax_two_ob_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn")))
pax_two_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn"))
pax_two_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown")))
pax_three_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownt"))
pax_three_ob_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn")))
pax_three_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn"))
pax_three_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown")))
pax_four_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown"))
pax_four_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn")))
pax_four_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn"))
pax_four_ib_meal.select_by_index(1)
You can visit the www.jet2.com page and load up the script below to see what I'm seeing (it's on the meals page as it's the meals drop down options I'm having issues with). After reserving your seats, you will have to manually click on the continue button when 'you have reserved your seats' message comes up as I'm still trying to figure out how to do this.
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from datetime import datetime, timedelta
def select_date(calendar, mininum_date=None):
try:
# check if "Your Date" is there
your_date_elm = calendar.find_element_by_class_name("your-date")
your_date = your_date_elm.get_attribute("data-date")
print("Found 'Your Date': " + your_date)
your_date_elm.click()
# check if your_date against the minimum date if given
your_date = datetime.strptime(your_date, "%Y-%m-%d")
if mininum_date and your_date < mininum_date:
raise NoSuchElementException("Minimum date violation")
return your_date
except NoSuchElementException:
flight_date = None
flight_date_elm = None
while True:
print("Processing " + calendar.find_element_by_css_selector("div.subheader > p").text)
try:
if mininum_date:
flight_date_elms = calendar.find_elements_by_class_name("flights")
flight_date_elm = next(flight_date_elm for flight_date_elm in flight_date_elms
if datetime.strptime(flight_date_elm.get_attribute("data-date"), "%Y-%m-%d") >= mininum_date)
else:
flight_date_elm = calendar.find_element_by_class_name("flights")
except (StopIteration, NoSuchElementException):
calendar.find_element_by_partial_link_text("Next month").click()
# if found - print out the date, click and exit the loop
if flight_date_elm:
flight_date = flight_date_elm.get_attribute("data-date")
print("Found 'Flight Date': " + flight_date)
flight_date_elm.click()
break
return datetime.strptime(flight_date, "%Y-%m-%d")
FROM = "Leeds Bradford"
TO = "Antalya"
PAX1_FORENAME = "Dad"
PAX2_FORENAME = "Mum"
PAX3_FORENAME = "Son"
PAX4_FORENAME = "Daughter"
PAX5_FORENAME = "Baby"
PAX_SURNAME = "Test"
driver = webdriver.Firefox()
#driver = webdriver.Chrome()
driver.get("http://www.jet2.com")
driver.maximize_window()
wait = WebDriverWait(driver, 20)
actions = ActionChains(driver)
# wait for the page to load
wait.until(EC.presence_of_element_located((By.ID, "departure-airport-input")))
# fill out the form
return_flight = driver.find_element_by_id('return-flight-selector').click()
depart_from = driver.find_element_by_id("departure-airport-input").send_keys(FROM)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ui-id-1 .ui-menu-item"))).click()
go_to = driver.find_element_by_id("destination-airport-input").send_keys(TO)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ui-id-2 .ui-menu-item"))).click()
# select depart date
datepicker = driver.find_element_by_id("departure-date-selector")
actions.move_to_element(datepicker).click().perform()
# find the calendar, month and year picker and the current date
calendar = driver.find_element_by_id("departureDateContainer")
month_picker = Select(calendar.find_element_by_class_name("ui-datepicker-month"))
year_picker = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
current_date = calendar.find_element_by_class_name("ui-datepicker-current-day")
# printing out current date
month = month_picker.first_selected_option.text
year = year_picker.first_selected_option.text
print("Current departure date: {day} {month} {year}".format(day=current_date.text, month=month, year=year))
# see if we have an available date in this month
try:
next_available_date = current_date.find_element_by_xpath("following::td[#data-handler='selectDay' and ancestor::div/#id='departureDateContainer']")
print("Found an available departure date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
next_available_date.click()
except NoSuchElementException:
# looping over until the next available date found
while True:
# click next, if not found, select the next year
try:
calendar.find_element_by_class_name("ui-datepicker-next").click()
except NoSuchElementException:
# select next year
year = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
year.select_by_visible_text(str(int(year.first_selected_option.text) + 1))
# reporting current processed month and year
month = Select(calendar.find_element_by_class_name("ui-datepicker-month")).first_selected_option.text
year = Select(calendar.find_element_by_class_name("ui-datepicker-year")).first_selected_option.text
print("Processing {month} {year}".format(month=month, year=year))
try:
next_available_date = calendar.find_element_by_xpath(".//td[#data-handler='selectDay']")
print("Found an available departure date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
next_available_date.click()
break
except NoSuchElementException:
continue
# select return date
datepicker = driver.find_element_by_id("return-date-selector")
actions.move_to_element(datepicker).click().perform()
# find the calendar, month and year picker and the current date
calendar = driver.find_element_by_id("returnDateContainer")
month_picker = Select(calendar.find_element_by_class_name("ui-datepicker-month"))
year_picker = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
current_date = calendar.find_element_by_class_name("ui-datepicker-current-day")
# printing out current date
month = month_picker.first_selected_option.text
year = year_picker.first_selected_option.text
print("Current return date: {day} {month} {year}".format(day=current_date.text, month=month, year=year))
# see if we have an available date in this month
try:
next_available_date = current_date.find_element_by_xpath("following::td[#data-handler='selectDay' and ancestor::div/#id='returnDateContainer']")
print("Found an available return date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
next_available_date.click()
except NoSuchElementException:
# looping over until the next available date found
while True:
# click next, if not found, select the next year
try:
calendar.find_element_by_class_name("ui-datepicker-next").click()
except NoSuchElementException:
# select next year
year = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
year.select_by_visible_text(str(int(year.first_selected_option.text) + 1))
# reporting current processed month and year
month = Select(calendar.find_element_by_class_name("ui-datepicker-month")).first_selected_option.text
year = Select(calendar.find_element_by_class_name("ui-datepicker-year")).first_selected_option.text
print("Processing {month} {year}".format(month=month, year=year))
try:
next_available_date = calendar.find_element_by_xpath(".//td[#data-handler='selectDay']")
print("Found an available return date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
next_available_date.click()
break
except NoSuchElementException:
continue
#select adults
adults = Select(driver.find_element_by_id("adults-number"))
adults.select_by_visible_text("2")
#select children
children = Select(driver.find_element_by_id("children-number"))
children.select_by_visible_text("2")
#children ages
child_one = Select(driver.find_element_by_id("childSelect1"))
child_one.select_by_visible_text("4")
child_two = Select(driver.find_element_by_id("childSelect2"))
child_two.select_by_visible_text("6")
confirm = driver.find_element_by_link_text("Confirm")
confirm.click()
#select infants
infants = Select(driver.find_element_by_id("infants-number"))
infants.select_by_visible_text("1")
#search flights
search_flight = driver.find_element_by_id("search-flights").click()
# get the outbound date
outbound = wait.until(EC.visibility_of_element_located((By.ID, "outboundsearchresults")))
outbound_date = select_date(outbound)
# get the inbound date
inbound = driver.find_element_by_id("inboundsearchresults")
inbound_minimum_date = outbound_date + timedelta(days=7)
inbound_date = select_date(inbound, mininum_date=inbound_minimum_date)
print(outbound_date, inbound_date)
# continue after flights selected
proceed_to_pax = driver.find_element_by_id('navigateActionNext').click()
pax_page = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_passengerList_PassengerGridView_ctl08_butAddBagsForAll")))
#select currency
currency = Select(driver.find_element_by_id("ctl00_MainContent_dynamicCurrencyDropDown"))
currency.select_by_value("1")
#Passenger details
pax_one_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_TitleDropDownList"))
pax_one_title.select_by_visible_text("Mr")
pax_one_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_ForeNameTextBox").send_keys(PAX1_FORENAME)
pax_one_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_SurNameTextBox").send_keys(PAX_SURNAME)
pax_two_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_TitleDropDownList"))
pax_two_title.select_by_visible_text("Mrs")
pax_two_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_ForeNameTextBox").send_keys(PAX2_FORENAME)
pax_two_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_SurNameTextBox").send_keys(PAX_SURNAME)
pax_three_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_TitleDropDownList"))
pax_three_title.select_by_visible_text("Mr")
pax_three_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_ForeNameTextBox").send_keys(PAX3_FORENAME)
pax_three_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_SurNameTextBox").send_keys(PAX_SURNAME)
pax_four_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_TitleDropDownList"))
pax_four_title.select_by_visible_text("Ms")
pax_four_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_ForeNameTextBox").send_keys(PAX4_FORENAME)
pax_four_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_SurNameTextBox").send_keys(PAX_SURNAME)
pax_five_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_TitleDropDownList"))
pax_five_title.select_by_visible_text("Mstr")
pax_five_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_ForeNameTextBox").send_keys(PAX5_FORENAME)
pax_five_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_SurNameTextBox").send_keys(PAX_SURNAME)
#pax baggage
pax_one_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_baggageOutDropDown"))
pax_one_bags.select_by_value("0")
pax_two_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_baggageOutDropDown"))
pax_two_bags.select_by_value("0")
pax_three_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_baggageOutDropDown"))
pax_three_bags.select_by_value("0")
pax_four_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_baggageOutDropDown"))
pax_four_bags.select_by_value("0")
#infant carer
infant_one_carer = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_InfantCarerDropDown"))
infant_one_carer.select_by_visible_text("Mr Dad Test")
#checkin
#online = driver.find_element_by_id("ctl00_MainContent_passengerList_checkinOnline").click()
airport = driver.find_element_by_id("ctl00_MainContent_passengerList_checkinAirport").click()
#continue to seats
continue_pax = driver.find_element_by_id("pageContinue").click()
modal_outer = wait.until(EC.invisibility_of_element_located((By.ID, "ctl00_MainContent_PageTransitionDialog_messageWrapper")))
continue_again = wait.until(EC.element_to_be_clickable((By.ID, "pageContinue"))).click();
seats_page = wait.until(EC.visibility_of_element_located((By.ID, "findyourseat")))
#seats selection - outbound
for outbound_passenger in driver.find_elements_by_css_selector("ol[data-flightbound='Outbound'] li[data-personid]"):
outbound_passenger.click()
#driver.find_elements_by_css_selector("ol.passengerlist li[data-personid]"):
outbound_has_infant = outbound_passenger.get_attribute("data-hasinfant")
# choose seats
if outbound_has_infant:
# select a non-selected infant seat
outbound_seat = driver.find_element_by_css_selector(".outbound .planebody a.seat.infant:not(.reserved):not(.selected)")
else:
# select a non-reserved non-selected seat
outbound_seat = driver.find_element_by_css_selector(".outbound .planebody a.seat:not(.reserved):not(.selected)")
print("Passenger: %s, choosing seat: %s" % (outbound_passenger.text.strip(), outbound_seat.get_attribute("data-seat")))
outbound_seat.click()
outbound_plan = wait.until(EC.invisibility_of_element_located((By.CLASS_NAME, "outbound")))
inbound_plan = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "inbound")))
#seats selection - inbound
for inbound_passenger in driver.find_elements_by_css_selector("ol[data-flightbound='Inbound'] li[data-personid]"):
inbound_passenger.click()
#driver.find_elements_by_css_selector("ol.passengerlist li[data-personid]"):
inbound_has_infant = inbound_passenger.get_attribute("data-hasinfant")
# choose seats
if inbound_has_infant:
# select a non-selected infant seat
inbound_seat = driver.find_element_by_css_selector(".inbound .planebody a.seat.infant:not(.reserved):not(.selected)")
else:
# select a non-reserved non-selected seat
inbound_seat = driver.find_element_by_css_selector(".inbound .planebody a.seat:not(.reserved):not(.selected)")
print("Passenger: %s, choosing seat: %s" % (inbound_passenger.text.strip(), inbound_seat.get_attribute("data-seat")))
try:
inbound_seat.click()
except ElementNotVisibleException:
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#AllInboundPassengersSeatedOk button"))).click()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".submitseatselection button"))).click()
meals = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_InFlightMeal_removeMealButton")))
#Meal details
try:
pax_one_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown"))
pax_one_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn")))
pax_one_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn"))
pax_one_ib_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown")))
pax_two_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown"))
pax_two_ob_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn")))
pax_two_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn"))
pax_two_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown")))
pax_three_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownt"))
pax_three_ob_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn")))
pax_three_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn"))
pax_three_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown")))
pax_four_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown"))
pax_four_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn")))
pax_four_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn"))
pax_four_ib_meal.select_by_index(1)
The logic is a bit different - when you select an item from the dropdown, this dropdown becomes disabled until the price is recalculated - see the disabled attribute appearing on the select element after selecting an option.
So, select an option and wait for the dropdown to be clickable/enabled:
pax_one_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown"))
pax_one_ob_meal.select_by_index(0)
# wait for the dropdown to be clickable/enabled again
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown")))
# proceed to the next dropdown
Please use the xpath or css locator to locate the element and then use select dropdown using index.Use of Fluent wait is good to use in this case.
I see two issues :-)
The first issue is:
//locator is incorrect it has a t in the end
pax_three_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownt"))
// it should be
ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown
and the second issue is with the modal dialog box which we are forced to manually click on "continue" button is actually seems to be part of a iframe and you can get around this by switching through the iframes.
This is a very crude way but the below code works though it can be optimized( so add the below code above " meals selection")
framecount = driver.find_elements_by_tag_name("iframe")
for frame in framecount:
driver.switch_to.frame(frame)
try:
wait.until(EC.element_to_be_clickable((By.XPATH, ".//*[#id='AllInboundPassengersSeatedOk']/div[2]/p[2]/button"))).click()
driver.switch_to.default_content()
break
except TimeoutException:
driver.switch_to.default_content()
print "Not found in the frame"
// i could not understand why but until you loop thorugh the iframes the below element is not visiable
wait.until(EC.element_to_be_clickable((By.XPATH, ".//*[#id='AllInboundPassengersSeatedOk']/div[2]/p[2]/button"))).click()
//Start of meals section
meals = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_InFlightMeal_removeMealButton")))
After the above changes the script worked fine for me :-)

Element no longer attached to the DOM and timeout exceptions

I have written a full selenium script that's working but not all the time as whem I try to select meals (this is last sections of the page), I sometimes get two errors.
One error is a timeout exception as it waits for a meal drop down to have an option selected, wait for it to be clickable again after it loads its selected option before moving onto the next option. I assume for this I need to set the wait = WebDriverWait(driver, 20) to longer than 20 seconds just in case the drop down options are taking longer to load.
Another issue I am having an seems to be occurring a lot in the meals page is this 'Element is no longer attached to the DOM' issue. Again this usually happens when I am on the meals page. Doing some research it seems to be possible that a javascript could be causing this issue but not too sure. Could it be to fix this issue I need to include more waits or maybe I should be looking to refresh pages after navigating from one page to another?
Below I only pasted the relevant code. If you want to view the whole code and try it yourself on the application, then send me a comment.
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
...
driver = webdriver.Firefox()
#driver = webdriver.Chrome()
driver.get("http://www.jet2.com")
driver.maximize_window()
wait = WebDriverWait(driver, 20)
actions = ActionChains(driver)
...
# proceed to the next page (meals)
submit_seat_selection = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#AllInboundPassengersSeatedOk button.submitseatselection")))
submit_seat_selection.click()
meals = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_InFlightMeal_removeMealButton")))
#Meal details
pax_one_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown"))
pax_one_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown")))
pax_one_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn"))
pax_one_ib_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn")))
pax_two_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown"))
pax_two_ob_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown")))
pax_two_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn"))
pax_two_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn")))
pax_three_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown"))
pax_three_ob_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown")))
pax_three_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn"))
pax_three_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn")))
pax_four_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown"))
pax_four_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown")))
pax_four_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn"))
pax_four_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn")))
UPDATE:
Below is the whole code as requested:
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from datetime import datetime, timedelta
import settings
# Search Flights
FROM = "Leeds Bradford"
TO = "Antalya"
# PAX Details
PAX1_FORENAME = "Dad"
PAX2_FORENAME = "Mum"
PAX3_FORENAME = "Son"
PAX4_FORENAME = "Daughter"
PAX5_FORENAME = "Baby"
PAX_SURNAME = "Test"
#Payment Details
NAME_ON_CARD = "Mr Test"
CARD_NUMBER = "1000070000000001"
SECURITY_CODE = "111"
#Contact Details
CONTACT_FIRST_NAME = "Dad"
CONTACT_LAST_NAME = "Test"
POSTCODE = "LS11 9AW"
MOBILE_PHONE = "07766554433"
DESTINATION_PHONE = "01122334455"
HOME_PHONE = "01234567890"
EMAIL = settings.EMAIL
def select_date(calendar, mininum_date=None):
try:
# check if "Your Date" is there
your_date_elm = calendar.find_element_by_class_name("your-date")
your_date = your_date_elm.get_attribute("data-date")
print("Found 'Your Date': " + your_date)
your_date_elm.click()
# check if your_date against the minimum date if given
your_date = datetime.strptime(your_date, "%Y-%m-%d")
if mininum_date and your_date < mininum_date:
raise NoSuchElementException("Minimum date violation")
return your_date
except NoSuchElementException:
flight_date = None
flight_date_elm = None
while True:
print("Processing " + calendar.find_element_by_css_selector("div.subheader > p").text)
try:
if mininum_date:
flight_date_elms = calendar.find_elements_by_class_name("flights")
flight_date_elm = next(flight_date_elm for flight_date_elm in flight_date_elms
if datetime.strptime(flight_date_elm.get_attribute("data-date"), "%Y-%m-%d") >= mininum_date)
else:
flight_date_elm = calendar.find_element_by_class_name("flights")
except (StopIteration, NoSuchElementException):
calendar.find_element_by_partial_link_text("Next month").click()
# if found - print out the date, click and exit the loop
if flight_date_elm:
flight_date = flight_date_elm.get_attribute("data-date")
print("Found 'Flight Date': " + flight_date)
flight_date_elm.click()
break
return datetime.strptime(flight_date, "%Y-%m-%d")
driver = webdriver.Firefox()
#driver = webdriver.Chrome()
driver.get("http://www.jet2.com")
driver.maximize_window()
wait = WebDriverWait(driver, 90)
actions = ActionChains(driver)
# wait for the page to load
wait.until(EC.presence_of_element_located((By.ID, "departure-airport-input")))
# fill out the form
return_flight = driver.find_element_by_id('return-flight-selector').click()
depart_from = driver.find_element_by_id("departure-airport-input").send_keys(FROM)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ui-id-1 .ui-menu-item"))).click()
go_to = driver.find_element_by_id("destination-airport-input").send_keys(TO)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ui-id-2 .ui-menu-item"))).click()
# select depart date
datepicker = driver.find_element_by_id("departure-date-selector")
actions.move_to_element(datepicker).click().perform()
# find the calendar, month and year picker and the current date
calendar = driver.find_element_by_id("departureDateContainer")
month_picker = Select(calendar.find_element_by_class_name("ui-datepicker-month"))
year_picker = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
current_date = calendar.find_element_by_class_name("ui-datepicker-current-day")
# printing out current date
month = month_picker.first_selected_option.text
year = year_picker.first_selected_option.text
print("Current departure date: {day} {month} {year}".format(day=current_date.text, month=month, year=year))
# see if we have an available date in this month
try:
next_available_date = current_date.find_element_by_xpath("following::td[#data-handler='selectDay' and ancestor::div/#id='departureDateContainer']")
print("Found an available departure date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
next_available_date.click()
except NoSuchElementException:
# looping over until the next available date found
while True:
# click next, if not found, select the next year
try:
calendar.find_element_by_class_name("ui-datepicker-next").click()
except NoSuchElementException:
# select next year
year = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
year.select_by_visible_text(str(int(year.first_selected_option.text) + 1))
# reporting current processed month and year
month = Select(calendar.find_element_by_class_name("ui-datepicker-month")).first_selected_option.text
year = Select(calendar.find_element_by_class_name("ui-datepicker-year")).first_selected_option.text
print("Processing {month} {year}".format(month=month, year=year))
try:
next_available_date = calendar.find_element_by_xpath(".//td[#data-handler='selectDay']")
print("Found an available departure date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
next_available_date.click()
break
except NoSuchElementException:
continue
# select return date
datepicker = driver.find_element_by_id("return-date-selector")
actions.move_to_element(datepicker).click().perform()
# find the calendar, month and year picker and the current date
calendar = driver.find_element_by_id("returnDateContainer")
month_picker = Select(calendar.find_element_by_class_name("ui-datepicker-month"))
year_picker = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
current_date = calendar.find_element_by_class_name("ui-datepicker-current-day")
# printing out current date
month = month_picker.first_selected_option.text
year = year_picker.first_selected_option.text
print("Current return date: {day} {month} {year}".format(day=current_date.text, month=month, year=year))
# see if we have an available date in this month
try:
next_available_date = current_date.find_element_by_xpath("following::td[#data-handler='selectDay' and ancestor::div/#id='returnDateContainer']")
print("Found an available return date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
next_available_date.click()
except NoSuchElementException:
# looping over until the next available date found
while True:
# click next, if not found, select the next year
try:
calendar.find_element_by_class_name("ui-datepicker-next").click()
except NoSuchElementException:
# select next year
year = Select(calendar.find_element_by_class_name("ui-datepicker-year"))
year.select_by_visible_text(str(int(year.first_selected_option.text) + 1))
# reporting current processed month and year
month = Select(calendar.find_element_by_class_name("ui-datepicker-month")).first_selected_option.text
year = Select(calendar.find_element_by_class_name("ui-datepicker-year")).first_selected_option.text
print("Processing {month} {year}".format(month=month, year=year))
try:
next_available_date = calendar.find_element_by_xpath(".//td[#data-handler='selectDay']")
print("Found an available return date: {day} {month} {year}".format(day=next_available_date.text, month=month, year=year))
next_available_date.click()
break
except NoSuchElementException:
continue
#select adults
adults = Select(driver.find_element_by_id("adults-number"))
adults.select_by_visible_text("2")
#select children
children = Select(driver.find_element_by_id("children-number"))
children.select_by_visible_text("2")
#children ages
child_one = Select(driver.find_element_by_id("childSelect1"))
child_one.select_by_visible_text("4")
child_two = Select(driver.find_element_by_id("childSelect2"))
child_two.select_by_visible_text("6")
confirm = driver.find_element_by_link_text("Confirm")
confirm.click()
#select infants
infants = Select(driver.find_element_by_id("infants-number"))
infants.select_by_visible_text("1")
#search flights
search_flight = driver.find_element_by_id("search-flights").click()
# get the outbound date
outbound = wait.until(EC.visibility_of_element_located((By.ID, "outboundsearchresults")))
outbound_date = select_date(outbound)
# get the inbound date
inbound = driver.find_element_by_id("inboundsearchresults")
inbound_minimum_date = outbound_date + timedelta(days=7)
inbound_date = select_date(inbound, mininum_date=inbound_minimum_date)
print(outbound_date, inbound_date)
# continue after flights selected
proceed_to_pax = driver.find_element_by_id('navigateActionNext').click()
pax_page = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_passengerList_PassengerGridView_ctl08_butAddBagsForAll")))
#select currency
currency = Select(driver.find_element_by_id("ctl00_MainContent_dynamicCurrencyDropDown"))
currency.select_by_value("1")
#Passenger details
pax_one_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_TitleDropDownList"))
pax_one_title.select_by_visible_text("Mr")
pax_one_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_ForeNameTextBox").send_keys(PAX1_FORENAME)
pax_one_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_SurNameTextBox").send_keys(PAX_SURNAME)
pax_two_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_TitleDropDownList"))
pax_two_title.select_by_visible_text("Mrs")
pax_two_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_ForeNameTextBox").send_keys(PAX2_FORENAME)
pax_two_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_SurNameTextBox").send_keys(PAX_SURNAME)
pax_three_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_TitleDropDownList"))
pax_three_title.select_by_visible_text("Mr")
pax_three_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_ForeNameTextBox").send_keys(PAX3_FORENAME)
pax_three_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_SurNameTextBox").send_keys(PAX_SURNAME)
pax_four_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_TitleDropDownList"))
pax_four_title.select_by_visible_text("Ms")
pax_four_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_ForeNameTextBox").send_keys(PAX4_FORENAME)
pax_four_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_SurNameTextBox").send_keys(PAX_SURNAME)
pax_five_title = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_TitleDropDownList"))
pax_five_title.select_by_visible_text("Mstr")
pax_five_forename = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_ForeNameTextBox").send_keys(PAX5_FORENAME)
pax_five_surname = driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_SurNameTextBox").send_keys(PAX_SURNAME)
#pax baggage
pax_one_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_baggageOutDropDown"))
pax_one_bags.select_by_value("1")
pax_two_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_baggageOutDropDown"))
pax_two_bags.select_by_value("1")
pax_three_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl04_baggageOutDropDown"))
pax_three_bags.select_by_value("1")
pax_four_bags = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl05_baggageOutDropDown"))
pax_four_bags.select_by_value("1")
pax_one_golf = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl02_GolfDropDown"))
pax_one_golf.select_by_value("1")
pax_two_bike = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl03_BikesDropDown"))
pax_two_bike.select_by_value("1")
#infant carer
infant_one_carer = Select(driver.find_element_by_id("ctl00_MainContent_passengerList_PassengerGridView_ctl06_InfantCarerDropDown"))
infant_one_carer.select_by_visible_text("Mr Dad Test")
#checkin
#online = driver.find_element_by_id("ctl00_MainContent_passengerList_checkinOnline").click()
airport = driver.find_element_by_id("ctl00_MainContent_passengerList_checkinAirport").click()
#continue to seats
continue_pax = driver.find_element_by_id("pageContinue").click()
#modal_outer = wait.until(EC.invisibility_of_element_located((By.ID, "ctl00_MainContent_PageTransitionDialog_messageWrapper")))
#continue_again = wait.until(EC.element_to_be_clickable((By.ID, "pageContinue"))).click();
seats_page = wait.until(EC.visibility_of_element_located((By.ID, "findyourseat")))
#seats selection - outbound
for outbound_passenger in driver.find_elements_by_css_selector("ol[data-flightbound='Outbound'] li[data-personid]"):
outbound_passenger.click()
#driver.find_elements_by_css_selector("ol.passengerlist li[data-personid]"):
outbound_has_infant = outbound_passenger.get_attribute("data-hasinfant")
# choose seats
if outbound_has_infant:
# select a non-selected infant seat
outbound_seat = driver.find_element_by_css_selector(".outbound .planebody a.seat.infant:not(.reserved):not(.selected)")
else:
# select a non-reserved non-selected seat
outbound_seat = driver.find_element_by_css_selector(".outbound .planebody a.seat:not(.reserved):not(.selected)")
print("Passenger: %s, choosing seat: %s" % (outbound_passenger.text.strip(), outbound_seat.get_attribute("data-seat")))
outbound_seat.click()
outbound_plan = wait.until(EC.invisibility_of_element_located((By.CLASS_NAME, "outbound")))
inbound_plan = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "inbound")))
#seats selection - inbound
for inbound_passenger in driver.find_elements_by_css_selector("ol[data-flightbound='Inbound'] li[data-personid]"):
inbound_passenger.click()
#driver.find_elements_by_css_selector("ol.passengerlist li[data-personid]"):
inbound_has_infant = inbound_passenger.get_attribute("data-hasinfant")
# choose seats
if inbound_has_infant:
# select a non-selected infant seat
inbound_seat = driver.find_element_by_css_selector(".inbound .planebody a.seat.infant:not(.reserved):not(.selected)")
else:
# select a non-reserved non-selected seat
inbound_seat = driver.find_element_by_css_selector(".inbound .planebody a.seat:not(.reserved):not(.selected)")
print("Passenger: %s, choosing seat: %s" % (inbound_passenger.text.strip(), inbound_seat.get_attribute("data-seat")))
inbound_seat.click()
# proceed to the next page (meals)
submit_seat_selection = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#AllInboundPassengersSeatedOk button.submitseatselection")))
submit_seat_selection.click()
meals = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_InFlightMeal_removeMealButton")))
#Meal details
pax_one_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown"))
pax_one_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDown")))
pax_one_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn"))
pax_one_ib_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl02_mealsDropDownIn")))
pax_two_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown"))
pax_two_ob_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDown")))
pax_two_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn"))
pax_two_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl03_mealsDropDownIn")))
pax_three_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown"))
pax_three_ob_meal.select_by_index(2)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDown")))
pax_three_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn"))
pax_three_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl04_mealsDropDownIn")))
pax_four_ob_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown"))
pax_four_ob_meal.select_by_index(0)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDown")))
pax_four_ib_meal = Select(driver.find_element_by_id("ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn"))
pax_four_ib_meal.select_by_index(1)
wait.until(EC.element_to_be_clickable((By.ID, "ctl00_MainContent_InFlightMeal_PassengerGridView_ctl05_mealsDropDownIn")))
# Select Insurance
yes_insurance = driver.find_element_by_id('ctl00_MainContent_TravelInsuranceView_insuranceRequiredYes').click()
single_trip = driver.find_element_by_xpath('//input[#id="ctl00_MainContent_TravelInsuranceView_insuranceProduct1" and not(#disabled)]').click()
driver.find_element_by_xpath('//span[#id="insurance-button-submit" and (#disabled="false")]')
confirm_insurance = driver.find_element_by_id('ctl00_MainContent_TravelInsuranceView_InsuranceSubmitButton').click()
nearly_there = wait.until(EC.invisibility_of_element_located((By.ID, "ct100_MainContent_PageTransitionDialog_messageWrapper")))
checkout_btn = wait.until(EC.element_to_be_clickable((By.NAME, "ctl00$MainContent$forwardButton"))).click()
# Proceed to Payment Page
payment_page = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_rbCreditcard")))
# Payment details
payment_method = driver.find_element_by_id('ctl00_MainContent_rbCreditcard').click()
wait.until(EC.invisibility_of_element_located((By.ID, "PleaseWaitDialog")))
name_on_card = driver.find_element_by_id("nameOnCard").send_keys(NAME_ON_CARD)
card_type = Select(driver.find_element_by_id("cardType"))
card_type.select_by_visible_text("Visa")
wait.until(EC.invisibility_of_element_located((By.ID, "PleaseWaitDialog")))
card_number = driver.find_element_by_id("cardNumber").send_keys(CARD_NUMBER)
exp_month = Select(driver.find_element_by_id("month"))
exp_month.select_by_index(1)
exp_year = Select(driver.find_element_by_id("year"))
exp_year.select_by_index(2)
security_code = driver.find_element_by_id("cardVerificationNumber").send_keys(SECURITY_CODE)
# Contact details
title = Select(driver.find_element_by_id("ctl00_MainContent_addressView_contactTitleDropDown"))
title.select_by_visible_text("Mr")
contact_first_name = driver.find_element_by_id("ctl00_MainContent_addressView_contactFirstNameTextBox").send_keys(CONTACT_FIRST_NAME)
contact_last_name = driver.find_element_by_id("ctl00_MainContent_addressView_contactLastNameTextBox").send_keys(CONTACT_LAST_NAME)
country = Select(driver.find_element_by_id("ctl00_MainContent_addressView_countryDropDown"))
country.select_by_visible_text("United Kingdom")
find_address = driver.find_element_by_id('ctl00_MainContent_addressView_CheckPostcodeButton').click()
postcode_find = wait.until(EC.visibility_of_element_located((By.ID, "ctl00_MainContent_postcodeLookupDiv")))
postcode = driver.find_element_by_id("ctl00_MainContent_ThePostCodeTextBox").send_keys(POSTCODE)
search_again = driver.find_element_by_id('FindAgainButton').click()
address_shown = wait.until(EC.visibility_of_element_located((By.XPATH, '//option')))
address_pick = Select(driver.find_element_by_id("ctl00_MainContent_PostCodeListBox"))
address_pick.select_by_value("50774613")
found_button = driver.find_element_by_id('ctl00_MainContent_FoundButton').click()
postcode_disappear = wait.until(EC.invisibility_of_element_located((By.ID, "ctl00_MainContent_postcodeLookupDiv")))
mobile_phone = driver.find_element_by_id("ctl00_MainContent_addressView_leadPhoneDestTextBox").send_keys(MOBILE_PHONE)
destination_phone = driver.find_element_by_id("ctl00_MainContent_addressView_destPhoneTextBox").send_keys(DESTINATION_PHONE)
home_phone = driver.find_element_by_id("ctl00_MainContent_addressView_leadPhoneTextBox").send_keys(HOME_PHONE)
email = driver.find_element_by_id("ctl00_MainContent_addressView_emailAddTextBox").send_keys(EMAIL)
confirm_email = driver.find_element_by_id("ctl00_MainContent_addressView_confirmEmailTextBox").send_keys(EMAIL)
news_checkbox = driver.find_element_by_id('ctl00_MainContent_newsCheckBox').click()
travel_reason = Select(driver.find_element_by_id("ctl00_MainContent_reasonForTravelDropDown"))
travel_reason.select_by_visible_text("Holiday")
first_time = driver.find_element_by_id('ctl00_MainContent_FirstTimeUserRadio_1').click()
tandc = driver.find_element_by_id('ctl00_MainContent_chkAcceptTandCs').click()
#complete_booking = driver.find_element_by_id('ctl00_MainContent_continueButton')
#complete_booking.click()
It looks like the error happens inside the Expected Condition between the is_displayed() and is_enabled() checks. The "Stale Element Reference Error" is not handled when the enabledness is checked. Let's try with a custom Expected Condition:
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException
class custom_element_to_be_clickable(object):
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
try:
element = driver.find_element(self.locator)
return element.is_displayed() and element.is_enabled()
except NoSuchElementException, StaleElementReferenceException:
return False
Use this instead of EC.element_to_be_clickable.

Categories

Resources