Как проверить текущую дату и перейти к следующей дате

У меня проблема с python, которую я не могу понять. Не уверен, что мне нужно использовать операторы if, но поскольку я новичок в python, я на самом деле не уверен, как кодировать эту небольшую проблему.

Практически у меня такая проблема. Для календаря отправления я хочу, чтобы python мог делать следующее:

  • Посмотреть «Ваша дата». Если есть рейс (неважно, дешевый или обычный), нажмите на него. Если нет, перейдите к следующей доступной дате, на которую есть рейс, и нажмите на нее.
  • Нужно будет иметь возможность перейти к следующему месяцу, если в текущем месяце нет доступной даты (у меня есть пример кода для этого).

Что касается календаря возврата, я хочу, чтобы он делал то же самое, но гарантировал, что он выбирает дату как минимум через 7 дней после выбранной даты отъезда.

Это практически мой вопрос, как это сделать?

Ниже приведен HTML-код календаря отправления (календарь возврата точно такой же, за исключением результатов входящего поиска, а не результатов исходящего поиска):

Ниже у меня есть пример кода, который работает при выборе из обычного средства выбора даты (это используется на странице перед URL-адресом), если вы хотите использовать этот шаблон и манипулировать им:

# 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

person BruceyBandit    schedule 07.02.2016    source источник


Ответы (1)


Идея состоит в том, чтобы определить повторно используемую функцию, назвав ее select_date(), которая получает "календарный" WebElement и необязательную минимальную дату. Эта функция сначала будет искать Your date в календаре, и если он там и больше минимума (если задано), щелкнет по нему и вернет дату. Если Your date нет, ищите доступные "летные" дни и, если указана минимальная дата и дата больше или равна ей, щелкните по ней и верните дату.

Рабочая реализация:

from datetime import datetime, timedelta

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


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.get("http://www.jet2.com/cheap-flights/leeds-bradford/antalya/2016-03-01/2016-04-12?adults=2&children=2&infants=1&childages=4%2c6")

wait = WebDriverWait(driver, 10)

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

driver.close()

Для указанного в вопросе URL-адреса он печатает:

Processing March 2016
Found 'Flight Date': 2016-03-28

Processing April 2016
Found 'Flight Date': 2016-04-04

2016-03-28 00:00:00 2016-04-04 00:00:00

Две даты, напечатанные в конце, — это даты отъезда и даты возвращения.

Дайте мне знать, если вам нужны какие-либо разъяснения, и надеюсь, что это поможет.

person alecxe    schedule 08.02.2016
comment
Отлично, мне нужно многому научиться за короткое время, но с вашим скриптом я могу использовать его, чтобы манипулировать другими имеющимися у меня скриптами. Позже мне придется столкнуться с еще одним препятствием, и, возможно, мне придется попросить вас о помощи позже, но в то же время большое спасибо :) - person BruceyBandit; 08.02.2016
comment
@BruceyBandit, конечно, рад видеть, что вы углубляетесь в автоматизацию тестирования. Дайте мне знать, если вам нужна дополнительная помощь. - person alecxe; 08.02.2016