如何在移动到下一个下拉列表之前等待处理一个下拉列表?

时间:2016-02-14 09:46:10

标签: python python-2.7 selenium selenium-webdriver

我的selenium(python)中的下拉菜单存在问题。在此页面中,当选择下拉选项时,它将处理选择,使其他选项在该过程完成之前不可选择。我试图在我的脚本中说,等到下拉列表处理了它的选项,然后转到下一个,但它只是悬挂。如何在下一个下拉列表中等待在一个下拉菜单中处理该选项?

以下是我的尝试:

#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)

您可以访问www.jet2.com页面并加载下面的脚本以查看我所看到的内容(它位于膳食页面上,因为它是我遇到问题的膳食下拉选项)。预订座位后,当您“保留座位”信息出现时,您必须手动点击“继续”按钮,因为我仍在尝试弄清楚如何执行此操作。

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)

3 个答案:

答案 0 :(得分:2)

逻辑略有不同 - 当您从下拉列表中选择项目时,此下拉列表将被禁用,直到价格重新计算为止 - 请在选择选项后查看$("#dropdownID" ).change(function() { //You can write validate code here... alert( "Handler for .change() called." ); }); 元素上显示的disabled属性。

因此,选择一个选项并等待下拉列表可点击/启用:

select

答案 1 :(得分:0)

请使用xpath或css定位器找到该元素,然后使用index使用select下拉列表。在这种情况下,使用Fluent等即可。

答案 2 :(得分:0)

我看到两个问题: - )

第一个问题是:

//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

第二个问题是模态对话框,我们被迫手动点击&#34;继续&#34;按钮实际上似乎是iframe的一部分,你可以通过切换iframe来解决这个问题。 这是一种非常粗糙的方式,但下面的代码虽然可以进行优化(所以在上面添加以下代码&#34;用餐选择&#34;)

    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")))

经过上述更改后,脚本对我来说运行正常: - )