Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare

L'autore dell'articolo, la cui traduzione pubblichiamo oggi, afferma che il suo obiettivo è parlare dello sviluppo di un web scraper in Python utilizzando Selenium, che cerca i prezzi dei biglietti aerei. Nella ricerca dei biglietti vengono utilizzate date flessibili (+- 3 giorni rispetto alle date specificate). Il raschietto salva i risultati della ricerca in un file Excel e invia alla persona che ha eseguito la ricerca un'e-mail con un riepilogo di ciò che ha trovato. L'obiettivo di questo progetto è aiutare i viaggiatori a trovare le migliori offerte.

Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare

Se, mentre comprendi il materiale, ti senti perso, dai un'occhiata questo articolo.

Cosa stiamo cercando?

Sei libero di utilizzare il sistema qui descritto come desideri. Ad esempio, l'ho usato per cercare tour del fine settimana e biglietti per la mia città natale. Se sei seriamente intenzionato a trovare biglietti redditizi, puoi eseguire lo script sul server (semplice Server, per 130 rubli al mese, è abbastanza adatto a questo) e assicurati che funzioni una o due volte al giorno. I risultati della ricerca ti verranno inviati via email. Inoltre, ti consiglio di impostare tutto in modo che lo script salvi un file Excel con i risultati della ricerca in una cartella Dropbox, che ti permetterà di visualizzare tali file da qualsiasi luogo e in qualsiasi momento.

Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare
Non ho ancora trovato tariffe con errori, ma penso che sia possibile

Nella ricerca, come già accennato, viene utilizzata una “data flessibile”; lo script trova le offerte che si trovano entro tre giorni dalle date indicate. Sebbene durante l'esecuzione lo script cerchi le offerte in una sola direzione, è facile modificarlo in modo che possa raccogliere dati su diverse direzioni di volo. Con il suo aiuto puoi anche cercare tariffe errate, tali scoperte possono essere molto interessanti.

Perché hai bisogno di un altro raschietto web?

Quando ho iniziato a usare il web scraping, sinceramente non ne ero particolarmente interessato. Volevo realizzare più progetti nel campo della modellazione predittiva, dell'analisi finanziaria e, possibilmente, nel campo dell'analisi della colorazione emotiva dei testi. Ma si è scoperto che era molto interessante capire come creare un programma che raccogliesse dati dai siti web. Approfondendo questo argomento, mi sono reso conto che il web scraping è il "motore" di Internet.

Potresti pensare che questa sia un'affermazione troppo audace. Ma considera che Google ha iniziato con un web scraper creato da Larry Page utilizzando Java e Python. I robot di Google esplorano Internet, cercando di fornire ai propri utenti le migliori risposte alle loro domande. Il web scraping ha infiniti usi e, anche se sei interessato a qualcos'altro in Data Science, avrai bisogno di alcune competenze di scraping per ottenere i dati che devi analizzare.

Ho trovato alcune delle tecniche utilizzate qui in modo meraviglioso il libro sul web scraping, che ho acquisito di recente. Contiene molti semplici esempi e idee per l'applicazione pratica di ciò che hai imparato. Inoltre, c'è un capitolo molto interessante su come aggirare i controlli reCaptcha. Questa è stata una novità per me, perché non sapevo nemmeno che esistessero strumenti speciali e persino interi servizi per risolvere tali problemi.

Ti piace viaggiare?!

Alla domanda semplice e piuttosto innocua posta nel titolo di questa sezione, spesso si sente una risposta positiva, accompagnata da un paio di racconti di viaggio della persona a cui è stata posta. La maggior parte di noi sarebbe d'accordo sul fatto che viaggiare è un ottimo modo per immergersi in nuovi ambienti culturali e ampliare i propri orizzonti. Tuttavia, se chiedi a qualcuno se gli piace cercare i biglietti aerei, sono sicuro che la risposta non sarà così positiva. In effetti, Python viene in nostro aiuto qui.

Il primo compito che dobbiamo risolvere sulla strada per la creazione di un sistema per la ricerca di informazioni sui biglietti aerei sarà la selezione di una piattaforma adatta dalla quale prenderemo le informazioni. Risolvere questo problema non è stato facile per me, ma alla fine ho scelto il servizio Kayak. Ho provato i servizi di Momondo, Skyscanner, Expedia e pochi altri, ma i meccanismi di protezione dei robot su queste risorse erano impenetrabili. Dopo diversi tentativi, durante i quali ho dovuto occuparmi di semafori, attraversamenti pedonali e biciclette, cercando di convincere i sistemi che ero umano, ho deciso che Kayak era più adatto a me, nonostante anche se vengano caricate troppe pagine in breve tempo iniziano anche i controlli. Sono riuscito a fare in modo che il bot inviasse richieste al sito a intervalli da 4 a 6 ore e tutto ha funzionato bene. Di tanto in tanto, sorgono difficoltà quando lavori con Kayak, ma se iniziano a tormentarti con i controlli, devi gestirli manualmente e quindi avviare il bot, oppure attendere qualche ora e i controlli dovrebbero interrompersi. Se necessario puoi adattare facilmente il codice per un'altra piattaforma e, se lo fai, puoi segnalarlo nei commenti.

Se hai appena iniziato con il web scraping e non sai perché alcuni siti web hanno problemi con esso, prima di iniziare il tuo primo progetto in quest'area, fatti un favore e fai una ricerca su Google con le parole "web scraping etiquette" . I tuoi esperimenti potrebbero terminare prima di quanto pensi se esegui il web scraping in modo imprudente.

Guida introduttiva

Ecco una panoramica generale di ciò che accadrà nel nostro codice web scraper:

  • Importa le librerie richieste.
  • Apertura di una scheda di Google Chrome.
  • Chiama una funzione che avvia il bot, passandogli le città e le date che verranno utilizzate durante la ricerca dei biglietti.
  • Questa funzione prende i primi risultati della ricerca, ordinati in base ai migliori, e fa clic su un pulsante per caricare più risultati.
  • Un'altra funzione raccoglie dati dall'intera pagina e restituisce un frame di dati.
  • I due passaggi precedenti vengono eseguiti utilizzando i tipi di ordinamento per prezzo del biglietto (economico) e per velocità del volo (più veloce).
  • All'utente dello script viene inviata un'e-mail contenente un riepilogo dei prezzi dei biglietti (biglietti più economici e prezzo medio) e un frame di dati con le informazioni ordinate in base ai tre indicatori sopra menzionati viene salvato come file Excel.
  • Tutte le azioni di cui sopra vengono eseguite in un ciclo dopo un periodo di tempo specificato.

Va notato che ogni progetto Selenium inizia con un driver web. Io uso Driver Chrome, Lavoro con Google Chrome, ma ci sono altre opzioni. Anche PhantomJS e Firefox sono popolari. Dopo aver scaricato il driver, è necessario inserirlo nella cartella appropriata e questo completa la preparazione per il suo utilizzo. Le prime righe del nostro script aprono una nuova scheda Chrome.

Tieni presente che nella mia storia non sto cercando di aprire nuovi orizzonti per trovare ottimi affari sui biglietti aerei. Esistono metodi molto più avanzati per cercare tali offerte. Voglio solo offrire ai lettori di questo materiale un modo semplice ma pratico per risolvere questo problema.

Ecco il codice di cui abbiamo parlato sopra.

from time import sleep, strftime
from random import randint
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import smtplib
from email.mime.multipart import MIMEMultipart

# Используйте тут ваш путь к chromedriver!
chromedriver_path = 'C:/{YOUR PATH HERE}/chromedriver_win32/chromedriver.exe'

driver = webdriver.Chrome(executable_path=chromedriver_path) # Этой командой открывается окно Chrome
sleep(2)

All'inizio del codice puoi vedere i comandi di importazione dei pacchetti utilizzati in tutto il nostro progetto. COSÌ, randint utilizzato per far "addormentare" il bot per un numero casuale di secondi prima di avviare una nuova operazione di ricerca. Di solito, nessun bot può farne a meno. Se esegui il codice sopra, si aprirà una finestra di Chrome, che il bot utilizzerà per lavorare con i siti.

Facciamo un piccolo esperimento e apriamo il sito kayak.com in una finestra separata. Selezioneremo la città da cui voleremo e la città in cui vogliamo arrivare, nonché le date del volo. Quando si scelgono le date, assicurarsi che venga utilizzato l'intervallo +-3 giorni. Ho scritto il codice tenendo conto di ciò che il sito produce in risposta a tali richieste. Se, ad esempio, devi cercare i biglietti solo per le date specificate, è molto probabile che dovrai modificare il codice del bot. Quando parlo del codice fornisco le opportune spiegazioni, ma se ti senti confuso fammelo sapere.

Ora fai clic sul pulsante di ricerca e guarda il collegamento nella barra degli indirizzi. Dovrebbe essere simile al collegamento che utilizzo nell'esempio seguente in cui è dichiarata la variabile kayak, che memorizza l'URL e viene utilizzato il metodo get driver web. Dopo aver fatto clic sul pulsante di ricerca, i risultati dovrebbero apparire sulla pagina.

Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare
Quando ho usato il comando get più di due o tre volte in pochi minuti mi è stato chiesto di completare la verifica utilizzando reCaptcha. Puoi superare questo controllo manualmente e continuare a sperimentare finché il sistema non decide di eseguire un nuovo controllo. Quando ho testato lo script, sembrava che la prima sessione di ricerca fosse sempre andata bene, quindi se volessi sperimentare il codice, avresti solo dovuto controllare periodicamente manualmente e lasciare eseguire il codice, utilizzando lunghi intervalli tra le sessioni di ricerca. E, se ci pensi, è improbabile che una persona abbia bisogno di informazioni sui prezzi dei biglietti ricevuti a intervalli di 10 minuti tra le operazioni di ricerca.

Lavorare con una pagina utilizzando XPath

Quindi, abbiamo aperto una finestra e caricato il sito. Per ottenere prezzi e altre informazioni, dobbiamo utilizzare la tecnologia XPath o i selettori CSS. Ho deciso di restare con XPath e non ho sentito il bisogno di utilizzare selettori CSS, ma è del tutto possibile lavorare in questo modo. Navigare all'interno di una pagina usando XPath può essere complicato, e anche se usi le tecniche che ho descritto in questo articolo, che prevedeva la copia degli identificatori corrispondenti dal codice della pagina, mi sono reso conto che questo, in realtà, non è il modo ottimale per accedere agli elementi necessari. A proposito, dentro questo Il libro fornisce un'eccellente descrizione delle basi per lavorare con le pagine utilizzando i selettori XPath e CSS. Ecco come appare il metodo del driver web corrispondente.

Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare
Quindi, continuiamo a lavorare sul bot. Usiamo le capacità del programma per selezionare i biglietti più economici. Nell'immagine seguente, il codice del selettore XPath è evidenziato in rosso. Per poter visualizzare il codice è necessario cliccare con il tasto destro del mouse sull'elemento della pagina che ci interessa e selezionare il comando Ispeziona dal menu che compare. Questo comando può essere richiamato per diversi elementi della pagina, il cui codice verrà visualizzato ed evidenziato nel visualizzatore di codice.

Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare
Visualizza il codice della pagina

Per trovare conferma del mio ragionamento sugli svantaggi della copia dei selettori dal codice, prestare attenzione alle seguenti funzionalità.

Questo è ciò che ottieni quando copi il codice:

//*[@id="wtKI-price_aTab"]/div[1]/div/div/div[1]/div/span/span

Per poter copiare qualcosa di simile, devi cliccare con il tasto destro del mouse sulla sezione di codice che ti interessa e selezionare la voce Copia > Copia XPath dal menu che compare.

Ecco cosa ho usato per definire il pulsante Più economico:

cheap_results = ‘//a[@data-code = "price"]’

Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare
Copia comando > Copia XPath

È abbastanza ovvio che la seconda opzione sembra molto più semplice. Quando viene utilizzato, cerca un elemento a che abbia l'attributo data-codeuguale a price. Quando si utilizza la prima opzione, l'elemento viene cercato id che è uguale a wtKI-price_aTabe il percorso XPath dell'elemento è simile /div[1]/div/div/div[1]/div/span/span. Una query XPath come questa su una pagina funzionerà, ma solo una volta. Posso dirlo subito id cambierà la prossima volta che la pagina verrà caricata. Sequenza di caratteri wtKI cambia dinamicamente ogni volta che la pagina viene caricata, quindi il codice che lo utilizza sarà inutile dopo il successivo ricaricamento della pagina. Quindi prenditi del tempo per comprendere XPath. Questa conoscenza ti sarà utile.

Tuttavia, va notato che copiare i selettori XPath può essere utile quando si lavora con siti abbastanza semplici e, se ci si sente a proprio agio, non c'è niente di sbagliato in questo.

Ora pensiamo a cosa fare se è necessario ottenere tutti i risultati della ricerca su più righe, all'interno di un elenco. Molto semplice. Ogni risultato è all'interno di un oggetto con una classe resultWrapper. Il caricamento di tutti i risultati può essere eseguito in un ciclo simile a quello mostrato di seguito.

Va notato che se comprendi quanto sopra, dovresti comprendere facilmente la maggior parte del codice che analizzeremo. Mentre questo codice viene eseguito, accediamo a ciò di cui abbiamo bisogno (di fatto, l'elemento in cui è racchiuso il risultato) utilizzando una sorta di meccanismo di specifica del percorso (XPath). Questo viene fatto per ottenere il testo dell'elemento e inserirlo in un oggetto da cui è possibile leggere i dati (usato per primo flight_containers, poi - flights_list).

Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare
Vengono visualizzate le prime tre righe e possiamo vedere chiaramente tutto ciò di cui abbiamo bisogno. Tuttavia, abbiamo modi più interessanti per ottenere informazioni. Dobbiamo prendere i dati da ciascun elemento separatamente.

Andare al lavoro!

Il modo più semplice per scrivere una funzione è caricare risultati aggiuntivi, quindi inizieremo da lì. Vorrei massimizzare il numero di voli su cui il programma riceve informazioni, senza destare sospetti nel servizio che porta a un'ispezione, quindi clicco sul pulsante Carica altri risultati una volta ogni volta che viene visualizzata la pagina. In questo codice, dovresti prestare attenzione al blocco try, che ho aggiunto perché a volte il pulsante non si carica correttamente. Se riscontri anche questo, commenta le chiamate a questa funzione nel codice funzione start_kayak, che vedremo di seguito.

# Загрузка большего количества результатов для того, чтобы максимизировать объём собираемых данных
def load_more():
    try:
        more_results = '//a[@class = "moreButton"]'
        driver.find_element_by_xpath(more_results).click()
        # Вывод этих заметок в ходе работы программы помогает мне быстро выяснить то, чем она занята
        print('sleeping.....')
        sleep(randint(45,60))
    except:
        pass

Ora, dopo una lunga analisi di questa funzione (a volte posso lasciarmi prendere la mano), siamo pronti a dichiarare una funzione che raschierà la pagina.

Ho già raccolto la maggior parte di ciò che serve nella seguente funzione chiamata page_scrape. A volte i dati del percorso restituito vengono combinati, quindi utilizzo un metodo semplice per separarli. Ad esempio, quando utilizzo le variabili per la prima volta section_a_list и section_b_list. La nostra funzione restituisce un frame di dati flights_df, questo ci permette di separare i risultati ottenuti da diversi metodi di ordinamento dei dati e successivamente combinarli.

def page_scrape():
    """This function takes care of the scraping part"""
    
    xp_sections = '//*[@class="section duration"]'
    sections = driver.find_elements_by_xpath(xp_sections)
    sections_list = [value.text for value in sections]
    section_a_list = sections_list[::2] # так мы разделяем информацию о двух полётах
    section_b_list = sections_list[1::2]
    
    # Если вы наткнулись на reCaptcha, вам может понадобиться что-то предпринять.
    # О том, что что-то пошло не так, вы узнаете исходя из того, что вышеприведённые списки пусты
    # это выражение if позволяет завершить работу программы или сделать ещё что-нибудь
    # тут можно приостановить работу, что позволит вам пройти проверку и продолжить скрапинг
    # я использую тут SystemExit так как хочу протестировать всё с самого начала
    if section_a_list == []:
        raise SystemExit
    
    # Я буду использовать букву A для уходящих рейсов и B для прибывающих
    a_duration = []
    a_section_names = []
    for n in section_a_list:
        # Получаем время
        a_section_names.append(''.join(n.split()[2:5]))
        a_duration.append(''.join(n.split()[0:2]))
    b_duration = []
    b_section_names = []
    for n in section_b_list:
        # Получаем время
        b_section_names.append(''.join(n.split()[2:5]))
        b_duration.append(''.join(n.split()[0:2]))

    xp_dates = '//div[@class="section date"]'
    dates = driver.find_elements_by_xpath(xp_dates)
    dates_list = [value.text for value in dates]
    a_date_list = dates_list[::2]
    b_date_list = dates_list[1::2]
    # Получаем день недели
    a_day = [value.split()[0] for value in a_date_list]
    a_weekday = [value.split()[1] for value in a_date_list]
    b_day = [value.split()[0] for value in b_date_list]
    b_weekday = [value.split()[1] for value in b_date_list]
    
    # Получаем цены
    xp_prices = '//a[@class="booking-link"]/span[@class="price option-text"]'
    prices = driver.find_elements_by_xpath(xp_prices)
    prices_list = [price.text.replace('$','') for price in prices if price.text != '']
    prices_list = list(map(int, prices_list))

    # stops - это большой список, в котором первый фрагмент пути находится по чётному индексу, а второй - по нечётному
    xp_stops = '//div[@class="section stops"]/div[1]'
    stops = driver.find_elements_by_xpath(xp_stops)
    stops_list = [stop.text[0].replace('n','0') for stop in stops]
    a_stop_list = stops_list[::2]
    b_stop_list = stops_list[1::2]

    xp_stops_cities = '//div[@class="section stops"]/div[2]'
    stops_cities = driver.find_elements_by_xpath(xp_stops_cities)
    stops_cities_list = [stop.text for stop in stops_cities]
    a_stop_name_list = stops_cities_list[::2]
    b_stop_name_list = stops_cities_list[1::2]
    
    # сведения о компании-перевозчике, время отправления и прибытия для обоих рейсов
    xp_schedule = '//div[@class="section times"]'
    schedules = driver.find_elements_by_xpath(xp_schedule)
    hours_list = []
    carrier_list = []
    for schedule in schedules:
        hours_list.append(schedule.text.split('n')[0])
        carrier_list.append(schedule.text.split('n')[1])
    # разделяем сведения о времени и о перевозчиках между рейсами a и b
    a_hours = hours_list[::2]
    a_carrier = carrier_list[1::2]
    b_hours = hours_list[::2]
    b_carrier = carrier_list[1::2]

    
    cols = (['Out Day', 'Out Time', 'Out Weekday', 'Out Airline', 'Out Cities', 'Out Duration', 'Out Stops', 'Out Stop Cities',
            'Return Day', 'Return Time', 'Return Weekday', 'Return Airline', 'Return Cities', 'Return Duration', 'Return Stops', 'Return Stop Cities',
            'Price'])

    flights_df = pd.DataFrame({'Out Day': a_day,
                               'Out Weekday': a_weekday,
                               'Out Duration': a_duration,
                               'Out Cities': a_section_names,
                               'Return Day': b_day,
                               'Return Weekday': b_weekday,
                               'Return Duration': b_duration,
                               'Return Cities': b_section_names,
                               'Out Stops': a_stop_list,
                               'Out Stop Cities': a_stop_name_list,
                               'Return Stops': b_stop_list,
                               'Return Stop Cities': b_stop_name_list,
                               'Out Time': a_hours,
                               'Out Airline': a_carrier,
                               'Return Time': b_hours,
                               'Return Airline': b_carrier,                           
                               'Price': prices_list})[cols]
    
    flights_df['timestamp'] = strftime("%Y%m%d-%H%M") # время сбора данных
    return flights_df

Ho provato a nominare le variabili in modo che il codice fosse comprensibile. Ricorda che le variabili iniziano con a appartengono alla prima fase del percorso, e b - al secondo. Passiamo alla funzione successiva.

Meccanismi di supporto

Ora disponiamo di una funzione che ci consente di caricare ulteriori risultati di ricerca e di una funzione per elaborare tali risultati. Questo articolo avrebbe potuto finire qui, dato che queste due funzioni forniscono tutto il necessario per sfogliare pagine che puoi aprire da solo. Ma non abbiamo ancora considerato alcuni dei meccanismi ausiliari discussi sopra. Ad esempio, questo è il codice per l'invio di e-mail e alcune altre cose. Tutto questo lo trovate nella funzione start_kayak, che ora esamineremo.

Affinché questa funzione funzioni, sono necessarie informazioni su città e date. Utilizzando queste informazioni, forma un collegamento in una variabile kayak, che viene utilizzato per indirizzarti a una pagina che conterrà i risultati di ricerca ordinati in base alla migliore corrispondenza con la query. Dopo la prima sessione di scraping, lavoreremo con i prezzi nella tabella in alto nella pagina. Troveremo cioè il prezzo minimo del biglietto e il prezzo medio. Tutto questo, insieme al pronostico rilasciato dal sito, verrà inviato tramite email. Nella pagina, la tabella corrispondente dovrebbe trovarsi nell'angolo in alto a sinistra. Lavorare con questa tabella, tra l'altro, può causare un errore durante la ricerca utilizzando date esatte, poiché in questo caso la tabella non viene visualizzata sulla pagina.

def start_kayak(city_from, city_to, date_start, date_end):
    """City codes - it's the IATA codes!
    Date format -  YYYY-MM-DD"""
    
    kayak = ('https://www.kayak.com/flights/' + city_from + '-' + city_to +
             '/' + date_start + '-flexible/' + date_end + '-flexible?sort=bestflight_a')
    driver.get(kayak)
    sleep(randint(8,10))
    
    # иногда появляется всплывающее окно, для проверки на это и его закрытия можно воспользоваться блоком try
    try:
        xp_popup_close = '//button[contains(@id,"dialog-close") and contains(@class,"Button-No-Standard-Style close ")]'
        driver.find_elements_by_xpath(xp_popup_close)[5].click()
    except Exception as e:
        pass
    sleep(randint(60,95))
    print('loading more.....')
    
#     load_more()
    
    print('starting first scrape.....')
    df_flights_best = page_scrape()
    df_flights_best['sort'] = 'best'
    sleep(randint(60,80))
    
    # Возьмём самую низкую цену из таблицы, расположенной в верхней части страницы
    matrix = driver.find_elements_by_xpath('//*[contains(@id,"FlexMatrixCell")]')
    matrix_prices = [price.text.replace('$','') for price in matrix]
    matrix_prices = list(map(int, matrix_prices))
    matrix_min = min(matrix_prices)
    matrix_avg = sum(matrix_prices)/len(matrix_prices)
    
    print('switching to cheapest results.....')
    cheap_results = '//a[@data-code = "price"]'
    driver.find_element_by_xpath(cheap_results).click()
    sleep(randint(60,90))
    print('loading more.....')
    
#     load_more()
    
    print('starting second scrape.....')
    df_flights_cheap = page_scrape()
    df_flights_cheap['sort'] = 'cheap'
    sleep(randint(60,80))
    
    print('switching to quickest results.....')
    quick_results = '//a[@data-code = "duration"]'
    driver.find_element_by_xpath(quick_results).click()  
    sleep(randint(60,90))
    print('loading more.....')
    
#     load_more()
    
    print('starting third scrape.....')
    df_flights_fast = page_scrape()
    df_flights_fast['sort'] = 'fast'
    sleep(randint(60,80))
    
    # Сохранение нового фрейма в Excel-файл, имя которого отражает города и даты
    final_df = df_flights_cheap.append(df_flights_best).append(df_flights_fast)
    final_df.to_excel('search_backups//{}_flights_{}-{}_from_{}_to_{}.xlsx'.format(strftime("%Y%m%d-%H%M"),
                                                                                   city_from, city_to, 
                                                                                   date_start, date_end), index=False)
    print('saved df.....')
    
    # Можно следить за тем, как прогноз, выдаваемый сайтом, соотносится с реальностью
    xp_loading = '//div[contains(@id,"advice")]'
    loading = driver.find_element_by_xpath(xp_loading).text
    xp_prediction = '//span[@class="info-text"]'
    prediction = driver.find_element_by_xpath(xp_prediction).text
    print(loading+'n'+prediction)
    
    # иногда в переменной loading оказывается эта строка, которая, позже, вызывает проблемы с отправкой письма
    # если это прозошло - меняем её на "Not Sure"
    weird = '¯_(ツ)_/¯'
    if loading == weird:
        loading = 'Not sure'
    
    username = '[email protected]'
    password = 'YOUR PASSWORD'

    server = smtplib.SMTP('smtp.outlook.com', 587)
    server.ehlo()
    server.starttls()
    server.login(username, password)
    msg = ('Subject: Flight Scrapernn
Cheapest Flight: {}nAverage Price: {}nnRecommendation: {}nnEnd of message'.format(matrix_min, matrix_avg, (loading+'n'+prediction)))
    message = MIMEMultipart()
    message['From'] = '[email protected]'
    message['to'] = '[email protected]'
    server.sendmail('[email protected]', '[email protected]', msg)
    print('sent email.....')

Ho testato questo script utilizzando un account Outlook (hotmail.com). Non ho testato che funzioni correttamente con un account Gmail, questo sistema di posta elettronica è piuttosto popolare, ma ci sono molte opzioni possibili. Se utilizzi un account Hotmail, affinché tutto funzioni, devi solo inserire i tuoi dati nel codice.

Se vuoi capire cosa viene fatto esattamente in sezioni specifiche del codice per questa funzione, puoi copiarle e sperimentarle. Sperimentare con il codice è l'unico modo per capirlo veramente.

Sistema pronto

Ora che abbiamo fatto tutto quello di cui abbiamo parlato, possiamo creare un semplice ciclo che chiami le nostre funzioni. Lo script richiede dati all'utente su città e date. Durante il test con riavvio costante dello script, difficilmente vorrai inserire manualmente questi dati ogni volta, quindi le righe corrispondenti, per il momento del test, possono essere commentate decommentando quelle sottostanti, in cui i dati necessari allo script lo script è hardcoded.

city_from = input('From which city? ')
city_to = input('Where to? ')
date_start = input('Search around which departure date? Please use YYYY-MM-DD format only ')
date_end = input('Return when? Please use YYYY-MM-DD format only ')

# city_from = 'LIS'
# city_to = 'SIN'
# date_start = '2019-08-21'
# date_end = '2019-09-07'

for n in range(0,5):
    start_kayak(city_from, city_to, date_start, date_end)
    print('iteration {} was complete @ {}'.format(n, strftime("%Y%m%d-%H%M")))
    
    # Ждём 4 часа
    sleep(60*60*4)
    print('sleep finished.....')

Ecco come appare un'esecuzione di prova dello script.
Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare
Esecuzione di prova dello script

Risultati di

Se sei arrivato fin qui, congratulazioni! Ora hai un web scraper funzionante, anche se vedo già molti modi per migliorarlo. Ad esempio, può essere integrato con Twilio in modo che invii messaggi di testo anziché e-mail. Puoi utilizzare una VPN o qualcos'altro per ricevere contemporaneamente risultati da più server. Periodicamente si verifica anche un problema nel controllare l'utente del sito per vedere se è una persona, ma anche questo problema può essere risolto. In ogni caso ora hai una base che puoi espandere se lo desideri. Ad esempio, assicurati che un file Excel venga inviato all'utente come allegato a un'e-mail.

Python: un assistente nella ricerca di biglietti aerei economici per chi ama viaggiare

Solo gli utenti registrati possono partecipare al sondaggio. AccediPer favore.

Utilizzi tecnologie di web scraping?

  • No

8 utenti hanno votato. 1 utente si è astenuto.

Fonte: habr.com

Aggiungi un commento