Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.

L'autore dell'articolo, la cui traduzione pubblichiamo oggi, afferma che il suo obiettivo è raccontare dello sviluppo di un web scraper in Python utilizzando Selenium, che esegue la ricerca dei prezzi dei voli. Nella ricerca dei biglietti vengono utilizzate date flessibili (+- 3 giorni rispetto alle date indicate). Lo scraper salva i risultati della ricerca in un file Excel e invia un'email a chi lo ha avviato con informazioni generali su ciò che è riuscito a trovare. L'obiettivo di questo progetto è assistere i viaggiatori nella ricerca delle offerte più vantaggiose.

Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.

Se, mentre analizzi il materiale, ti sentirai perso, dai un'occhiata a questa articolo.

Cosa cercheremo?

Sei libero di utilizzare il sistema descritto qui come meglio credi. Io, ad esempio, l'ho usato per cercare weekend fuori e biglietti per la mia città natale. Se sei seriamente intenzionato a trovare biglietti vantaggiosi, puoi eseguire lo script su un server (un semplice server, a 130 rubli al mese, è più che adeguato) e farlo eseguire una o due volte al giorno. I risultati della ricerca arriveranno nella tua email. Inoltre, consiglio di configurare tutto in modo che lo script salvi un file Excel con i risultati della ricerca in una cartella Dropbox, permettendoti di visualizzare tali file da qualsiasi luogo e in qualsiasi momento.

Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.
Non ho ancora trovato tariffe errate, ma ritengo che sia possibile

Nella ricerca, come già detto, si utilizza la 'data flessibile', lo script trova offerte che rientrano in un intervallo di tre giorni dalle date specificate. Sebbene durante l'esecuzione dello script venga effettuata la ricerca di offerte solo in una direzione, non è difficile modificarlo affinché possa raccogliere dati su più direzioni di volo. Con esso è possibile persino cercare tariffe errate, e tali scoperte possono rivelarsi molto interessanti.

Perché ci serve un altro web scraper?

Quando ho iniziato a fare web scraping per la prima volta, devo ammettere che non era particolarmente interessante per me. Volevo concentrarmi su progetti di modellazione predittiva, analisi finanziaria e, forse, sull'analisi del sentiment nei testi. Ma mi sono reso conto che è davvero affascinante capire come creare un programma che raccoglie dati dai siti web. Man mano che approfondivo l'argomento, ho capito che il web scraping è il vero "motore" di Internet.

Potresti pensare che sia un'affermazione troppo audace. Ma considera che Google è iniziato con un web scraper che Larry Page ha creato utilizzando Java e Python. I robot di Google esplorano e continuano a esplorare Internet, cercando di fornire le migliori risposte agli utenti. Il web scraping ha infinite applicazioni e anche se nel campo della Data Science sei interessato a qualcos'altro, avrai comunque bisogno di competenze di scraping per ottenere i dati da analizzare.

Alcuni dei metodi utilizzati qui li ho trovati in un fantastico libro sul web scraping, che ho recentemente acquisito. Puoi trovare molti esempi semplici e idee per applicare quanto appreso. Inoltre, c'è un capitolo molto interessante sulle validazioni di reCaptcha. Per me è stata una rivelazione, poiché non sapevo che esistessero strumenti specializzati e addirittura servizi interi per risolvere problemi simili.

Ami viaggiare?!

A una semplice e piuttosto innocua domanda, portata nel titolo di questa sezione, si può spesso sentire una risposta positiva, arricchita da un paio di storie di viaggio di chi la riceve. La maggior parte di noi concorderebbe sul fatto che i viaggi sono un ottimo modo per immergersi in nuove culture e ampliare i propri orizzonti. Tuttavia, se chiedi a qualcuno se gli piace cercare voli aerei, sono certo che la risposta sarà molto meno positiva. In effetti, qui ci viene in aiuto Python.

La prima sfida che dobbiamo affrontare nella creazione di un sistema di ricerca di informazioni sui biglietti aerei sarà quella di scegliere la piattaforma adatta da cui raccogliere le informazioni. Risolvere questo problema non è stato facile, ma alla fine ho scelto il servizio Kayak. Ho provato servizi come Momondo, Skyscanner, Expedia e altri, ma i loro meccanismi di protezione dagli robot erano impenetrabili. Dopo diversi tentativi, durante i quali ho cercato di convincere i sistemi di essere umano, ho dovuto affrontare semafori, attraversamenti pedonali e biciclette. Ho deciso che Kayak era il migliore per me, anche se qui, se si caricano troppe pagine in poco tempo, scattano anche controlli. Sono riuscito a fare in modo che il bot inviasse richieste al sito con intervalli di 4-6 ore, e tutto ha funzionato bene. Ci sono occasionalmente difficoltà anche con Kayak, ma se sei tormentato dai controlli, devi affrontarli manualmente e poi far partire il bot, oppure aspettare alcune ore per farli cessare. Se necessario, puoi adattare il codice per un’altra piattaforma e se lo fai, puoi comunicarcelo nei commenti.

Se stai iniziando a conoscere il web scraping e non sai perché alcuni siti web lottano contro di esso, prima di iniziare il tuo primo progetto in questo campo, fai un favore a te stesso e cerca su Google materiale con i termini "web scraping etiquette". I tuoi esperimenti potrebbero concludersi prima di quanto pensi, se ti cimenterai nel web scraping in maniera avventata.

Inizio del lavoro

Ecco una panoramica generale di cosa succederà nel codice del nostro web scraper:

  • Importare le librerie necessarie.
  • Aprire una scheda di Google Chrome.
  • Chiamare la funzione che avvia il bot, passando le città e le date che verranno utilizzate per cercare i biglietti.
  • Questa funzione ottiene i primi risultati della ricerca, ordinati per il criterio di maggiore attrattività (best), e preme il pulsante per caricare ulteriori risultati.
  • Un'altra funzione raccoglie i dati da tutta la pagina e restituisce un frame di dati.
  • I due passaggi precedenti vengono eseguiti utilizzando i tipi di ordinamento per prezzo dei biglietti (cheap) e per velocità del volo (fastest).
  • All'utente dello script viene inviata un'email contenente un riepilogo sui prezzi dei biglietti (i biglietti più economici e il prezzo medio), mentre il frame di dati con le informazioni, ordinato secondo i tre indicatori menzionati, viene salvato in un file Excel.
  • Tutte le azioni sopra descritte vengono eseguite in un ciclo a intervalli di tempo prestabiliti.

Va notato che ogni progetto Selenium inizia con un webdriver. Io utilizzo Chromedriver, lavoro con Google Chrome, ma ci sono anche altre opzioni. Sono molto popolari anche PhantomJS e Firefox. Dopo aver scaricato il driver, è necessario posizionarlo nella cartella appropriata; in questo modo la preparazione per il suo utilizzo è completata. Nelle prime righe del nostro script viene aperta una nuova scheda di Chrome.

Tenete presente che nel mio racconto non sto cercando di aprire nuovi orizzonti nella ricerca di offerte vantaggiose per i biglietti aerei. Esistono tecniche di ricerca molto più avanzate per tali offerte. Voglio solo proporre ai lettori di questo materiale un modo semplice ma praticabile per affrontare 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

# Inserisci qui il tuo percorso per chromedriver!
chromedriver_path = 'C:/{YOUR PATH HERE}/chromedriver_win32/chromedriver.exe'

driver = webdriver.Chrome(executable_path=chromedriver_path) # Questo comando apre una finestra di Chrome
sleep(2)

All'inizio del codice si possono vedere i comandi di importazione dei pacchetti utilizzati in tutto il nostro progetto. Così, randint viene utilizzato affinché il bot 'dormisse' per un numero casuale di secondi prima di avviare una nuova operazione di ricerca. Di solito, nessun bot può funzionare senza questo. Se si esegue il codice sopra riportato, si aprirà una finestra di Chrome che il bot utilizzerà per lavorare con i siti web.

Facciamo un piccolo esperimento e apriamo in una finestra separata il sito kayak.com. Selezioniamo la città da cui intendiamo partire e la città in cui vogliamo arrivare, oltre alle date dei voli. Durante la scelta delle date, verifichiamo di utilizzare un intervallo di ±3 giorni. Ho scritto del codice tenendo conto di cosa restituisce il sito in risposta a questo tipo di richieste. Se, ad esempio, hai bisogno di cercare biglietti solo per le date specificate, è probabile che tu debba modificare il codice del bot. Mentre parlo del codice, faccio le relative spiegazioni, ma se senti di essere confuso — fai sapere.

Ora clicchiamo sul pulsante di avvio della ricerca e diamo un'occhiata al link nella barra degli indirizzi. Dovrebbe assomigliare a quel link che utilizzo nell'esempio qui sotto, dove viene dichiarata la variabile kayak, che contiene l'URL, e viene utilizzato il metodo get del webdriver. Dopo aver cliccato sul pulsante di ricerca, dovrebbero apparire i risultati nella pagina.

Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.
Quando ho usato il comando get più di due o tre volte in pochi minuti, mi è stato chiesto di completare un controllo usando reCaptcha. Questo controllo può essere superato manualmente e si possono continuare gli esperimenti fino a quando il sistema non decide di iniziare un nuovo controllo. Quando testavo lo script, ho avuto l'impressione che la prima sessione di ricerca andasse sempre senza problemi, quindi, se vuoi sperimentare con il codice, dovrai solo passare manualmente il controllo di tanto in tanto e lasciare che il codice venga eseguito, utilizzando intervalli lunghi tra le sessioni di ricerca. Inoltre, se ci si pensa, è improbabile che una persona abbia bisogno di informazioni sui prezzi dei biglietti ottenute con intervalli di 10 minuti tra le operazioni di ricerca.

Lavorare con la pagina usando XPath

Quindi, abbiamo aperto la finestra e caricato il sito. Per ottenere informazioni sui prezzi e su altri dettagli, dobbiamo utilizzare la tecnologia XPath o i selettori CSS. Ho deciso di concentrarmi su XPath e non ho sentito la necessità di utilizzare i selettori CSS, ma è certamente possibile lavorare anche in questo modo. Navigare nella pagina utilizzando XPath può rivelarsi un compito difficile, e anche se utilizzi i metodi che ho descritto in questo nell'articolo in cui venivano copiati gli identificativi corrispondenti dal codice della pagina, ho capito che in realtà non è un modo ottimale per accedere agli elementi necessari. A proposito, in questo libro si può trovare una descrizione eccellente delle basi del lavoro con le pagine utilizzando XPath e i CSS selector. Ecco come appare il metodo corrispondente del web driver.

Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.
Quindi, continuiamo il lavoro sul bot. Utilizzeremo le funzionalità del programma per cercare i biglietti più economici. Nell'immagine seguente, il codice del selettore XPath è evidenziato in rosso. Per visualizzare il codice, è necessario fare clic con il tasto destro del mouse sull'elemento della pagina che ti interessa e nell'elenco che appare selezionare l'opzione Ispeziona codice (Inspect). Questa opzione può essere attivata per diversi elementi della pagina, il cui codice verrà visualizzato e evidenziato nella finestra di visualizzazione del codice.

Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.
Visualizza codice della pagina

Per trovare conferma delle mie riflessioni sui difetti del copiare i selettori dal codice, presta attenzione alle seguenti caratteristiche.

Ecco cosa otteniamo copiando il codice:

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

Per copiare qualcosa di simile, devi fare clic con il tasto destro del mouse sulla parte di codice che ti interessa e selezionare nel menu che appare l'opzione Copy > Copy XPath.

Ecco cosa ho usato per identificare il pulsante Cheapest:

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

Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.
Comando Copy > Copy XPath

È assolutamente evidente che la seconda opzione appare molto più semplice. Con essa si cerca l'elemento a, che ha l'attributo data-code, uguale a price. Con l'uso della prima opzione, si cerca l'elemento id il cui valore è wtKI-price_aTab, mentre il percorso XPath fino all'elemento appare come /div[1]/div/div/div[1]/div/span/span. Una richiesta XPath simile alla pagina farà il suo dovere, ma solo una volta. Posso affermare sin da ora che id cambierà al successivo caricamento della pagina. La sequenza di simboli wtKI cambia dinamicamente ad ogni caricamento della pagina, il che significa che il codice in cui è utilizzato diventerà inutile dopo un nuovo caricamento della pagina. Pertanto, dedicati un po' di tempo per comprendere XPath. Queste conoscenze ti saranno di grande aiuto.

Tuttavia, va notato che copiare i selettori XPath può tornare utile quando si lavora con siti abbastanza semplici, e se ti sta bene, non c'è nulla di sbagliato in questo.

Ora pensiamo a come procedere se è necessario ottenere tutti i risultati di ricerca in più righe, all'interno di un elenco. È molto semplice. Ogni risultato si trova all'interno di un oggetto con classe resultWrapper. Il caricamento di tutti i risultati può essere eseguito in un ciclo, simile a quello che sarà mostrato di seguito.

Va notato che se hai compreso quanto detto sopra, non dovresti avere problemi a capire la maggior parte del codice che analizzeremo. Durante l'esecuzione di questo codice, a ciò di cui abbiamo bisogno (in realtà, è l'elemento che avvolge il risultato), accediamo utilizzando un certo meccanismo per specificare il percorso (XPath). Questo viene fatto per ottenere il testo dell'elemento e inserirlo in un oggetto da cui possiamo leggere i dati (inizialmente utilizziamo flight_containers, poi — flights_list).

Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.
Vengono visualizzate le prime tre righe e possiamo vedere chiaramente tutto ciò di cui abbiamo bisogno. Tuttavia, abbiamo anche modi più interessanti per ottenere informazioni. Dobbiamo prendere i dati da ogni elemento separatamente.

Al lavoro!

È più semplice scrivere una funzione per caricare risultati aggiuntivi, quindi iniziamo da lì. Vorrei massimizzare il numero di voli di cui il programma ottiene informazioni, senza suscitare sospetti nel servizio che possano portare a controlli, quindi clicco una volta sul pulsante Carica più risultati ogni volta che viene visualizzata la pagina. In questo codice, vale la pena prestare attenzione al blocco try, che ho aggiunto perché a volte il pulsante non si carica correttamente. Se anche tu ti imbatti in questo problema, commenta le chiamate a questa funzione nel codice della funzione start_kayak, che esamineremo 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 un lungo esame di questa funzione (a volte posso anche lasciarmi trasportare), siamo pronti a dichiarare una funzione che si occuperà dello scraping della pagina.

Ho già raccolto gran parte di ciò che serve, nella funzione successiva, chiamata page_scrape. A volte i dati restituiti sui passaggi del percorso si rivelano combinati, per separarli utilizzo un metodo semplice. Ad esempio, quando utilizzo variabili per la prima volta section_a_list e section_b_list. La nostra funzione restituisce un frame di dati flights_df, questo ci consente di separare i risultati ottenuti utilizzando diversi metodi di ordinamento dei dati e successivamente di unirli.

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 cercato di dare nomi alle variabili in modo che il codice fosse comprensibile. Ricordate che le variabili che iniziano con a si riferiscono alla prima fase del percorso, mentre b si riferisce alla seconda. Passiamo alla funzione successiva.

Meccanismi ausiliari

Ora abbiamo una funzione che consente di caricare risultati di ricerca aggiuntivi e una funzione per elaborare questi risultati. Questo articolo potrebbe concludersi qui, poiché queste due funzioni forniscono tutto il necessario per il web scraping delle pagine che possono essere aperte autonomamente. Ma finora non abbiamo considerato alcuni meccanismi ausiliari di cui abbiamo parlato sopra. Per esempio, si tratta del codice per inviare email e alcune altre cose. Tutto ciò può essere trovato nella funzione start_kayak, che esamineremo ora.

Per il funzionamento di questa funzione sono necessarie informazioni sulle città e sulle date. Essa, utilizzando queste informazioni, forma un link nella variabile kayak, che viene utilizzata per accedere alla pagina con i risultati della ricerca, ordinati in base alla loro migliore corrispondenza con la richiesta. Dopo la prima sessione di scraping, ci occuperemo dei prezzi presenti nella tabella, nella parte superiore della pagina. In particolare, troveremo il prezzo minimo del biglietto e il prezzo medio. Tutto questo, insieme alla previsione fornita dal sito, sarà inviato via email. Nella pagina, la tabella corrispondente dovrebbe trovarsi nell'angolo in alto a sinistra. A proposito, il lavoro con questa tabella potrebbe generare un errore durante la ricerca con date precise, poiché in tal caso la tabella non viene visualizzata nella pagina.

def start_kayak(city_from, city_to, date_start, date_end):
    """Codici delle città - sono i codici IATA!
    Formato data - YYYY-MM-DD"""
    
    kayak = ('https://www.kayak.com/flights/' + city_from + '-' + city_to +
             '/' + date_start + '-flessibile/' + date_end + '-flessibile?sort=bestflight_a')
    driver.get(kayak)
    sleep(randint(8,10))
    
    # A volte appare una finestra popup, per controllare questo e chiuderla si può utilizzare il blocco try
    try:
        xp_popup_close = '//*[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('caricamento in corso.....')
    
#     load_more()
    
    print('inizio del primo scraping.....')
    df_flights_best = page_scrape()
    df_flights_best['sort'] = 'best'
    sleep(randint(60,80))
    
    # Prendiamo il prezzo più basso dalla tabella posizionata nella parte superiore della pagina
    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('passaggio ai risultati più economici.....')
    cheap_results = '//*[contains(@data-code = "price")]'
    driver.find_element_by_xpath(cheap_results).click()
    sleep(randint(60,90))
    print('caricamento in corso.....')
    
#     load_more()
    
    print('inizio del secondo scraping.....')
    df_flights_cheap = page_scrape()
    df_flights_cheap['sort'] = 'cheap'
    sleep(randint(60,80))
    
    print('passaggio ai risultati più rapidi.....')
    quick_results = '//*[contains(@data-code = "duration")]'
    driver.find_element_by_xpath(quick_results).click()  
    sleep(randint(60,90))
    print('caricamento in corso.....')
    
#     load_more()
    
    print('inizio del terzo scraping.....')
    df_flights_fast = page_scrape()
    df_flights_fast['sort'] = 'fast'
    sleep(randint(60,80))
    
    # Salvataggio del nuovo frame in un file Excel, il cui nome riflette le città e le date
    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('df salvato.....')
    
    # Si può monitorare come la previsione fornita dal sito si confronta con la realtà
    xp_loading = '//*[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)
    
    # A volte nella variabile loading si trova questa stringa, che successivamente provoca problemi nell'invio della mail
    # Se ciò è accaduto - cambiamola in "Non sono sicuro"
    weird = '¯_(ツ)_/¯'
    if loading == weird:
        loading = 'Non sicuro'
    
    username = 'YOUREMAIL@hotmail.com'
    password = 'YOUR PASSWORD'

    server = smtplib.SMTP('smtp.outlook.com', 587)
    server.ehlo()
    server.starttls()
    server.login(username, password)
    msg = ('Subject: Flight Scrapernn
Volo più economico: {}nPrezzo medio: {}nnRaccomandazione: {}nnFine del messaggio'.format(matrix_min, matrix_avg, (loading+'n'+prediction)))
    message = MIMEMultipart()
    message['From'] = 'YOUREMAIL@hotmail.com'
    message['to'] = 'YOUROTHEREMAIL@domain.com'
    server.sendmail('YOUREMAIL@hotmail.com', 'YOUROTHEREMAIL@domain.com', msg)
    print('email inviata.....')

Ho testato questo script utilizzando un account Outlook (hotmail.com). Non l'ho verificato per la compatibilità con un account Gmail, che è un servizio di posta molto popolare, ma ci sono molte possibilità. Se utilizzi un account Hotmail, per farlo funzionare è sufficiente inserire i tuoi dati nel codice.

Se desideri capire cosa succede in singole sezioni del codice di questa funzione, puoi copiarle e sperimentare. Sperimentare con il codice è l'unico modo per comprenderlo appieno.

Sistema pronto

Ora che abbiamo fatto tutto ciò di cui abbiamo parlato, possiamo creare un semplice ciclo in cui vengono chiamate le nostre funzioni. Lo script chiede all'utente di inserire dati su città e date. Durante il test con il riavvio continuo dello script, probabilmente non vorrai inserire questi dati manualmente ogni volta, quindi per il tempo del test puoi commentare le righe corrispondenti, decommentando quelle sottostanti che contengono i dati richiesti dallo script.

city_from = input('Da quale città? ')
city_to = input('Dove andare? ')
date_start = input('Intorno a quale data di partenza vuoi cercare? Usa solo il formato YYYY-MM-DD ')
date_end = input('Quando ritorna? Usa solo il formato YYYY-MM-DD ')

# 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('l'iterazione {} è completata @ {}'.format(n, strftime("%Y%m%d-%H%M")))
    
    # Aspettiamo 4 ore
    sleep(60*60*4)
    print('sonno finito.....')

Ecco come appare l'esecuzione del test dello script.
Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.
Esecuzione del test dello script

Conclusioni

Se sei arrivato fino a questo punto, congratulazioni! Ora hai uno scraper web funzionante, anche se vedo già molti modi per migliorarlo. Ad esempio, potresti integrarlo con Twilio, in modo che invii messaggi di testo anziché email. Potresti usare un VPN o qualcos'altro per ricevere risultati da più server contemporaneamente. C'è anche un problema che si presenta periodicamente, riguardante la verifica se l'utente del sito è un essere umano, ma anche questo problema può essere risolto. In ogni caso, ora hai una base che puoi ampliare se lo desideri. Ad esempio, potresti fare in modo che il file Excel venga inviato all'utente come allegato in un'email.

Python è un aiuto nella ricerca di biglietti aerei economici per coloro che amano viaggiare.

Solo gli utenti registrati possono partecipare al sondaggio. Accedi, per favore.

Utilizzi tecnologie di web scraping?

  • No

Hanno votato 8 utenti. Si è astenuto 1 utente.

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster