Python 航班价格跟踪器在几个月的屏幕上不断循环

Python flight price tracker keeps looping through months screen

提问人:Yamar Lyons 提问时间:11/14/2023 最后编辑:Yamar Lyons 更新时间:11/14/2023 访问量:37

问:

我正在使用 Selenium 在 Python 中构建一个航班价格跟踪器,但我在几个月的代码循环中遇到了一些问题。它一直按下一个箭头,但它没有选择我在程序中的日期。如果我想要的日期不在屏幕上,它应该能够去搜索特定日期。我试图抓取的网站是 Exepdia。

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
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
import time

import pandas as pd

import smtplib
from email.message import EmailMessage

import schedule

departure_flight_inputs = {'Departure': "ORD",
                           'Arrival': "LAS",
                           'Date': "June 1, 2024"}

return_flight_inputs = {'Departure': "LAS",
                        'Arrival': "ORD",
                        'Date': "June 8, 2024"}

def find_cheapest_flights(flight_info):
    PATH = R"C:\Users\theya\OneDrive\Desktop\FlightPriceTracker\chromedriver.exe"
    chrome_options = webdriver.ChromeOptions()
    driver = webdriver.Chrome(service=webdriver.ChromeService(executable_path=PATH), options=chrome_options)

    leaving_from = flight_info['Departure']
    going_to = flight_info['Arrival']
    trip_date = flight_info['Date']

 
    #Go to Expedia
    driver.get("https://expedia.com")

   
    #Click on Flights
   
    flight_xpath = "//span[normalize-space()='Flights']"
    flight_element = WebDriverWait(driver,5).until(
        EC.presence_of_element_located((By.XPATH, flight_xpath))
        )
    flight_element.click()
    time.sleep(0.2)
    
    
    #Click on One-Way. I prefer one way flights
    oneway_xpath = "//span[normalize-space()='One-way']"
    one_way_element = WebDriverWait(driver,5).until(
        EC.presence_of_element_located((By.XPATH, oneway_xpath))
        )
    one_way_element.click()
    time.sleep(0.2)


    #Part 1: Flying From, Flying To, Departure Date, Return Date
    
    #**********************  Complete Leaving From Portion  **********************
    leaving_from_xpath = "//button[@aria-label='Leaving from']"
    leaving_from_element = WebDriverWait(driver,5).until(
        EC.presence_of_element_located((By.XPATH, leaving_from_xpath))
        )
    leaving_from_element.click()
   
   # Added the input so I would be able to write orignal code only allowed it to click.
    leaving_from_input_xpath = "//input[@id='origin_select']"
    leaving_from_input = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, leaving_from_input_xpath))
        )

    leaving_from_input.clear
    leaving_from_input.send_keys(leaving_from)
    time.sleep(1)
    
    time.sleep(1) #Need this otherwise it will be too fast for the broswer
    leaving_from_input.send_keys(Keys.RETURN)
    #**********************  Complete Leaving From Portion  **********************
    
    
    
    #**********************  Complete Going To Portion  **********************
    going_to_xpath = "//button[@aria-label='Going to']"
    going_to_element = WebDriverWait(driver,5).until(
        EC.presence_of_element_located((By.XPATH, going_to_xpath))
        )
    
    going_to_element.click()
   
    going_to_input_xpath = "//input[@id='destination_select']"
    going_to_input = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, going_to_input_xpath))
        )
    
    going_to_input.clear
    going_to_input.send_keys(going_to)
    time.sleep(1)

    time.sleep(1) #Need this otherwise it will be too fast for the broswer
    going_to_input.send_keys( Keys.RETURN) #Go down on item and click on it
    #**********************  Complete Going To Portion  **********************
    
 #Find the current date. WILL arrow through too
    trip_date_xpath = '//div[@aria-label="{}"]'.format(trip_date)
    departing_date_element = ""
    while departing_date_element == "":
        try:
            departing_date_element = WebDriverWait(driver,3).until(
            EC.presence_of_element_located((By.XPATH, trip_date_xpath))
            )
            departing_date_element.click() #Click on the departure date
        except TimeoutException:
           departing_date_element=""
           next_month_xpath = "//button[@data-stid='uitk-calendar-navigation-controls-next-button']"
           driver.find_element("xpath",next_month_xpath).click()
           time.sleep(1)
    
    depart_date_done_xpath = "//button[@class='uitk-button uitk-button-medium uitk-button-has-text uitk-button-primary uitk-layout-flex-item']"
    driver.find_element("xpath",depart_date_done_xpath).click() 
 #**********************  Complete Departure Date Portion  **********************
    
    
    #**********************  Click Search  **********************
    search_button_xpath = '//button[@data-testid="submit-button"]'
    driver.find_element_by_xpath(search_button_xpath).click()
    time.sleep(15) #Need to let the page load properly
    #**********************  Click Search  **********************






    #Part 2: Setting Conditions for our flight
    
    #**********************  Check for Nonstop Flights Sorted by Lowest Price  **********************
    nonstop_flight_xpath = '//input[@id="stops-0"]'
    one_stop_flight_xpath = '//input[@id="stops-1"]'
    
    
    if len(driver.find_elements_by_xpath(nonstop_flight_xpath)) > 0:
        
        driver.find_element_by_xpath(nonstop_flight_xpath).click()
        time.sleep(5)
        
        #Check if there are available flights
        available_flights = driver.find_elements_by_xpath("//span[contains(text(),'Select and show fare information ')]")
        if len(available_flights) >  0:
            if len(available_flights) == 1: #Don't have to sort by prices here
                flights = [(item.text.split(",")[0].split('for')[-1].title(),
                            item.text.split(",")[1].title().replace("At",":"),
                            item.text.split(",")[2].title().replace("At",":"),
                            item.text.split(",")[3].title().replace("At",":")) for item in available_flights[0:5]]

            else:
                #Sort by lowest prices
                driver.find_element_by_xpath('//option[@data-opt-id="PRICE_INCREASING"]').click()
                time.sleep(5)
                flights = [(item.text.split(",")[0].split('for')[-1].title(),
                            item.text.split(",")[1].title().replace("At",":"),
                            item.text.split(",")[2].title().replace("At",":"),
                            item.text.split(",")[3].title().replace("At",":")) for item in available_flights[0:5]]
            
            
            print("Conditions satisfied for: {}:{}, {}:{}, {}:{}".format("Departure",leaving_from,
                                                             "Arrival",going_to,
                                                             "Date",trip_date))
            driver.quit()
            return flights
    else:
        print('Not all conditions could be met for the following: "{}:{}, {}:{}, {}:{}'.format("Departure",leaving_from,
                                                                                             "Arrival",going_to,
                                                                                             "Date",trip_date))
        driver.quit()
        return []
    
    

    #**********************  Check for Nonstop Flights Sorted by Lowest Price  **********************



def send_email():
    #Get return values
    departing_flights = find_cheapest_flights(departure_flight_inputs)
    return_flights = find_cheapest_flights(return_flight_inputs)

    #Put it into a dataframe to visualize this more easily
    df = pd.DataFrame(departing_flights + return_flights)
    
    if not df.empty: #Only send an email if we have actual flight info
        email = open('Your Email Here').read()
        password=open('Your Password Here').read()
        
        msg = EmailMessage()
        
        msg['Subject'] = "Python Flight Info! {} --> {}, Departing: {}, Returning: {}".format(departure_flight_inputs['Departure'], departure_flight_inputs['Arrival'], departure_flight_inputs['Date'],return_flight_inputs['Date'])
        
        msg['From'] = email
        msg['To'] = email
        
        msg.add_alternative('''\
            <!DOCTYPE html>
            <html>
                <body>
                    {}
                </body>
            </html>'''.format(df.to_html()), subtype="html")
    
            
        with smtplib.SMTP_SSL('Email server name here',465) as smtp:
            smtp.login(email,password)
            smtp.send_message(msg)
    

schedule.clear()
schedule.every(.1).minutes.do(send_email)

while True:
    schedule.run_pending()
    time.sleep(1)

我尝试制作一些新的 xPath,但没有任何作用。它只是在日历屏幕上循环,然后超时。

python selenium-webdriver 语法错误

评论


答: 暂无答案