Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa

Författaren till artikeln, vars översättning vi publicerar idag, säger att dess mål är att prata om utvecklingen av en webbskrapa i Python med hjälp av Selenium, som söker efter flygbiljetter. Vid sökning av biljetter används flexibla datum (+- 3 dagar i förhållande till angivna datum). Skraparen sparar sökresultaten i en Excel-fil och skickar den som körde sökningen ett mejl med en sammanfattning av vad de hittade. Målet med detta projekt är att hjälpa resenärer att hitta de bästa erbjudandena.

Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa

Om du känner dig vilsen samtidigt som du förstår materialet, ta en titt på detta artikel.

Vad letar vi efter?

Du är fri att använda systemet som beskrivs här som du vill. Till exempel använde jag den för att söka efter helgturer och biljetter till min hemstad. Om du menar allvar med att hitta lönsamma biljetter kan du köra skriptet på servern (enkelt server, för 130 rubel i månaden, är ganska lämplig för detta) och se till att det körs en eller två gånger om dagen. Sökresultat kommer att skickas till dig via e-post. Dessutom rekommenderar jag att du ställer in allt så att skriptet sparar en Excel-fil med sökresultat i en Dropbox-mapp, vilket gör att du kan se sådana filer var som helst och när som helst.

Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa
Jag har inte hittat taxor med fel än, men jag tror att det är möjligt

Vid sökning används, som redan nämnts, ett "flexibelt datum", skriptet hittar erbjudanden som ligger inom tre dagar från de angivna datumen. Även om det när man kör skriptet söker efter erbjudanden i endast en riktning, är det lätt att modifiera det så att det kan samla in data om flera flygriktningar. Med dess hjälp kan du till och med leta efter felaktiga tariffer; sådana fynd kan vara mycket intressanta.

Varför behöver du en annan webbskrapa?

När jag först började webbskrapa var jag ärligt talat inte särskilt intresserad av det. Jag ville göra fler projekt inom området prediktiv modellering, finansiell analys och, möjligen, inom området för att analysera den känslomässiga färgningen av texter. Men det visade sig att det var väldigt intressant att ta reda på hur man skapar ett program som samlar in data från webbplatser. När jag fördjupade mig i det här ämnet insåg jag att webbskrapning är Internets "motor".

Du kanske tycker att detta är ett för djärvt uttalande. Men tänk på att Google började med en webbskrapa som Larry Page skapade med Java och Python. Googles robotar har utforskat Internet och försökt ge sina användare de bästa svaren på deras frågor. Webbskrapning har oändliga användningsområden, och även om du är intresserad av något annat inom Data Science, behöver du lite skrapningskunskaper för att få den data du behöver analysera.

Jag hittade några av de tekniker som används här i en underbar boken om webbskrapning, som jag nyligen skaffat. Den innehåller många enkla exempel och idéer för praktisk tillämpning av det du har lärt dig. Dessutom finns det ett mycket intressant kapitel om att kringgå reCaptcha-kontroller. Detta kom som en nyhet för mig, eftersom jag inte ens visste att det fanns specialverktyg och till och med hela tjänster för att lösa sådana problem.

Gillar du att resa?!

På den enkla och ganska ofarliga frågan som ställs i rubriken på det här avsnittet kan du ofta höra ett positivt svar, åtföljt av ett par berättelser från resorna för personen till vilken den frågades. De flesta av oss håller med om att resor är ett bra sätt att fördjupa sig i nya kulturmiljöer och vidga sina vyer. Men om du frågar någon om de gillar att söka efter flygbiljetter är jag säker på att svaret inte blir så positivt. I själva verket kommer Python till vår hjälp här.

Den första uppgiften som vi måste lösa på vägen till att skapa ett system för att söka information om flygbiljetter kommer att vara att välja en lämplig plattform från vilken vi tar information. Att lösa detta problem var inte lätt för mig, men till slut valde jag Kajaktjänsten. Jag provade tjänsterna från Momondo, Skyscanner, Expedia och några andra, men robotskyddsmekanismerna på dessa resurser var ogenomträngliga. Efter flera försök, under vilka jag var tvungen att ta itu med trafikljus, övergångsställen och cyklar, för att försöka övertyga systemen om att jag var människa, bestämde jag mig för att kajaken var bäst lämpad för mig, trots att även om för många sidor är laddade på kort tid, och kontroller börjar också. Jag lyckades få boten att skicka förfrågningar till webbplatsen med intervaller på 4 till 6 timmar, och allt fungerade bra. Då och då uppstår svårigheter när du arbetar med Kayak, men om de börjar plåga dig med kontroller, måste du antingen hantera dem manuellt och sedan starta boten, eller vänta några timmar och kontrollerna ska sluta. Vid behov kan du enkelt anpassa koden för en annan plattform och om du gör det kan du rapportera det i kommentarerna.

Om du precis har börjat med webbskrapning och inte vet varför vissa webbplatser kämpar med det, innan du påbörjar ditt första projekt inom detta område, gör dig själv en tjänst och gör en Google-sökning på orden "web scraping etiquette" . Dina experiment kan sluta snabbare än du tror om du gör nätskrapning på ett oklokt sätt.

Komma igång

Här är en allmän översikt över vad som kommer att hända i vår webbskraparkod:

  • Importera de nödvändiga biblioteken.
  • Öppna en Google Chrome-flik.
  • Anropa en funktion som startar boten och skicka den till städer och datum som kommer att användas när du söker efter biljetter.
  • Den här funktionen tar de första sökresultaten, sorterade efter bästa, och klickar på en knapp för att ladda fler resultat.
  • En annan funktion samlar in data från hela sidan och returnerar en dataram.
  • De två föregående stegen utförs med hjälp av sorteringstyper efter biljettpris (billigt) och efter flyghastighet (snabbast).
  • Användaren av skriptet får ett e-postmeddelande med en sammanfattning av biljettpriserna (billigaste biljetterna och snittpris), och en dataram med information sorterad efter de tre ovan nämnda indikatorerna sparas som en Excel-fil.
  • Alla ovanstående åtgärder utförs i en cykel efter en viss tidsperiod.

Det bör noteras att varje Selenium-projekt börjar med en webbdrivrutin. jag använder Chromedriver, Jag arbetar med Google Chrome, men det finns andra alternativ. PhantomJS och Firefox är också populära. Efter att ha laddat ner drivrutinen måste du placera den i lämplig mapp, och detta slutför förberedelserna för dess användning. De första raderna i vårt skript öppnar en ny Chrome-flik.

Tänk på att i min berättelse försöker jag inte öppna nya horisonter för att hitta bra erbjudanden på flygbiljetter. Det finns mycket mer avancerade metoder för att söka efter sådana erbjudanden. Jag vill bara erbjuda läsare av detta material ett enkelt men praktiskt sätt att lösa detta problem.

Här är koden vi pratade om ovan.

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 början av koden kan du se paketimportkommandona som används under hela vårt projekt. Så, randint används för att få boten att "somna" i ett slumpmässigt antal sekunder innan en ny sökoperation påbörjas. Vanligtvis kan inte en enda bot klara sig utan detta. Om du kör ovanstående kod öppnas ett Chrome-fönster som boten kommer att använda för att arbeta med webbplatser.

Låt oss göra ett litet experiment och öppna webbplatsen kayak.com i ett separat fönster. Vi kommer att välja vilken stad vi ska flyga från och staden vi vill åka till, samt flygdatum. När du väljer datum, se till att intervallet +-3 dagar används. Jag skrev koden med hänsyn till vad webbplatsen producerar som svar på sådana förfrågningar. Om du till exempel behöver söka efter biljetter endast för angivna datum, så är det stor sannolikhet att du måste ändra botkoden. När jag pratar om koden ger jag lämpliga förklaringar, men om du känner dig förvirrad, låt mig veta.

Klicka nu på sökknappen och titta på länken i adressfältet. Den ska likna länken jag använder i exemplet nedan där variabeln deklareras kayak, som lagrar URL:en, och metoden används get webbdrivrutin. Efter att ha klickat på sökknappen bör resultat visas på sidan.

Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa
När jag använde kommandot get mer än två eller tre gånger inom några minuter blev jag ombedd att slutföra verifieringen med reCaptcha. Du kan klara denna kontroll manuellt och fortsätta experimentera tills systemet bestämmer sig för att köra en ny kontroll. När jag testade skriptet verkade det som att den första söksessionen alltid gick smidigt, så om du ville experimentera med koden skulle du bara periodvis behöva kontrollera manuellt och låta koden köras, med långa intervaller mellan söksessionerna. Och om du tänker på det är det osannolikt att en person behöver information om biljettpriser som tas emot med 10 minuters intervall mellan sökoperationer.

Arbeta med en sida med XPath

Så vi öppnade ett fönster och laddade sidan. För att få prissättning och annan information måste vi använda XPath-teknik eller CSS-väljare. Jag bestämde mig för att hålla mig till XPath och kände inget behov av att använda CSS-väljare, men det är fullt möjligt att arbeta på det sättet. Att navigera runt en sida med XPath kan vara knepigt, och även om du använder de tekniker som jag beskrev i detta artikel, som involverade att kopiera motsvarande identifierare från sidkoden, insåg jag att detta faktiskt inte är det optimala sättet att komma åt de nödvändiga elementen. Förresten, in detta Boken ger en utmärkt beskrivning av grunderna för att arbeta med sidor med XPath- och CSS-väljare. Så här ser motsvarande webbdrivrutinsmetod ut.

Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa
Så låt oss fortsätta arbeta med boten. Låt oss använda programmets möjligheter för att välja de billigaste biljetterna. I följande bild är XPath-väljarkoden markerad i rött. För att se koden måste du högerklicka på sidelementet du är intresserad av och välja kommandot Inspektera från menyn som visas. Detta kommando kan anropas för olika sidelement, vars kod kommer att visas och markeras i kodvisaren.

Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa
Visa sidkod

För att få bekräftelse på mitt resonemang om nackdelarna med att kopiera väljare från kod, var uppmärksam på följande funktioner.

Detta är vad du får när du kopierar koden:

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

För att kopiera något sånt här måste du högerklicka på den koddel du är intresserad av och välja kommandot Kopiera > Kopiera XPath från menyn som visas.

Här är vad jag använde för att definiera den billigaste knappen:

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

Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa
Kopiera kommando > Kopiera XPath

Det är ganska uppenbart att det andra alternativet ser mycket enklare ut. När den används söker den efter ett element a som har attributet data-code, likvärdig price. När du använder det första alternativet söks elementet id som är lika med wtKI-price_aTab, och XPath-sökvägen till elementet ser ut /div[1]/div/div/div[1]/div/span/span. En XPath-fråga som denna till en sida kommer att göra susen, men bara en gång. Det kan jag säga just nu id kommer att ändras nästa gång sidan laddas. Karaktärssekvens wtKI ändras dynamiskt varje gång sidan läses in, så koden som använder den kommer att vara värdelös efter nästa omladdning av sidan. Så ta dig tid att förstå XPath. Denna kunskap kommer att tjäna dig väl.

Det bör dock noteras att kopiering av XPath-väljare kan vara användbart när du arbetar med ganska enkla sajter, och om du är bekväm med detta är det inget fel med det.

Låt oss nu fundera på vad du ska göra om du behöver få alla sökresultat på flera rader, i en lista. Väldigt enkelt. Varje resultat är inuti ett objekt med en klass resultWrapper. Att ladda alla resultat kan göras i en slinga som liknar den som visas nedan.

Det bör noteras att om du förstår ovanstående, bör du enkelt förstå det mesta av koden som vi kommer att analysera. När den här koden körs kommer vi åt det vi behöver (i själva verket elementet som resultatet är inslaget i) med hjälp av någon form av sökvägsspecificerande mekanism (XPath). Detta görs för att få fram texten till elementet och placera den i ett objekt från vilket data kan läsas (används först flight_containers, då - flights_list).

Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa
De tre första raderna visas och vi kan tydligt se allt vi behöver. Men vi har mer intressanta sätt att få information. Vi måste ta data från varje element separat.

Börja jobba!

Det enklaste sättet att skriva en funktion är att ladda ytterligare resultat, så det är där vi börjar. Jag skulle vilja maximera antalet flygningar som programmet får information om, utan att väcka misstankar i tjänsten som leder till en inspektion, så jag klickar på knappen Ladda fler resultat en gång varje gång sidan visas. I den här koden bör du vara uppmärksam på blocket try, som jag lade till eftersom knappen ibland inte laddas ordentligt. Om du också stöter på detta, kommentera anrop till denna funktion i funktionskoden start_kayak, som vi kommer att titta på nedan.

# Загрузка большего количества результатов для того, чтобы максимизировать объём собираемых данных
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 lång analys av denna funktion (ibland kan jag ryckas med), är vi redo att deklarera en funktion som kommer att skrapa sidan.

Jag har redan samlat det mesta som behövs i följande funktion som heter page_scrape. Ibland kombineras den returnerade sökvägsdatan, så jag använder en enkel metod för att separera den. Till exempel när jag använder variabler för första gången section_a_list и section_b_list. Vår funktion returnerar en dataram flights_df, detta gör att vi kan separera resultaten som erhålls från olika datasorteringsmetoder och senare kombinera 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

Jag försökte namnge variablerna så att koden skulle vara förståelig. Kom ihåg att variabler som börjar med a tillhör den första etappen av stigen, och b - till den andra. Låt oss gå vidare till nästa funktion.

Stödmekanismer

Vi har nu en funktion som gör att vi kan ladda ytterligare sökresultat och en funktion för att bearbeta dessa resultat. Den här artikeln kunde ha slutat här, eftersom dessa två funktioner ger allt du behöver för att skrapa sidor som du kan öppna själv. Men vi har ännu inte övervägt några av de hjälpmekanismer som diskuterats ovan. Det här är till exempel koden för att skicka mejl och en del annat. Allt detta finns i funktionen start_kayak, som vi nu ska överväga.

För att den här funktionen ska fungera behöver du information om städer och datum. Med hjälp av denna information bildar den en länk i en variabel kayak, som används för att ta dig till en sida som kommer att innehålla sökresultat sorterade efter deras bästa matchning med frågan. Efter första skrappasset kommer vi att arbeta med priserna i tabellen överst på sidan. Vi hittar nämligen lägsta biljettpris och snittpris. Allt detta, tillsammans med förutsägelsen från webbplatsen, kommer att skickas via e-post. På sidan ska motsvarande tabell finnas i det övre vänstra hörnet. Att arbeta med den här tabellen kan förresten orsaka ett fel vid sökning med exakta datum, eftersom tabellen i det här fallet inte visas på sidan.

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

Jag testade det här skriptet med ett Outlook-konto (hotmail.com). Jag har inte testat att det fungerar korrekt med ett Gmail-konto, det här e-postsystemet är ganska populärt, men det finns många möjliga alternativ. Om du använder ett Hotmail-konto behöver du bara ange dina uppgifter i koden för att allt ska fungera.

Om du vill förstå exakt vad som görs i specifika avsnitt av koden för den här funktionen kan du kopiera dem och experimentera med dem. Att experimentera med koden är det enda sättet att verkligen förstå den.

Färdigt system

Nu när vi har gjort allt vi pratat om kan vi skapa en enkel loop som anropar våra funktioner. Skriptet begär data från användaren om städer och datum. När du testar med konstant omstart av skriptet är det osannolikt att du vill mata in dessa data manuellt varje gång, så motsvarande rader, för testningstillfället, kan kommenteras ut genom att avkommentera dem under dem, där de data som behövs av skriptet är hårdkodat.

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å här ser en testkörning av skriptet ut.
Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa
Testkörning av skriptet

Resultat av

Om du har kommit så långt, grattis! Du har nu en fungerande webbskrapa, även om jag redan kan se många sätt att förbättra den. Den kan till exempel integreras med Twilio så att den skickar sms istället för mejl. Du kan använda ett VPN eller något annat för att samtidigt ta emot resultat från flera servrar. Det finns också ett periodiskt problem med att kontrollera webbplatsanvändaren för att se om han är en person, men detta problem kan också lösas. Nu har du i alla fall en bas som du kan utöka om du vill. Se till exempel till att en Excel-fil skickas till användaren som en bilaga till ett e-postmeddelande.

Python - en assistent för att hitta billiga flygbiljetter för dem som älskar att resa

Endast registrerade användare kan delta i undersökningen. Logga in, Snälla du.

Använder du webbskrapningsteknik?

  • Ja

  • Ingen

8 användare röstade. 1 användare avstod från att rösta.

Källa: will.com

Lägg en kommentar