Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri

Mwandishi wa makala hiyo, tafsiri yake tunayochapisha leo, anasema kuwa lengo lake ni kuzungumza juu ya maendeleo ya scraper ya mtandao huko Python kwa kutumia Selenium, ambayo hutafuta bei za tiketi za ndege. Wakati wa kutafuta tikiti, tarehe zinazobadilika hutumiwa (+- siku 3 zinazohusiana na tarehe maalum). Kibao huhifadhi matokeo ya utafutaji katika faili ya Excel na kutuma barua pepe kwa mtu aliyetafuta utafutaji na muhtasari wa kile walichokipata. Lengo la mradi huu ni kuwasaidia wasafiri kupata ofa bora zaidi.

Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri

Ikiwa, unapoelewa nyenzo, unahisi kupotea, angalia hii makala.

Tutatafuta nini?

Uko huru kutumia mfumo ulioelezewa hapa unavyotaka. Kwa mfano, niliitumia kutafuta ziara za wikendi na tikiti za kwenda mji wangu. Ikiwa una nia ya dhati ya kupata tikiti za faida, unaweza kuendesha hati kwenye seva (rahisi seva, kwa rubles 130 kwa mwezi, inafaa kabisa kwa hili) na hakikisha kwamba inaendesha mara moja au mbili kwa siku. Matokeo ya utafutaji yatatumwa kwako kwa barua pepe. Kwa kuongeza, ninapendekeza kuweka kila kitu ili script ihifadhi faili ya Excel na matokeo ya utafutaji kwenye folda ya Dropbox, ambayo itawawezesha kutazama faili hizo kutoka popote na wakati wowote.

Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri
Bado sijapata ushuru na makosa, lakini nadhani inawezekana

Wakati wa kutafuta, kama ilivyotajwa tayari, "tarehe inayoweza kubadilika" hutumiwa; hati hupata matoleo ambayo ni ndani ya siku tatu za tarehe zilizotolewa. Ingawa inapoendesha hati, hutafuta matoleo katika mwelekeo mmoja tu, ni rahisi kuirekebisha ili iweze kukusanya data kwenye maelekezo kadhaa ya ndege. Kwa msaada wake, unaweza hata kutafuta ushuru usio sahihi; matokeo kama haya yanaweza kuvutia sana.

Kwa nini unahitaji kifuta mtandao mwingine?

Nilipoanza kuchakachua wavuti, kwa kweli sikupendezwa nayo. Nilitaka kufanya miradi zaidi katika uwanja wa mfano wa utabiri, uchambuzi wa kifedha, na, ikiwezekana, katika uwanja wa kuchambua rangi ya kihemko ya maandishi. Lakini ikawa kwamba ilikuwa ya kuvutia sana kujua jinsi ya kuunda programu inayokusanya data kutoka kwa tovuti. Nilipoingia kwenye mada hii, niligundua kuwa uchakachuaji wa wavuti ndio "injini" ya Mtandao.

Unaweza kufikiri kwamba hii ni taarifa ya ujasiri sana. Lakini zingatia kuwa Google ilianza na kichakachua wavuti ambacho Larry Page aliunda kwa kutumia Java na Python. Roboti za Google zimekuwa zikichunguza Mtandao, zikijaribu kuwapa watumiaji wake majibu bora kwa maswali yao. Uchakachuaji wa wavuti una matumizi mengi, na hata ikiwa una nia ya kitu kingine katika Sayansi ya Data, utahitaji ujuzi wa kugema ili kupata data unayohitaji kuchanganua.

Nilipata baadhi ya mbinu zinazotumika hapa katika ajabu kitabu kuhusu uchakachuaji wa wavuti, ambao nilipata hivi majuzi. Ina mifano mingi rahisi na mawazo ya matumizi ya vitendo ya yale uliyojifunza. Kwa kuongeza, kuna sura ya kuvutia sana juu ya kupitisha ukaguzi wa reCaptcha. Hii ilikuja kama habari kwangu, kwani sikujua hata kulikuwa na zana maalum na hata huduma nzima za kutatua shida kama hizo.

Unapenda kusafiri?!

Kwa swali rahisi na lisilo na madhara lililotolewa katika kichwa cha sehemu hii, mara nyingi unaweza kusikia jibu chanya, likiambatana na hadithi kadhaa kutoka kwa safari za mtu ambaye aliulizwa. Wengi wetu tutakubali kwamba kusafiri ni njia nzuri ya kujitumbukiza katika mazingira mapya ya kitamaduni na kupanua upeo wako. Walakini, ukimuuliza mtu kama anapenda kutafuta tikiti za ndege, nina hakika kuwa jibu halitakuwa nzuri sana. Kwa kweli, Python anakuja kutusaidia hapa.

Jukumu la kwanza ambalo tunahitaji kutatua wakati wa kuunda mfumo wa kutafuta habari kwenye tikiti za ndege itakuwa kuchagua jukwaa linalofaa ambalo tutachukua habari. Kutatua tatizo hili haikuwa rahisi kwangu, lakini mwisho nilichagua huduma ya Kayak. Nilijaribu huduma za Momondo, Skyscanner, Expedia, na wengine wachache, lakini taratibu za ulinzi wa roboti kwenye rasilimali hizi hazikuweza kupenyezwa. Baada ya majaribio kadhaa, ambayo nililazimika kushughulika na taa za trafiki, vivuko vya watembea kwa miguu na baiskeli, nikijaribu kushawishi mifumo kuwa mimi ni mwanadamu, niliamua kwamba Kayak ilinifaa zaidi, licha ya ukweli kwamba hata kurasa nyingi sana zimejaa. kwa muda mfupi, na ukaguzi pia huanza. Niliweza kufanya bot kutuma maombi kwa tovuti kwa muda wa saa 4 hadi 6, na kila kitu kilifanya kazi vizuri. Mara kwa mara, shida hutokea wakati wa kufanya kazi na Kayak, lakini ikiwa wanaanza kukusumbua na hundi, basi unahitaji kukabiliana nao kwa mikono na kisha kuzindua bot, au kusubiri saa chache na ukaguzi unapaswa kuacha. Ikiwa ni lazima, unaweza kurekebisha msimbo kwa jukwaa lingine kwa urahisi, na ukifanya hivyo, unaweza kuripoti kwenye maoni.

Ikiwa ndio kwanza unaanza na uchakachuaji wa wavuti na hujui ni kwa nini tovuti zingine zinatatizika, basi kabla ya kuanza mradi wako wa kwanza katika eneo hili, jifanyie upendeleo na utafute Google kwa maneno "tabia ya kugema mtandaoni" . Majaribio yako yanaweza kuisha mapema kuliko vile unavyofikiria ikiwa utafyeka wavuti bila busara.

Anza

Hapa kuna muhtasari wa jumla wa kile kitakachotokea katika msimbo wetu wa chakavu wa wavuti:

  • Ingiza maktaba zinazohitajika.
  • Kufungua kichupo cha Google Chrome.
  • Piga simu kitendakazi kinachoanzisha roboti, ukiipitisha miji na tarehe zitakazotumika wakati wa kutafuta tikiti.
  • Chaguo hili la kukokotoa huchukua matokeo ya kwanza ya utafutaji, yaliyopangwa kwa njia bora zaidi, na kubofya kitufe ili kupakia matokeo zaidi.
  • Chaguo jingine la kukokotoa hukusanya data kutoka kwa ukurasa mzima na kurejesha fremu ya data.
  • Hatua mbili za awali zinatekelezwa kwa kutumia aina za kupanga kwa bei ya tikiti (nafuu) na kwa kasi ya ndege (haraka zaidi).
  • Mtumiaji wa hati hutumwa barua pepe iliyo na muhtasari wa bei za tikiti (tiketi za bei nafuu na bei ya wastani), na fremu ya data iliyo na maelezo yaliyopangwa kwa viashirio vitatu vilivyotajwa hapo juu huhifadhiwa kama faili ya Excel.
  • Vitendo vyote hapo juu vinafanywa kwa mzunguko baada ya muda maalum.

Ikumbukwe kwamba kila mradi wa Selenium huanza na dereva wa wavuti. natumia Chromedriver, Ninafanya kazi na Google Chrome, lakini kuna chaguzi zingine. PhantomJS na Firefox pia ni maarufu. Baada ya kupakua dereva, unahitaji kuiweka kwenye folda inayofaa, na hii inakamilisha maandalizi ya matumizi yake. Mistari ya kwanza ya hati yetu inafungua kichupo kipya cha Chrome.

Kumbuka kwamba katika hadithi yangu sijaribu kufungua upeo mpya wa kupata ofa nzuri kwenye tikiti za ndege. Kuna njia za juu zaidi za kutafuta matoleo kama haya. Ninataka tu kuwapa wasomaji wa nyenzo hii njia rahisi lakini ya vitendo ya kutatua tatizo hili.

Hapa kuna nambari tuliyozungumza hapo juu.

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)

Mwanzoni mwa msimbo unaweza kuona amri za uingizaji wa kifurushi ambazo hutumiwa katika mradi wetu wote. Kwa hiyo, randint hutumika kufanya kijibu "usinzie" kwa idadi isiyo ya kawaida ya sekunde kabla ya kuanza operesheni mpya ya utafutaji. Kawaida, hakuna bot moja inayoweza kufanya bila hii. Ikiwa utatumia nambari iliyo hapo juu, dirisha la Chrome litafungua, ambalo roboti itatumia kufanya kazi na tovuti.

Hebu tufanye majaribio kidogo na kufungua tovuti ya kayak.com katika dirisha tofauti. Tutachagua jiji ambalo tutaruka, na jiji tunalotaka kufika, pamoja na tarehe za ndege. Wakati wa kuchagua tarehe, hakikisha kwamba muda wa siku +-3 hutumiwa. Niliandika msimbo kwa kuzingatia kile tovuti hutoa kwa kujibu maombi hayo. Ikiwa, kwa mfano, unahitaji kutafuta tikiti kwa tarehe maalum tu, basi kuna uwezekano mkubwa kwamba utalazimika kurekebisha msimbo wa roboti. Ninapozungumza juu ya nambari, mimi hutoa maelezo yanayofaa, lakini ikiwa unahisi kuchanganyikiwa, nijulishe.

Sasa bofya kwenye kifungo cha utafutaji na uangalie kiungo kwenye bar ya anwani. Inapaswa kuwa sawa na kiunga ninachotumia kwenye mfano hapa chini ambapo kutofautisha kunatangazwa kayak, ambayo huhifadhi URL, na njia inatumiwa get dereva wa wavuti. Baada ya kubofya kitufe cha utafutaji, matokeo yanapaswa kuonekana kwenye ukurasa.

Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri
Nilipotumia amri get zaidi ya mara mbili au tatu ndani ya dakika chache, niliulizwa kukamilisha uthibitishaji kwa kutumia reCaptcha. Unaweza kupitisha hundi hii wewe mwenyewe na uendelee kujaribu hadi mfumo uamue kuendesha ukaguzi mpya. Nilipojaribu hati, ilionekana kama kipindi cha kwanza cha utaftaji kila wakati kilikwenda vizuri, kwa hivyo ikiwa ungetaka kujaribu nambari, utalazimika kuangalia mara kwa mara na kuruhusu nambari iendeshe, kwa kutumia vipindi virefu kati ya vipindi vya utaftaji. Na, ikiwa unafikiria juu yake, hakuna uwezekano wa mtu kuhitaji habari kuhusu bei za tikiti zilizopokelewa kwa vipindi vya dakika 10 kati ya shughuli za utaftaji.

Kufanya kazi na ukurasa kwa kutumia XPath

Kwa hiyo, tulifungua dirisha na kupakia tovuti. Ili kupata bei na maelezo mengine, tunahitaji kutumia teknolojia ya XPath au viteuzi vya CSS. Niliamua kushikamana na XPath na sikuhisi hitaji la kutumia viteuzi vya CSS, lakini inawezekana kabisa kufanya kazi kwa njia hiyo. Kuzunguka ukurasa kwa kutumia XPath inaweza kuwa gumu, na hata ikiwa unatumia mbinu nilizoelezea hii makala, ambayo ilihusisha kunakili vitambulisho vinavyolingana kutoka kwa msimbo wa ukurasa, niligundua kuwa hii, kwa kweli, sio njia bora ya kufikia vipengele muhimu. Kwa njia, ndani hii Kitabu hutoa maelezo bora ya misingi ya kufanya kazi na kurasa kwa kutumia XPath na CSS selectors. Hivi ndivyo njia inayolingana ya kiendeshi cha wavuti inaonekana.

Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri
Kwa hivyo, wacha tuendelee kufanya kazi kwenye bot. Wacha tutumie uwezo wa programu kuchagua tikiti za bei rahisi zaidi. Katika picha ifuatayo, msimbo wa kuchagua XPath umeangaziwa kwa rangi nyekundu. Ili kutazama msimbo, unahitaji kubofya kulia kwenye kipengele cha ukurasa unachopenda na uchague amri ya Kukagua kutoka kwenye menyu inayoonekana. Amri hii inaweza kuitwa kwa vipengele tofauti vya ukurasa, msimbo ambao utaonyeshwa na kuonyeshwa kwenye mtazamaji wa kanuni.

Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri
Tazama msimbo wa ukurasa

Ili kupata uthibitisho wa hoja yangu juu ya ubaya wa kunakili wateule kutoka kwa nambari, makini na huduma zifuatazo.

Hivi ndivyo unapata unaponakili msimbo:

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

Ili kunakili kitu kama hiki, unahitaji kubonyeza kulia kwenye sehemu ya nambari unayopenda na uchague Nakili > Nakili amri ya XPath kutoka kwa menyu inayoonekana.

Hivi ndivyo nilivyokuwa nikifafanua kitufe cha bei nafuu zaidi:

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

Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri
Nakili Amri > Nakili XPath

Ni dhahiri kabisa kwamba chaguo la pili linaonekana rahisi zaidi. Inapotumiwa, hutafuta kipengele a ambacho kina sifa data-code, sawa price. Unapotumia chaguo la kwanza, kipengele kinatafutwa id ambayo ni sawa na wtKI-price_aTab, na njia ya XPath ya kipengee inaonekana kama /div[1]/div/div/div[1]/div/span/span. Swali la XPath kama hili kwa ukurasa litafanya ujanja, lakini mara moja tu. Naweza kusema hivi sasa id itabadilika ukurasa mwingine unapopakiwa. Mfuatano wa wahusika wtKI hubadilika kila wakati ukurasa unapopakiwa, kwa hivyo msimbo unaoutumia hautakuwa na maana baada ya ukurasa unaofuata kupakiwa upya. Kwa hivyo chukua muda kuelewa XPath. Ujuzi huu utakutumikia vyema.

Walakini, inapaswa kuzingatiwa kuwa kunakili wateule wa XPath kunaweza kuwa muhimu wakati wa kufanya kazi na tovuti rahisi, na ikiwa unastarehekea hii, hakuna chochote kibaya nayo.

Sasa hebu tufikirie nini cha kufanya ikiwa unahitaji kupata matokeo yote ya utafutaji katika mistari kadhaa, ndani ya orodha. Rahisi sana. Kila matokeo ni ndani ya kitu na darasa resultWrapper. Kupakia matokeo yote kunaweza kufanywa kwa kitanzi sawa na kilichoonyeshwa hapa chini.

Ikumbukwe kwamba ikiwa unaelewa hapo juu, basi unapaswa kuelewa kwa urahisi zaidi ya kanuni ambazo tutachambua. Nambari hii inapoendelea, tunapata kile tunachohitaji (kwa kweli, kipengele ambacho matokeo yamefungwa) kwa kutumia aina fulani ya utaratibu wa kubainisha njia (XPath). Hii inafanywa ili kupata maandishi ya kitu hicho na kuiweka kwenye kitu ambacho data inaweza kusomwa (iliyotumiwa kwanza. flight_containers, basi - flights_list).

Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri
Mistari mitatu ya kwanza inaonyeshwa na tunaweza kuona wazi kila kitu tunachohitaji. Walakini, tuna njia za kuvutia zaidi za kupata habari. Tunahitaji kuchukua data kutoka kwa kila kipengele tofauti.

Anza kazi!

Njia rahisi zaidi ya kuandika kitendakazi ni kupakia matokeo ya ziada, kwa hivyo ndipo tutaanza. Ningependa kuongeza idadi ya safari za ndege ambazo programu hupokea taarifa kuzihusu, bila kuibua shaka katika huduma inayopelekea ukaguzi, kwa hivyo ninabofya kitufe cha Pakia matokeo zaidi mara moja kila ukurasa unapoonyeshwa. Katika kanuni hii, unapaswa kuzingatia kuzuia try, ambayo niliongeza kwa sababu wakati mwingine kitufe hakipakii vizuri. Ukikumbana na hili pia, toa maoni kwa simu kwa chaguo hili la kukokotoa katika msimbo wa chaguo za kukokotoa start_kayak, ambayo tutaangalia hapa chini.

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

Sasa, baada ya uchanganuzi wa muda mrefu wa chaguo hili la kukokotoa (wakati mwingine naweza kubebwa), tuko tayari kutangaza chaguo la kukokotoa ambalo litafuta ukurasa.

Tayari nimekusanya zaidi ya kile kinachohitajika katika kazi ifuatayo inayoitwa page_scrape. Wakati mwingine data ya njia iliyorejeshwa imejumuishwa, kwa hivyo mimi hutumia njia rahisi kuitenganisha. Kwa mfano, ninapotumia vigezo kwa mara ya kwanza section_a_list и section_b_list. Chaguo zetu za kukokotoa hurejesha fremu ya data flights_df, hii huturuhusu kutenganisha matokeo yaliyopatikana kutoka kwa mbinu tofauti za kupanga data na baadaye kuyachanganya.

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

Nilijaribu kutaja vijiumbe ili msimbo uweze kueleweka. Kumbuka kwamba vigezo kuanzia a ni wa hatua ya kwanza ya njia, na b - kwa pili. Hebu tuendelee kwenye kipengele kinachofuata.

Njia za usaidizi

Sasa tuna chaguo la kukokotoa linaloturuhusu kupakia matokeo ya ziada ya utafutaji na chaguo la kukokotoa kuchakata matokeo hayo. Nakala hii inaweza kuishia hapa, kwa kuwa kazi hizi mbili hutoa kila kitu unachohitaji ili kufuta kurasa ambazo unaweza kufungua mwenyewe. Lakini bado hatujazingatia baadhi ya njia za usaidizi zilizojadiliwa hapo juu. Kwa mfano, huu ndio msimbo wa kutuma barua pepe na vitu vingine. Yote hii inaweza kupatikana katika kazi start_kayak, ambayo sasa tutazingatia.

Ili chaguo hili lifanye kazi, unahitaji habari kuhusu miji na tarehe. Kwa kutumia habari hii, huunda kiungo katika kutofautisha kayak, ambayo inatumika kukupeleka kwenye ukurasa ambao utakuwa na matokeo ya utafutaji yaliyopangwa kulingana na hoja yao bora zaidi. Baada ya kikao cha kwanza cha kugema, tutafanya kazi na bei kwenye jedwali lililo juu ya ukurasa. Yaani, tutapata bei ya chini ya tikiti na bei ya wastani. Yote hii, pamoja na utabiri uliotolewa na tovuti, itatumwa kwa barua pepe. Kwenye ukurasa, meza inayolingana inapaswa kuwa kwenye kona ya juu kushoto. Kufanya kazi na meza hii, kwa njia, kunaweza kusababisha kosa wakati wa kutafuta kwa kutumia tarehe halisi, kwani katika kesi hii meza haionyeshwa kwenye ukurasa.

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

Nilijaribu hati hii kwa kutumia akaunti ya Outlook (hotmail.com). Sijajaribu kufanya kazi kwa usahihi na akaunti ya Gmail, mfumo huu wa barua pepe ni maarufu sana, lakini kuna chaguzi nyingi zinazowezekana. Ikiwa unatumia akaunti ya Hotmail, basi ili kila kitu kifanye kazi, unahitaji tu kuingiza data yako kwenye msimbo.

Ikiwa ungependa kuelewa ni nini hasa kinafanywa katika sehemu maalum za msimbo wa chaguo hili la kukokotoa, unaweza kuzinakili na kuzijaribu. Kujaribu kutumia msimbo ndiyo njia pekee ya kuielewa kwa kweli.

Mfumo tayari

Sasa kwa kuwa tumefanya kila kitu tulichozungumza, tunaweza kuunda kitanzi rahisi kinachoita utendaji wetu. Hati inaomba data kutoka kwa mtumiaji kuhusu miji na tarehe. Unapojaribu kwa kuanzisha upya hati mara kwa mara, hakuna uwezekano wa kutaka kuingiza data hii kwa mikono kila wakati, kwa hivyo mistari inayolingana, ya wakati wa majaribio, inaweza kutolewa maoni kwa kutoa maoni kwa wale walio chini yao, ambayo data inayohitajika na hati ni ngumu.

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

Hivi ndivyo jaribio la hati inavyoonekana.
Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri
Jaribio la utekelezaji wa hati

Matokeo ya

Ikiwa umefikia hapa, pongezi! Sasa unayo kifuta mtandao kinachofanya kazi, ingawa tayari ninaweza kuona njia nyingi za kuiboresha. Kwa mfano, inaweza kuunganishwa na Twilio ili kutuma ujumbe mfupi badala ya barua pepe. Unaweza kutumia VPN au kitu kingine kupokea matokeo kwa wakati mmoja kutoka kwa seva kadhaa. Pia kuna tatizo linalojitokeza mara kwa mara kwa kuangalia mtumiaji wa tovuti ili kuona kama yeye ni mtu, lakini tatizo hili pia linaweza kutatuliwa. Kwa hali yoyote, sasa una msingi ambao unaweza kupanua ikiwa unataka. Kwa mfano, hakikisha kuwa faili ya Excel imetumwa kwa mtumiaji kama kiambatisho kwa barua pepe.

Python - msaidizi katika kutafuta tiketi za ndege za gharama nafuu kwa wale wanaopenda kusafiri

Watumiaji waliojiandikisha pekee ndio wanaweza kushiriki katika utafiti. Weka sahihitafadhali.

Je, unatumia teknolojia za kuchakachua wavuti?

  • Да

  • Hakuna

Watumiaji 8 walipiga kura. Mtumiaji 1 alijizuia.

Chanzo: mapenzi.com

Kuongeza maoni