Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse

Forfatteren til artiklen, hvis oversættelse vi udgiver i dag, siger, at dens mål er at tale om udviklingen af ​​en webskraber i Python ved hjælp af Selenium, som søger efter flybilletpriser. Ved søgning efter billetter anvendes fleksible datoer (+- 3 dage i forhold til de angivne datoer). Skraberen gemmer søgeresultaterne i en Excel-fil og sender den person, der kørte søgningen, en e-mail med en oversigt over, hvad de fandt. Målet med dette projekt er at hjælpe rejsende med at finde de bedste tilbud.

Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse

Hvis du, mens du forstår materialet, føler dig fortabt, så tag et kig på dette artikel.

Hvad skal vi lede efter?

Du kan frit bruge det her beskrevne system, som du ønsker. For eksempel brugte jeg den til at søge efter weekendture og billetter til min hjemby. Hvis du er seriøs med at finde rentable billetter, kan du køre scriptet på serveren (simpelt server, for 130 rubler om måneden, er ret velegnet til dette), og sørg for, at det kører en eller to gange om dagen. Søgeresultater vil blive sendt til dig via e-mail. Derudover anbefaler jeg at sætte alt op, så scriptet gemmer en Excel-fil med søgeresultater i en Dropbox-mappe, som giver dig mulighed for at se sådanne filer hvor som helst og når som helst.

Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse
Jeg har endnu ikke fundet takster med fejl, men jeg tror det er muligt

Ved søgning bruges, som allerede nævnt, en "fleksibel dato", scriptet finder tilbud, der ligger inden for tre dage efter de givne datoer. Selvom det, når det kører scriptet, kun søger efter tilbud i én retning, er det nemt at ændre det, så det kan indsamle data om flere flyruter. Med dens hjælp kan du endda lede efter forkerte takster; sådanne fund kan være meget interessante.

Hvorfor har du brug for en anden webskraber?

Da jeg startede med web-skrabning, var jeg ærlig talt ikke særlig interesseret i det. Jeg ønskede at lave flere projekter inden for prædiktiv modellering, finansiel analyse og muligvis inden for analyse af teksters følelsesmæssige farvning. Men det viste sig, at det var meget interessant at finde ud af, hvordan man laver et program, der indsamler data fra hjemmesider. Da jeg dykkede ned i dette emne, indså jeg, at web-skrabning er internettets "motor".

Du synes måske, at dette er for fed en udtalelse. Men tænk på, at Google startede med en webskraber, som Larry Page oprettede ved hjælp af Java og Python. Google-robotter har udforsket internettet og forsøgt at give sine brugere de bedste svar på deres spørgsmål. Web-skrabning har uendelige anvendelsesmuligheder, og selvom du er interesseret i noget andet inden for Data Science, skal du bruge nogle skrabefærdigheder for at få de data, du skal analysere.

Jeg fandt nogle af de teknikker, der blev brugt her i en vidunderlig bogen om web-skrabning, som jeg for nylig har erhvervet. Den indeholder mange enkle eksempler og ideer til praktisk anvendelse af det, du har lært. Derudover er der et meget interessant kapitel om at omgå reCaptcha-tjek. Dette kom som en nyhed for mig, da jeg ikke engang vidste, at der var specielle værktøjer og endda hele tjenester til at løse sådanne problemer.

Kan du lide at rejse?!

På det enkle og ret harmløse spørgsmål, der stilles i titlen på dette afsnit, kan du ofte høre et positivt svar, ledsaget af et par historier fra rejserne af den person, som det blev spurgt til. De fleste af os er enige om, at rejser er en fantastisk måde at fordybe sig i nye kulturelle miljøer og udvide sin horisont. Men hvis du spørger nogen, om de kan lide at søge efter flybilletter, er jeg sikker på, at svaret ikke vil være så positivt. Faktisk kommer Python os til hjælp her.

Den første opgave, vi skal løse på vejen til at skabe et system til at søge information om flybilletter, vil være at vælge en passende platform, hvorfra vi vil tage information. At løse dette problem var ikke let for mig, men til sidst valgte jeg Kajak-tjenesten. Jeg prøvede tjenesterne fra Momondo, Skyscanner, Expedia og et par andre, men robotbeskyttelsesmekanismerne på disse ressourcer var uigennemtrængelige. Efter adskillige forsøg, hvor jeg skulle håndtere lyskryds, fodgængerfelter og cykler, forsøgte at overbevise systemerne om, at jeg var menneskelig, besluttede jeg, at kajak var bedst egnet til mig, på trods af at selv om der er indlæst for mange sider i løbet af kort tid, og kontroller begynder også. Det lykkedes mig at få botten til at sende anmodninger til webstedet med intervaller på 4 til 6 timer, og alt fungerede fint. Fra tid til anden opstår der vanskeligheder, når du arbejder med Kayak, men hvis de begynder at plage dig med checks, skal du enten håndtere dem manuelt og derefter starte botten, eller vente et par timer, og kontrollerne skulle stoppe. Hvis det er nødvendigt, kan du nemt tilpasse koden til en anden platform, og hvis du gør det, kan du rapportere det i kommentarerne.

Hvis du lige er begyndt med web-skrabning og ikke ved, hvorfor nogle hjemmesider kæmper med det, så før du starter dit første projekt på dette område, så gør dig selv en tjeneste og lav en Google-søgning på ordene "web scraping etikette" . Dine eksperimenter slutter muligvis hurtigere, end du tror, ​​hvis du uklogt laver web-skrabning.

Kom godt i gang

Her er en generel oversigt over, hvad der vil ske i vores webskraberkode:

  • Importer de nødvendige biblioteker.
  • Åbning af en Google Chrome-fane.
  • Kald en funktion, der starter botten, og giver den de byer og datoer, der vil blive brugt, når du søger efter billetter.
  • Denne funktion tager de første søgeresultater, sorteret efter bedste, og klikker på en knap for at indlæse flere resultater.
  • En anden funktion indsamler data fra hele siden og returnerer en dataramme.
  • De to foregående trin udføres ved hjælp af sorteringstyper efter billetpris (billig) og efter flyvehastighed (hurtigst).
  • Brugeren af ​​scriptet får tilsendt en mail med en oversigt over billetpriser (billigste billetter og gennemsnitspris), og en dataramme med information sorteret efter de tre ovennævnte indikatorer gemmes som en Excel-fil.
  • Alle ovennævnte handlinger udføres i en cyklus efter en specificeret tidsperiode.

Det skal bemærkes, at hvert Selenium-projekt starter med en webdriver. Jeg bruger Chromedriver, Jeg arbejder med Google Chrome, men der er andre muligheder. PhantomJS og Firefox er også populære. Efter at have downloadet driveren, skal du placere den i den relevante mappe, og dette fuldender forberedelsen til dens brug. De første linjer i vores script åbner en ny Chrome-fane.

Husk på, at jeg i min historie ikke forsøger at åbne nye horisonter for at finde gode tilbud på flybilletter. Der er meget mere avancerede metoder til at søge efter sådanne tilbud. Jeg vil blot tilbyde læsere af dette materiale en enkel, men praktisk måde at løse dette problem på.

Her er koden, vi talte om ovenfor.

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)

I begyndelsen af ​​koden kan du se de pakkeimport-kommandoer, der bruges gennem hele vores projekt. Så, randint bruges til at få botten til at "falde i søvn" i et tilfældigt antal sekunder, før du starter en ny søgeoperation. Normalt kan ikke en eneste bot undvære dette. Hvis du kører ovenstående kode, åbnes et Chrome-vindue, som botten vil bruge til at arbejde med websteder.

Lad os lave et lille eksperiment og åbne webstedet kayak.com i et separat vindue. Vi vælger den by, vi skal flyve fra, og den by, vi ønsker at komme til, samt flydatoer. Når du vælger datoer, skal du sørge for, at intervallet +-3 dage bruges. Jeg skrev koden under hensyntagen til, hvad webstedet producerer som svar på sådanne anmodninger. Hvis du for eksempel kun skal søge efter billetter på bestemte datoer, så er der stor sandsynlighed for, at du bliver nødt til at ændre botkoden. Når jeg taler om koden, giver jeg passende forklaringer, men hvis du føler dig forvirret, så lad mig det vide.

Klik nu på søgeknappen og se på linket i adresselinjen. Det skal ligne det link, jeg bruger i eksemplet nedenfor, hvor variablen er erklæret kayak, som gemmer URL'en, og metoden bruges get web driver. Når du har klikket på søgeknappen, skulle resultaterne blive vist på siden.

Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse
Da jeg brugte kommandoen get mere end to eller tre gange inden for et par minutter, blev jeg bedt om at fuldføre verifikation ved hjælp af reCaptcha. Du kan bestå denne kontrol manuelt og fortsætte med at eksperimentere, indtil systemet beslutter at køre en ny kontrol. Da jeg testede scriptet, så det ud til, at den første søgesession altid gik glat, så hvis du ville eksperimentere med koden, skulle du kun periodisk manuelt tjekke og lade koden køre, ved at bruge lange intervaller mellem søgesessionerne. Og hvis du tænker over det, er det usandsynligt, at en person har brug for information om billetpriser modtaget med 10-minutters intervaller mellem søgeoperationer.

Arbejde med en side ved hjælp af XPath

Så vi åbnede et vindue og indlæste webstedet. For at få priser og andre oplysninger skal vi bruge XPath-teknologi eller CSS-vælgere. Jeg besluttede at holde mig til XPath og følte ikke behov for at bruge CSS-vælgere, men det er meget muligt at arbejde på den måde. Det kan være vanskeligt at navigere rundt på en side ved hjælp af XPath, og selvom du bruger de teknikker, jeg beskrev i dette artikel, som involverede kopiering af de tilsvarende identifikatorer fra sidekoden, indså jeg, at dette faktisk ikke er den optimale måde at få adgang til de nødvendige elementer. Forresten, i dette Bogen giver en fremragende beskrivelse af det grundlæggende i at arbejde med sider ved hjælp af XPath- og CSS-vælgere. Sådan ser den tilsvarende webdrivermetode ud.

Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse
Så lad os fortsætte med at arbejde på botten. Lad os bruge programmets muligheder til at vælge de billigste billetter. På det følgende billede er XPath-vælgerkoden fremhævet med rødt. For at se koden skal du højreklikke på det sideelement, du er interesseret i, og vælge kommandoen Inspicer i menuen, der vises. Denne kommando kan kaldes for forskellige sideelementer, hvis kode vil blive vist og fremhævet i kodefremviseren.

Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse
Se sidekode

For at finde bekræftelse af min begrundelse om ulemperne ved at kopiere vælgere fra kode, skal du være opmærksom på følgende funktioner.

Dette er, hvad du får, når du kopierer koden:

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

For at kopiere noget som dette, skal du højreklikke på den sektion af kode, du er interesseret i, og vælge kommandoen Kopier > Kopier XPath fra menuen, der vises.

Her er hvad jeg brugte til at definere den billigste knap:

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

Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse
Kopiér kommando > Kopier XPath

Det er helt indlysende, at den anden mulighed ser meget enklere ud. Når den bruges, søger den efter et element a, der har attributten data-code, lige price. Når du bruger den første mulighed, søges elementet id som er lig med wtKI-price_aTab, og XPath-stien til elementet ser ud /div[1]/div/div/div[1]/div/span/span. En XPath-forespørgsel som denne til en side vil gøre tricket, men kun én gang. Det kan jeg sige lige nu id ændres næste gang siden indlæses. Karaktersekvens wtKI ændres dynamisk hver gang siden indlæses, så koden, der bruger den, vil være ubrugelig efter næste genindlæsning af siden. Så brug lidt tid på at forstå XPath. Denne viden vil tjene dig godt.

Det skal dog bemærkes, at kopiering af XPath-vælgere kan være nyttigt, når du arbejder med ret simple websteder, og hvis du er fortrolig med dette, er der ikke noget galt med det.

Lad os nu tænke over, hvad du skal gøre, hvis du har brug for at få alle søgeresultaterne på flere linjer, inde i en liste. Meget simpelt. Hvert resultat er inde i et objekt med en klasse resultWrapper. Indlæsning af alle resultater kan gøres i en løkke svarende til den, der er vist nedenfor.

Det skal bemærkes, at hvis du forstår ovenstående, så skal du nemt forstå det meste af koden, som vi vil analysere. Mens denne kode kører, får vi adgang til det, vi har brug for (faktisk det element, som resultatet er pakket ind i) ved hjælp af en form for sti-specificerende mekanisme (XPath). Dette gøres for at få teksten til elementet og placere det i et objekt, hvorfra data kan læses (først brugt flight_containers, derefter - flights_list).

Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse
De første tre linjer vises, og vi kan tydeligt se alt, hvad vi har brug for. Vi har dog mere interessante måder at få information på. Vi skal tage data fra hvert element separat.

Kom igang med at arbejde!

Den nemmeste måde at skrive en funktion på er at indlæse yderligere resultater, så det er der, vi starter. Jeg vil gerne maksimere antallet af flyvninger, som programmet modtager information om, uden at rejse mistanke i tjenesten, der fører til en inspektion, så jeg klikker på knappen Indlæs flere resultater én gang, hver gang siden vises. I denne kode skal du være opmærksom på blokken try, som jeg tilføjede, fordi knappen nogle gange ikke indlæses korrekt. Hvis du også støder på dette, skal du kommentere opkald til denne funktion i funktionskoden start_kayak, som vi vil se på nedenfor.

# Загрузка большего количества результатов для того, чтобы максимизировать объём собираемых данных
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

Nu, efter en lang analyse af denne funktion (nogle gange kan jeg lade mig rive med), er vi klar til at erklære en funktion, der vil skrabe siden.

Jeg har allerede samlet det meste af det, der er nødvendigt i følgende funktion kaldet page_scrape. Nogle gange kombineres de returnerede stidata, så jeg bruger en simpel metode til at adskille dem. For eksempel når jeg bruger variabler for første gang section_a_list и section_b_list. Vores funktion returnerer en dataramme flights_df, giver dette os mulighed for at adskille resultaterne opnået fra forskellige datasorteringsmetoder og senere kombinere dem.

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

Jeg forsøgte at navngive variablerne, så koden ville være forståelig. Husk at variable starter med a hører til den første etape af stien, og b - til den anden. Lad os gå videre til næste funktion.

Støttemekanismer

Vi har nu en funktion, der giver os mulighed for at indlæse yderligere søgeresultater og en funktion til at behandle disse resultater. Denne artikel kunne være endt her, da disse to funktioner giver alt, hvad du behøver for at skrabe sider, som du selv kan åbne. Men vi har endnu ikke overvejet nogle af de hjælpemekanismer, der er diskuteret ovenfor. Dette er for eksempel koden til at sende e-mails og nogle andre ting. Alt dette kan findes i funktionen start_kayak, som vi nu vil overveje.

Denne funktion kræver information om byer og datoer. Ved at bruge denne information danner den et link i en variabel kayak, som bruges til at føre dig til en side, der vil indeholde søgeresultater sorteret efter deres bedste match med forespørgslen. Efter første skrabe-session vil vi arbejde med priserne i tabellen øverst på siden. Vi finder nemlig minimumsbilletprisen og gennemsnitsprisen. Alt dette, sammen med forudsigelsen udstedt af webstedet, vil blive sendt via e-mail. På siden skal den tilsvarende tabel være i øverste venstre hjørne. Arbejde med denne tabel kan i øvrigt forårsage en fejl ved søgning med nøjagtige datoer, da tabellen i dette tilfælde ikke vises på siden.

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.....')

Jeg testede dette script ved hjælp af en Outlook-konto (hotmail.com). Jeg har ikke testet det til at fungere korrekt med en Gmail-konto, dette e-mail-system er ret populært, men der er mange muligheder. Hvis du bruger en Hotmail-konto, skal du blot indtaste dine data i koden for at alt skal fungere.

Hvis du ønsker at forstå, hvad der præcist bliver gjort i specifikke sektioner af koden til denne funktion, kan du kopiere dem og eksperimentere med dem. At eksperimentere med koden er den eneste måde at virkelig forstå den på.

Klart system

Nu hvor vi har gjort alt, hvad vi talte om, kan vi oprette en simpel løkke, der kalder vores funktioner. Scriptet anmoder om data fra brugeren om byer og datoer. Når du tester med konstant genstart af scriptet, er det usandsynligt, at du vil indtaste disse data manuelt hver gang, så de tilsvarende linjer, for testtidspunktet, kan kommenteres ud ved at fjerne kommentarerne under dem, hvori de data, der er nødvendige af scriptet er hårdkodet.

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.....')

Sådan ser en testkørsel af scriptet ud.
Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse
Testkørsel af scriptet

Resultaterne af

Hvis du er nået så langt, tillykke! Du har nu en fungerende webskraber, selvom jeg allerede kan se mange måder at forbedre den på. Den kan for eksempel integreres med Twilio, så den sender sms’er i stedet for mails. Du kan bruge en VPN eller noget andet til samtidig at modtage resultater fra flere servere. Der er også et periodisk opstået problem med at tjekke webstedsbrugeren for at se, om han er en person, men dette problem kan også løses. Under alle omstændigheder har du nu en base, som du kan udvide, hvis du ønsker det. Sørg for for eksempel, at en Excel-fil sendes til brugeren som en vedhæftet fil til en e-mail.

Python - en assistent til at finde billige flybilletter til dem, der elsker at rejse

Kun registrerede brugere kan deltage i undersøgelsen. Log ind, Vær venlig.

Bruger du web-skrabeteknologier?

  • Ja

  • Nej

8 brugere stemte. 1 bruger undlod at stemme.

Kilde: www.habr.com

Tilføj en kommentar