Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují

Autor článku, jehož překlad dnes zveřejňujeme, říká, že jeho cílem je mluvit o vývoji webového scraperu v Pythonu pomocí Selenium, který vyhledává ceny letenek. Při vyhledávání vstupenek se používají flexibilní termíny (+- 3 dny vzhledem k uvedeným termínům). Škrabka uloží výsledky hledání do souboru aplikace Excel a pošle osobě, která hledání provedla, e-mail se shrnutím toho, co našla. Cílem tohoto projektu je pomoci cestovatelům najít ty nejlepší nabídky.

Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují

Pokud se při pochopení látky cítíte ztraceni, podívejte se na tento článek.

co hledáme?

Zde popsaný systém můžete volně používat, jak si přejete. Použil jsem ho například k hledání víkendových zájezdů a letenek do mého rodného města. Pokud to s hledáním ziskových lístků myslíte vážně, můžete skript spustit na serveru (jednoduché serveru, za 130 rublů měsíčně, je k tomu docela vhodný) a ujistěte se, že běží jednou nebo dvakrát denně. Výsledky vyhledávání vám budou zaslány e-mailem. Navíc doporučuji vše nastavit tak, aby skript ukládal excelový soubor s výsledky hledání do složky Dropbox, což vám umožní prohlížet si takové soubory odkudkoli a kdykoli.

Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují
Tarify s chybami jsem zatím nenašel, ale myslím, že to možné je

Při vyhledávání se, jak již bylo zmíněno, používá „flexibilní datum“, skript najde nabídky, které jsou do tří dnů od zadaných termínů. Přestože skript při spuštění vyhledává nabídky pouze jedním směrem, je snadné jej upravit tak, aby mohl sbírat data o více směrech letu. S jeho pomocí můžete dokonce hledat chybné tarify, takové nálezy mohou být velmi zajímavé.

Proč potřebujete další webový škrabák?

Když jsem poprvé začal s webovým scrapingem, upřímně mě to nijak zvlášť nezajímalo. Chtěl jsem dělat více projektů v oblasti prediktivního modelování, finanční analýzy a případně v oblasti analýzy emočního zabarvení textů. Ukázalo se ale, že je velmi zajímavé přijít na to, jak vytvořit program, který sbírá data z webových stránek. Když jsem se ponořil do tohoto tématu, uvědomil jsem si, že web scraping je „motorem“ internetu.

Možná si myslíte, že je to příliš odvážné tvrzení. Ale vezměte v úvahu, že Google začal s webovým škrabákem, který Larry Page vytvořil pomocí Javy a Pythonu. Roboti Google prozkoumávají internet a snaží se svým uživatelům poskytnout ty nejlepší odpovědi na jejich otázky. Web scraping má nekonečná využití, a i když vás v Data Science zajímá něco jiného, ​​budete potřebovat nějaké dovednosti scrapingu, abyste získali data, která potřebujete analyzovat.

Našel jsem některé zde použité techniky v úžasné knihu o web scraping, který jsem nedávno získal. Obsahuje mnoho jednoduchých příkladů a nápadů pro praktickou aplikaci toho, co jste se naučili. Navíc je zde velmi zajímavá kapitola o obcházení reCaptcha kontrol. To mi přišlo jako novinka, protože jsem ani nevěděl, že existují speciální nástroje a dokonce celé služby pro řešení takových problémů.

Cestuješ rád?!

Na jednoduchou a vcelku neškodnou otázku položenou v názvu této sekce můžete často slyšet kladnou odpověď, doprovázenou několika historkami z cest toho, komu byla položena. Většina z nás by souhlasila s tím, že cestování je skvělý způsob, jak se ponořit do nového kulturního prostředí a rozšířit si obzory. Pokud se však někoho zeptáte, zda má rád vyhledávání letenek, jsem si jist, že odpověď nebude tak kladná. Ve skutečnosti nám zde na pomoc přichází Python.

Prvním úkolem, který musíme na cestě k vytvoření systému pro vyhledávání informací o letenkách vyřešit, bude výběr vhodné platformy, ze které budeme informace přebírat. Řešení tohoto problému pro mě nebylo jednoduché, ale nakonec jsem zvolil službu Kajak. Vyzkoušel jsem služby Momondo, Skyscanner, Expedia a několik dalších, ale mechanismy ochrany robotů na těchto zdrojích byly neproniknutelné. Po několika pokusech, během kterých jsem se musel potýkat se semafory, přechody pro chodce a jízdními koly, snažíc se přesvědčit systémy, že jsem člověk, jsem se rozhodl, že Kajak je pro mě nejvhodnější, a to navzdory skutečnosti, že i když je načteno příliš mnoho stránek v krátké době a začínají také kontroly. Podařilo se mi, aby robot posílal požadavky na web v intervalech 4 až 6 hodin a vše fungovalo dobře. Čas od času se při práci s Kayakem vyskytnou potíže, ale pokud vás začnou otravovat kontrolami, musíte se s nimi vypořádat ručně a poté spustit robota, nebo počkat několik hodin a kontroly by se měly zastavit. V případě potřeby můžete snadno upravit kód pro jinou platformu a pokud tak učiníte, můžete to nahlásit v komentářích.

Pokud s web scraping teprve začínáte a nevíte, proč se s tím některé weby potýkají, pak než se pustíte do svého prvního projektu v této oblasti, udělejte si laskavost a vyhledejte na Googlu slova „web scraping etiquette“ . Vaše experimenty mohou skončit dříve, než si myslíte, pokud budete web škrábat nerozumně.

Začínáme

Zde je obecný přehled toho, co se stane v našem kódu webového škrabáku:

  • Importujte požadované knihovny.
  • Otevření karty Google Chrome.
  • Zavolejte funkci, která spustí robota a předá mu města a data, která budou použita při hledání lístků.
  • Tato funkce vezme první výsledky vyhledávání seřazené podle nejlepších a kliknutím na tlačítko načte další výsledky.
  • Další funkce sbírá data z celé stránky a vrací datový rámec.
  • Dva předchozí kroky se provádějí pomocí typů řazení podle ceny letenky (levné) a podle rychlosti letu (nejrychlejší).
  • Uživateli skriptu je zaslán e-mail s přehledem cen vstupenek (nejlevnější vstupenky a průměrná cena) a datový rámec s informacemi seřazenými podle tří výše uvedených ukazatelů je uložen jako soubor Excel.
  • Všechny výše uvedené akce se provádějí v cyklu po určité době.

Je třeba poznamenat, že každý projekt Selenium začíná webovým ovladačem. používám Chromedriver, pracuji s Google Chrome, ale jsou i jiné možnosti. Oblíbené jsou také PhantomJS a Firefox. Po stažení ovladače je potřeba jej umístit do příslušné složky a tím je příprava na jeho použití hotová. První řádky našeho skriptu otevírají novou kartu Chrome.

Mějte na paměti, že ve svém příběhu se nesnažím otevřít nové obzory pro hledání skvělých nabídek letenek. Existují mnohem pokročilejší způsoby vyhledávání takových nabídek. Chci jen čtenářům tohoto materiálu nabídnout jednoduchý, ale praktický způsob, jak tento problém vyřešit.

Zde je kód, o kterém jsme hovořili výše.

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)

Na začátku kódu můžete vidět příkazy pro import balíčku, které se používají v celém našem projektu. Tak, randint používá se k tomu, aby robot „usnul“ na náhodný počet sekund před zahájením nové vyhledávací operace. Obvykle se bez toho neobejde ani jeden bot. Pokud spustíte výše uvedený kód, otevře se okno Chrome, které bot použije pro práci s weby.

Udělejme si malý experiment a otevřeme web kayak.com v samostatném okně. Vybereme město, ze kterého poletíme, a město, kam se chceme dostat, a také termíny letů. Při výběru termínů dbejte na využití rozsahu +-3 dny. Napsal jsem kód s ohledem na to, co web produkuje v reakci na takové požadavky. Pokud například potřebujete hledat vstupenky pouze na zadaná data, pak je vysoká pravděpodobnost, že budete muset upravit kód bota. Když mluvím o kódu, poskytuji vhodná vysvětlení, ale pokud se cítíte zmateni, dejte mi vědět.

Nyní klikněte na tlačítko Hledat a podívejte se na odkaz v adresním řádku. Měl by být podobný odkazu, který používám v příkladu níže, kde je proměnná deklarována kayak, který ukládá adresu URL, a použije se metoda get webový ovladač. Po kliknutí na tlačítko hledat by se na stránce měly objevit výsledky.

Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují
Když jsem použil příkaz get více než dvakrát nebo třikrát během několika minut jsem byl požádán o dokončení ověření pomocí reCaptcha. Tuto kontrolu můžete projít ručně a pokračovat v experimentování, dokud se systém nerozhodne spustit novou kontrolu. Když jsem skript testoval, zdálo se, že první relace vyhledávání vždy proběhla hladce, takže pokud byste chtěli s kódem experimentovat, museli byste kód pravidelně ručně kontrolovat a nechat jej běžet s použitím dlouhých intervalů mezi relacemi vyhledávání. A pokud se nad tím zamyslíte, je nepravděpodobné, že by člověk potřeboval informace o cenách letenek, které obdrží v 10minutových intervalech mezi vyhledávacími operacemi.

Práce se stránkou pomocí XPath

Otevřeli jsme tedy okno a načetli web. Abychom získali ceny a další informace, musíme použít technologii XPath nebo selektory CSS. Rozhodl jsem se zůstat u XPath a necítil jsem potřebu používat CSS selektory, ale je docela možné, že to tak funguje. Navigace po stránce pomocí XPath může být složitá, a to i v případě, že použijete techniky, které jsem popsal v tohle článku, který zahrnoval zkopírování odpovídajících identifikátorů z kódu stránky, jsem si uvědomil, že to ve skutečnosti není optimální způsob přístupu k potřebným prvkům. Mimochodem, v tohle Kniha výborně popisuje základy práce se stránkami pomocí selektorů XPath a CSS. Takto vypadá odpovídající metoda webového ovladače.

Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují
Pokračujme tedy v práci na robotovi. Využijme možností programu pro výběr nejlevnějších letenek. Na následujícím obrázku je kód selektoru XPath zvýrazněn červeně. Chcete-li zobrazit kód, musíte kliknout pravým tlačítkem myši na prvek stránky, který vás zajímá, a ze zobrazené nabídky vybrat příkaz Prozkoumat. Tento příkaz lze volat pro různé prvky stránky, jejichž kód se zobrazí a zvýrazní v prohlížeči kódu.

Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují
Zobrazit kód stránky

Abychom našli potvrzení mých úvah o nevýhodách kopírování selektorů z kódu, věnujte pozornost následujícím funkcím.

Zkopírováním kódu získáte toto:

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

Chcete-li něco takového zkopírovat, musíte kliknout pravým tlačítkem myši na sekci kódu, která vás zajímá, a ze zobrazené nabídky vybrat příkaz Kopírovat > Kopírovat XPath.

Zde je to, co jsem použil k definování tlačítka Nejlevnější:

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

Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují
Kopírovat příkaz > Kopírovat cestu XPath

Je zcela zřejmé, že druhá možnost vypadá mnohem jednodušeji. Při použití hledá prvek a, který má atribut data-code, rovná price. Při použití první možnosti se prvek vyhledá id která se rovná wtKI-price_aTab, a cesta XPath k prvku vypadá /div[1]/div/div/div[1]/div/span/span. Dotaz XPath na stránku, jako je tento, bude stačit, ale pouze jednou. To můžu říct hned id se změní při příštím načtení stránky. Posloupnost znaků wtKI se dynamicky mění při každém načtení stránky, takže kód, který ji používá, bude po dalším načtení stránky k ničemu. Věnujte tedy nějaký čas pochopení XPath. Tyto znalosti vám dobře poslouží.

Je však třeba poznamenat, že kopírování selektorů XPath může být užitečné při práci s docela jednoduchými stránkami a pokud vám to vyhovuje, není na tom nic špatného.

Nyní se zamysleme nad tím, co dělat, pokud potřebujete získat všechny výsledky vyhledávání na několika řádcích v seznamu. Velmi jednoduché. Každý výsledek je uvnitř objektu s třídou resultWrapper. Načítání všech výsledků lze provést ve smyčce podobné té, která je zobrazena níže.

Je třeba poznamenat, že pokud rozumíte výše uvedenému, měli byste snadno porozumět většině kódu, který budeme analyzovat. Jak tento kód běží, přistupujeme k tomu, co potřebujeme (ve skutečnosti k prvku, do kterého je zabalen výsledek) pomocí nějakého mechanismu specifikujícího cestu (XPath). To se provádí za účelem získání textu prvku a jeho umístění do objektu, ze kterého lze číst data (první použití flight_containers, pak - flights_list).

Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují
Zobrazí se první tři řádky a jasně vidíme vše potřebné. Máme však zajímavější způsoby získávání informací. Musíme brát data z každého prvku zvlášť.

Jít do práce!

Nejjednodušší způsob, jak napsat funkci, je načíst další výsledky, takže začneme. Chtěl bych maximalizovat počet letů, o kterých program obdrží informace, aniž bych vyvolal podezření ve službě, která vede ke kontrole, proto při každém zobrazení stránky kliknu na tlačítko Načíst další výsledky. V tomto kódu byste měli věnovat pozornost bloku try, který jsem přidal, protože se občas tlačítko nenačte správně. Pokud se s tím také setkáte, zakomentujte volání této funkce v kódu funkce start_kayak, na který se podíváme níže.

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

Nyní, po dlouhém rozboru této funkce (občas se nechám unést), jsme připraveni deklarovat funkci, která bude stránku škrábat.

Většinu toho, co je potřeba, jsem již shromáždil v následující funkci tzv page_scrape. Někdy jsou vrácená data cesty kombinována, takže k jejich oddělení používám jednoduchou metodu. Například když poprvé použiji proměnné section_a_list и section_b_list. Naše funkce vrací datový rámec flights_df, to nám umožňuje oddělit výsledky získané z různých metod třídění dat a později je kombinovat.

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

Snažil jsem se pojmenovat proměnné tak, aby byl kód srozumitelný. Pamatujte, že proměnné začínající na a patří do první fáze cesty a b - do druhého. Přejděme k další funkci.

Podpůrné mechanismy

Nyní máme funkci, která nám umožňuje načíst další výsledky vyhledávání, a funkci pro zpracování těchto výsledků. Tento článek mohl skončit zde, protože tyto dvě funkce poskytují vše, co potřebujete k seškrábání stránek, které můžete sami otevřít. Ale ještě jsme neuvažovali o některých pomocných mechanismech diskutovaných výše. Jedná se například o kód pro odesílání e-mailů a některé další věci. To vše najdete ve funkci start_kayak, kterou nyní zvážíme.

Aby tato funkce fungovala, potřebujete informace o městech a datech. Pomocí těchto informací tvoří odkaz v proměnné kayak, který slouží k přechodu na stránku, která bude obsahovat výsledky vyhledávání seřazené podle nejlepší shody s dotazem. Po prvním scrapingu budeme pracovat s cenami v tabulce v horní části stránky. Totiž najdeme minimální cenu letenky a průměrnou cenu. To vše spolu s předpovědí vydanou webem bude zasláno e-mailem. Na stránce by měla být odpovídající tabulka v levém horním rohu. Práce s touto tabulkou mimochodem může způsobit chybu při vyhledávání pomocí přesných dat, protože v tomto případě se tabulka na stránce nezobrazuje.

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

Testoval jsem tento skript pomocí účtu Outlook (hotmail.com). Netestoval jsem, aby fungoval správně s účtem Gmail, tento e-mailový systém je poměrně populární, ale existuje mnoho možných možností. Pokud používáte účet Hotmail, pak aby vše fungovalo, stačí zadat do kódu vaše údaje.

Pokud chcete porozumět tomu, co se přesně dělá v konkrétních částech kódu pro tuto funkci, můžete je zkopírovat a experimentovat s nimi. Experimentování s kódem je jediný způsob, jak jej skutečně pochopit.

Připravený systém

Nyní, když jsme udělali vše, o čem jsme mluvili, můžeme vytvořit jednoduchou smyčku, která volá naše funkce. Skript vyžaduje od uživatele data o městech a datech. Při testování s neustálým restartováním skriptu je nepravděpodobné, že budete chtít tato data pokaždé zadávat ručně, takže odpovídající řádky po dobu testování můžete zakomentovat odkomentováním těch pod nimi, ve kterých jsou data potřebná pro skript je pevně zakódován.

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

Takto vypadá testovací běh skriptu.
Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují
Testovací běh skriptu

Výsledky

Pokud jste se dostali až sem, gratulujeme! Nyní máte funkční webový škrabák, i když už vidím mnoho způsobů, jak jej vylepšit. Může být například integrován s Twilio tak, aby místo e-mailů posílal textové zprávy. K současnému příjmu výsledků z několika serverů můžete použít VPN nebo něco jiného. Pravidelně se také objevuje problém s kontrolou uživatele webu, zda se nejedná o osobu, ale i tento problém lze vyřešit. V každém případě nyní máte základnu, kterou můžete rozšířit, pokud si přejete. Ujistěte se například, že soubor aplikace Excel je uživateli odeslán jako příloha e-mailu.

Python - pomocník při hledání levných letenek pro ty, kteří rádi cestují

Průzkumu se mohou zúčastnit pouze registrovaní uživatelé. Přihlásit se, prosím.

Používáte technologie web scraping?

  • Ano

  • Ne

Hlasovalo 8 uživatelů. 1 uživatel se zdržel hlasování.

Zdroj: www.habr.com

Přidat komentář