Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују

Аутор чланка, чији превод данас објављујемо, каже да је његов циљ да говори о развоју веб сцрапера у Пајтону помоћу Селена који тражи цене авио карата. Приликом тражења карата користе се флексибилни датуми (+- 3 дана у односу на наведене датуме). Сцрапер чува резултате претраге у Екцел датотеци и шаље особи која је покренула претрагу е-поруку са резимеом онога што је пронашла. Циљ овог пројекта је да помогне путницима да пронађу најбоље понуде.

Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују

Ако се током разумевања градива осећате изгубљено, погледајте ово чланак.

Шта тражимо?

Овде описани систем можете слободно користити како желите. На пример, користио сам га да тражим викенд туре и карте за свој родни град. Ако сте озбиљни у проналажењу профитабилних тикета, можете покренути скрипту на серверу (једноставно сервер, за 130 рубаља месечно, сасвим је погодан за ово) и уверите се да ради једном или два пута дневно. Резултати претраге ће вам бити послати е-поштом. Поред тога, препоручујем да све подесите тако да скрипта сачува Екцел датотеку са резултатима претраге у фасцикли Дропбок, што ће вам омогућити да такве датотеке видите са било ког места и у било које време.

Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују
Још нисам нашао тарифе са грешкама, али мислим да је могуће

Приликом претраживања, као што је већ поменуто, користи се „флексибилни датум“; скрипта проналази понуде које су у року од три дана од датих датума. Иако при покретању скрипте тражи понуде само у једном правцу, лако га је модификовати тако да може да прикупља податке о неколико праваца лета. Уз његову помоћ можете чак тражити и погрешне тарифе; такви налази могу бити веома занимљиви.

Зашто вам треба још један веб стругач?

Када сам први пут почео да крегам са веба, то ме, искрено, није посебно занимало. Желео сам да радим више пројеката у области предиктивног моделирања, финансијске анализе и, евентуално, у области анализе емоционалне обојености текстова. Али испоставило се да је било веома интересантно смислити како направити програм који прикупља податке са веб локација. Док сам се упуштао у ову тему, схватио сам да је стругање веба „мотор“ интернета.

Можда мислите да је ово превише смела изјава. Али узмите у обзир да је Гугл почео са веб стругачем који је Лари Пејџ направио користећи Јава и Питхон. Гугл роботи истражују интернет, покушавајући да својим корисницима пруже најбоље одговоре на њихова питања. Скрапинг на вебу има бескрајну употребу, па чак и ако сте заинтересовани за нешто друго у науци о подацима, требаће вам неке вештине стругања да бисте добили податке које требате да анализирате.

Пронашао сам неке од техника које се овде користе у дивном књига о веб стругању, које сам недавно набавио. Садржи много једноставних примера и идеја за практичну примену онога што сте научили. Поред тога, постоји веома занимљиво поглавље о заобилажењу реЦаптцха провера. То ми је дошла као вест, јер нисам ни знао да постоје посебни алати, па чак и читави сервиси за решавање оваквих проблема.

Да ли волиш да путујеш?!

На једноставно и прилично безазлено питање постављено у наслову ове рубрике, често се може чути позитиван одговор, пропраћен пар прича са путовања особе којој је постављено. Већина нас би се сложила да је путовање одличан начин да се уроните у нова културна окружења и проширите своје видике. Међутим, ако некога питате да ли воли да тражи авионске карте, сигуран сам да одговор неће бити тако позитиван. У ствари, Питхон нам овде долази у помоћ.

Први задатак који треба да решимо на путу стварања система за претраживање информација о авио картама биће одабир одговарајуће платформе са које ћемо преузимати информације. Решавање овог проблема ми није било лако, али сам на крају изабрао Кајак сервис. Испробао сам услуге Момонда, Скисцаннера, Екпедиа и неколико других, али механизми заштите робота на овим ресурсима су били непробојни. После неколико покушаја, током којих сам морао да се носим са семафорима, пешачким прелазима и бициклима, покушавајући да убедим системе да сам човек, одлучио сам да ми кајак највише одговара, упркос чињеници да чак и ако је превише страница учитано за кратко време, а почињу и провере. Успео сам да натерам бота да шаље захтеве сајту у интервалима од 4 до 6 сати и све је функционисало како треба. С времена на време настају потешкоће при раду са Кајаком, али ако почну да вас гњаве проверама, онда морате или да се позабавите њима ручно и затим покренете бот, или сачекајте неколико сати и провере би требало да престану. Ако је потребно, можете лако прилагодити код за другу платформу, а ако то учините, можете то пријавити у коментарима.

Ако тек почињете са писањем на вебу и не знате зашто се неке веб странице боре са тим, онда пре него што започнете свој први пројекат у овој области, учините себи услугу и претражите на Гуглу речи „етикеција веб сцрапинга“ . Ваши експерименти се могу завршити раније него што мислите ако непаметно кренете на вебу.

Први кораци

Ево општег прегледа шта ће се десити у нашем коду за стругање веба:

  • Увезите потребне библиотеке.
  • Отварање картице Гоогле Цхроме.
  • Позовите функцију која покреће бот, прослеђујући му градове и датуме који ће се користити приликом тражења карата.
  • Ова функција узима прве резултате претраге, сортиране по најбољем, и кликне на дугме да учита још резултата.
  • Друга функција прикупља податке са целе странице и враћа оквир података.
  • Два претходна корака се изводе коришћењем типова сортирања по цени карте (јефтино) и брзини лета (најбрже).
  • Кориснику скрипте се шаље мејл са резимеом цена карата (најјефтиније карте и просечне цене), а оквир података са информацијама сортираним по три горе наведена индикатора се чува као Екцел фајл.
  • Све горе наведене радње се изводе у циклусу након одређеног временског периода.

Треба напоменути да сваки Селенијум пројекат почиње са веб драјвером. ја користим Цхромедривер, радим са Гоогле Цхроме-ом, али постоје и друге опције. ПхантомЈС и Фирефок су такође популарни. Након преузимања драјвера, потребно је да га ставите у одговарајућу фасциклу и тиме се завршава припрема за његову употребу. Први редови наше скрипте отварају нову Цхроме картицу.

Имајте на уму да у својој причи не покушавам да отворим нове хоризонте за проналажење одличних понуда за авионске карте. Постоје много напредније методе тражења таквих понуда. Само желим да понудим читаоцима овог материјала једноставан, али практичан начин за решавање овог проблема.

Ево кода о коме смо горе говорили.

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)

На почетку кода можете видети команде за увоз пакета које се користе у целом нашем пројекту. Тако, randint користи се да би бот „заспао“ на насумичан број секунди пре него што започне нову операцију претраживања. Обично ни један бот не може без овога. Ако покренете горњи код, отвориће се Цхроме прозор који ће бот користити за рад са сајтовима.

Хајде да направимо мали експеримент и отворимо веб локацију каиак.цом у посебном прозору. Одабраћемо град из којег ћемо летети, град у који желимо да стигнемо, као и датуме летова. Када бирате датуме, водите рачуна да се користи распон од +-3 дана. Написао сам код узимајући у обзир шта сајт производи као одговор на такве захтеве. Ако, на пример, треба да тражите карте само за одређене датуме, онда постоји велика вероватноћа да ћете морати да измените шифру бота. Када говорим о коду, дајем одговарајућа објашњења, али ако се осећате збуњено, јавите ми.

Сада кликните на дугме за претрагу и погледајте везу у адресној траци. Требало би да буде сличан линку који користим у доњем примеру где је променљива декларисана kayak, који чува УРЛ, а метод се користи get веб драјвер. Након што кликнете на дугме за претрагу, резултати би се требали појавити на страници.

Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују
Када сам употребио команду get више од два или три пута у року од неколико минута, од мене је затражено да завршим верификацију користећи реЦаптцха. Ову проверу можете проћи ручно и наставити да експериментишете док систем не одлучи да покрене нову проверу. Када сам тестирао скрипту, чинило се да је прва сесија претраге увек ишла глатко, тако да ако желите да експериментишете са кодом, морали бисте само повремено да ручно проверавате и пустите код да се покрене, користећи дуге интервале између сесија претраге. И, ако размислите о томе, мало је вероватно да ће некој особи требати информације о ценама карата које се добијају у интервалима од 10 минута између операција претраге.

Рад са страницом користећи КСПатх

Дакле, отворили смо прозор и учитали сајт. Да бисмо добили цене и друге информације, морамо да користимо КСПатх технологију или ЦСС селекторе. Одлучио сам да се држим КСПатх-а и нисам осећао потребу да користим ЦСС селекторе, али је сасвим могуће да се ради на тај начин. Кретање по страници помоћу КСПатх-а може бити незгодно, чак и ако користите технике које сам описао у ово чланак, који је подразумевао копирање одговарајућих идентификатора из кода странице, схватио сам да то, у ствари, није оптималан начин за приступ потребним елементима. Иначе, у ово Књига пружа одличан опис основа рада са страницама помоћу КСПатх и ЦСС селектора. Овако изгледа одговарајући метод веб драјвера.

Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују
Дакле, наставимо да радимо на боту. Хајде да искористимо могућности програма да изаберемо најјефтиније карте. На следећој слици, КСПатх код селектора је истакнут црвеном бојом. Да бисте видели код, потребно је да кликнете десним тастером миша на елемент странице који вас занима и изаберете команду Инспецт из менија који се појави. Ова команда се може позвати за различите елементе странице, чији ће код бити приказан и истакнут у прегледнику кода.

Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују
Погледајте код странице

Да бисте нашли потврду мог размишљања о недостацима копирања селектора из кода, обратите пажњу на следеће карактеристике.

Ево шта добијате када копирате код:

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

Да бисте копирали нешто овако, потребно је да кликнете десним тастером миша на део кода који вас занима и из менија који се појави изаберете команду Цопи > Цопи КСПатх.

Ево шта сам користио да дефинишем најјефтиније дугме:

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

Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују
Команда за копирање > Копирај КСПатх

Сасвим је очигледно да друга опција изгледа много једноставније. Када се користи, тражи елемент а који има атрибут data-codeједнако price. Када користите прву опцију, елемент се претражује id која је једнака wtKI-price_aTab, а КСПатх путања до елемента изгледа тако /div[1]/div/div/div[1]/div/span/span. Овакав КСПатх упит за страницу ће учинити трик, али само једном. Одмах то могу рећи id ће се променити следећи пут када се страница учита. Редослед карактера wtKI мења се динамички сваки пут када се страница учита, тако да ће код који га користи бити бескористан након следећег поновног учитавања странице. Зато одвојите мало времена да разумете КСПатх. Ово знање ће вам добро послужити.

Међутим, треба напоменути да копирање КСПатх селектора може бити корисно када радите са прилично једноставним сајтовима, и ако вам ово одговара, нема ништа лоше у томе.

Хајде сада да размислимо шта да урадимо ако треба да добијете све резултате претраге у неколико редова, унутар листе. Врло једноставна. Сваки резултат је унутар објекта са класом resultWrapper. Учитавање свих резултата може се обавити у петљи сличној доле приказаној.

Треба напоменути да ако разумете горе наведено, онда би требало лако да разумете већину кода који ћемо анализирати. Док се овај код покреће, приступамо ономе што нам је потребно (у ствари, елементу у који је резултат умотан) користећи неку врсту механизма за специфицирање путање (КСПатх). Ово се ради да би се добио текст елемента и сместио у објекат из којег се подаци могу читати (прво коришћени flight_containers, онда - flights_list).

Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују
Прве три линије су приказане и јасно видимо све што нам је потребно. Међутим, имамо занимљивије начине за добијање информација. Потребно је да узмемо податке из сваког елемента посебно.

Баци се на посао!

Најлакши начин да напишете функцију је учитавање додатних резултата, па ћемо од тога почети. Желео бих да максимизирам број летова о којима програм добија информације, а да не изазивам сумњу у сервис који води до инспекције, па кликнем на дугме Учитај још резултата једном сваки пут када се страница прикаже. У овом коду треба обратити пажњу на блок try, који сам додао јер се дугме понекад не учитава како треба. Ако наиђете и на ово, коментаришите позиве овој функцији у коду функције start_kayak, који ћемо погледати у наставку.

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

Сада, након дуге анализе ове функције (понекад могу да се занесем), спремни смо да прогласимо функцију која ће остругати страницу.

Већ сам прикупио већину онога што је потребно у следећој функцији која се зове page_scrape. Понекад се враћени подаци о путањи комбинују, па користим једноставан метод да их одвојим. На пример, када први пут користим променљиве section_a_list и section_b_list. Наша функција враћа оквир података flights_df, ово нам омогућава да раздвојимо резултате добијене различитим методама сортирања података и касније их комбинујемо.

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

Покушао сам да именујем променљиве како би код био разумљив. Запамтите да променљиве почињу са a припадају првој етапи пута, и b - до другог. Пређимо на следећу функцију.

Механизми подршке

Сада имамо функцију која нам омогућава да учитамо додатне резултате претраге и функцију за обраду тих резултата. Овај чланак је могао да се заврши овде, пошто ове две функције пружају све што вам је потребно да скрапате странице које можете сами да отворите. Али још увек нисмо размотрили неке од помоћних механизама о којима смо горе говорили. На пример, ово је код за слање е-поште и неке друге ствари. Све ово се може наћи у функцији start_kayak, које ћемо сада размотрити.

Ова функција захтева информације о градовима и датумима. Користећи ове информације, он формира везу у променљивој kayak, који се користи да вас одведе на страницу која ће садржати резултате претраге сортиране према њиховом најбољем подударању са упитом. Након прве сесије сцрапинга, радићемо са ценама у табели на врху странице. Наиме, наћи ћемо минималну цену карте и просечну цену. Све ово, заједно са предвиђањем сајта, биће послато е-поштом. На страници, одговарајућа табела треба да се налази у горњем левом углу. Рад са овом табелом, иначе, може изазвати грешку при претраживању по тачним датумима, јер се у овом случају табела не приказује на страници.

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

Тестирао сам ову скрипту користећи Оутлоок налог (хотмаил.цом). Нисам тестирао да исправно ради са Гмаил налогом, овај систем е-поште је прилично популаран, али постоји много могућих опција. Ако користите Хотмаил налог, онда да би све функционисало, потребно је само да унесете своје податке у код.

Ако желите да разумете шта се тачно ради у одређеним деловима кода за ову функцију, можете их копирати и експериментисати са њима. Експериментисање са кодом је једини начин да се истински разуме.

Спреман систем

Сада када смо урадили све о чему смо причали, можемо да креирамо једноставну петљу која позива наше функције. Скрипта од корисника захтева податке о градовима и датумима. Приликом тестирања са сталним поновним покретањем скрипте, мало је вероватно да ћете хтети да ручно уносите ове податке сваки пут, тако да се одговарајући редови, за време тестирања, могу прокоментарисати декоментарисањем оних испод њих, у којима су подаци потребни за скрипта је тврдо кодирана.

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

Овако изгледа пробно покретање скрипте.
Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују
Пробно покретање скрипте

Резултати

Ако сте стигли довде, честитам! Сада имате радни веб стругач, иако већ видим много начина да га побољшам. На пример, може се интегрисати са Твилио-ом тако да шаље текстуалне поруке уместо е-поште. Можете користити ВПН или нешто друго да истовремено примате резултате са неколико сервера. Повремено се јавља и проблем са провером корисника сајта да ли је он особа, али се и овај проблем може решити. У сваком случају, сада имате базу коју можете проширити ако желите. На пример, уверите се да је Екцел датотека послата кориснику као прилог е-поруци.

Питхон - помоћник у проналажењу јефтиних авио карата за оне који воле да путују

Само регистровани корисници могу учествовати у анкети. Пријавите се, Добродошао си.

Да ли користите технологије веб-стругања?

  • Да

  • Не

Гласало је 8 корисника. 1 корисник је био уздржан.

Извор: ввв.хабр.цом

Додај коментар