Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw

L-awtur tal-artiklu, li t-traduzzjoni tiegħu qed nippubblikaw illum, jgħid li l-għan tiegħu huwa li jitkellem dwar l-iżvilupp ta 'web scraper f'Python li juża Selenium, li jfittex il-prezzijiet tal-biljetti tal-ajru. Meta tfittex biljetti, jintużaw dati flessibbli (+- 3 ijiem relattivi għad-dati speċifikati). Il-barraxa jiffranka r-riżultati tat-tfittxija f'fajl Excel u jibgħat lill-persuna li mexxiet it-tfittxija email b'sommarju ta 'dak li sabu. L-għan ta’ dan il-proġett huwa li jgħin lill-vjaġġaturi jsibu l-aħjar offerti.

Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw

Jekk, waqt li tifhem il-materjal, tħossok mitluf, agħti ħarsa lejn dan artikolu.

X’se nfittxu?

Inti liberu li tuża s-sistema deskritta hawn kif tixtieq. Pereżempju, użajtha biex infittex tours ta’ tmiem il-ġimgħa u biljetti għal raħal twelidi. Jekk inti serji dwar li ssib biljetti profittabbli, tista 'tħaddem l-iskrittura fuq is-server (sempliċi server, għal 130 rublu fix-xahar, huwa pjuttost adattat għal dan) u kun żgur li taħdem darba jew darbtejn kuljum. Ir-riżultati tat-tfittxija jintbagħtulek bl-email. Barra minn hekk, nirrakkomanda li twaqqaf kollox sabiex l-iskript jiffranka fajl Excel bir-riżultati tat-tfittxija f'folder ta 'Dropbox, li jippermettilek tara fajls bħal dawn minn kullimkien u fi kwalunkwe ħin.

Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw
Għadni ma sibtx tariffi bi żbalji, imma naħseb li huwa possibbli

Waqt it-tfittxija, kif diġà ssemma, tintuża "data flessibbli"; l-iskrittura ssib offerti li jkunu fi żmien tlett ijiem mid-dati mogħtija. Għalkemm meta tmexxi l-iskript, tfittex offerti f'direzzjoni waħda biss, huwa faċli li timmodifikaha sabiex tkun tista' tiġbor data fuq diversi direzzjonijiet tat-titjira. Bl-għajnuna tagħha, tista 'saħansitra tfittex tariffi żbaljati; sejbiet bħal dawn jistgħu jkunu interessanti ħafna.

Għaliex għandek bżonn barraxa tal-web ieħor?

Meta l-ewwel bdejt il-web scraping, onestament ma kontx partikolarment interessat fiha. Xtaqt nagħmel aktar proġetti fil-qasam tal-immudellar predittiv, l-analiżi finanzjarja, u, possibilment, fil-qasam tal-analiżi tal-kulur emozzjonali tat-testi. Iżda rriżulta li kien interessanti ħafna li wieħed jifhem kif jinħoloq programm li jiġbor data minn websajts. Hekk kif dħalt f'dan is-suġġett, indunajt li l-brix tal-web huwa l-"magna" tal-Internet.

Tista' taħseb li din hija dikjarazzjoni kuraġġuża wisq. Imma ikkunsidra li Google bdiet bi barraxa tal-web li Larry Page ħoloq bl-użu ta 'Java u Python. Ir-robots tal-Google ilhom jesploraw l-Internet, jippruvaw jipprovdu lill-utenti tiegħu bl-aħjar tweġibiet għall-mistoqsijiet tagħhom. Il-brix tal-web għandu użi bla tmiem, u anki jekk int interessat f'xi ħaġa oħra fix-Xjenza tad-Data, ikollok bżonn xi ħiliet ta 'brix biex tikseb id-dejta li għandek bżonn tanalizza.

Sibt xi wħud mit-tekniki użati hawn fil-isbaħ il-ktieb dwar il-web scraping, li reċentement akkwistajt. Fiha ħafna eżempji sempliċi u ideat għall-applikazzjoni prattika ta’ dak li tgħallimt. Barra minn hekk, hemm kapitolu interessanti ħafna dwar il-bypass tal-kontrolli reCaptcha. Din ġiet bħala aħbar għalija, peress li lanqas biss kont naf li kien hemm għodod speċjali u anke servizzi sħaħ biex issolvi problemi bħal dawn.

Tħobb issiefer?!

Għall-mistoqsija sempliċi u pjuttost bla ħsara magħmula fit-titlu ta 'din it-taqsima, ħafna drabi tista' tisma 'tweġiba pożittiva, akkumpanjata minn ftit stejjer mill-vjaġġi tal-persuna li lilha ġiet mitluba. Ħafna minna naqblu li l-ivvjaġġar huwa mod tajjeb ħafna biex tgħaddas ruħek f'ambjenti kulturali ġodda u twessa' l-orizzonti tiegħek. Madankollu, jekk tistaqsi lil xi ħadd jekk jħobbx ifittex biljetti tal-ajru, jien ċert li t-tweġiba mhux se tkun daqshekk pożittiva. Fil-fatt, Python jiġi għall-għajnuna tagħna hawn.

L-ewwel biċċa xogħol li rridu nsolvu fit-triq lejn il-ħolqien ta' sistema għat-tiftix ta' informazzjoni fuq biljetti tal-ajru se tkun l-għażla ta' pjattaforma xierqa li minnha nieħdu l-informazzjoni. Issolvi din il-problema ma kinitx faċli għalija, iżda fl-aħħar għażilt is-servizz tal-Kayak. Ippruvajt is-servizzi ta 'Momondo, Skyscanner, Expedia, u ftit oħrajn, iżda l-mekkaniżmi ta' protezzjoni tar-robot fuq dawn ir-riżorsi kienu impenetrabbli. Wara diversi tentattivi, li matulhom kelli nittratta d-dwal tat-traffiku, pedestrian crossings u roti, ipprova nikkonvinċi lis-sistemi li jien kont bniedem, iddeċidejt li l-Kayak kien l-aktar adattat għalija, minkejja l-fatt li anke jekk Wisq paġni huma mgħobbija. fi żmien qasir, u jibdew ukoll il-kontrolli. Irnexxieli nagħmel il-bot jibgħat talbiet lis-sit f'intervalli ta '4 sa 6 sigħat, u kollox ħadem tajjeb. Minn żmien għal żmien, jinqalgħu diffikultajiet meta taħdem mal-Kayak, imma jekk jibdew ifixkluk bi kontrolli, allura għandek bżonn jew tittrattahom manwalment u mbagħad tniedi l-bot, jew stenna ftit sigħat u l-kontrolli għandhom jieqfu. Jekk meħtieġ, tista 'faċilment tadatta l-kodiċi għal pjattaforma oħra, u jekk tagħmel hekk, tista' tirrapportah fil-kummenti.

Jekk għadek kif tibda bil-web scraping u ma tafx għaliex xi websajts jissieltu magħha, imbagħad qabel ma tibda l-ewwel proġett tiegħek f'dan il-qasam, tagħmel lilek innifsek favur u agħmel tfittxija Google fuq il-kliem "web scraping etikett" . L-esperimenti tiegħek jistgħu jispiċċaw aktar kmieni milli taħseb jekk tagħmel il-brix tal-web b'mod mhux għaqli.

Getting Started

Hawn ħarsa ġenerali lejn x'se jiġri fil-kodiċi tal-barraxa tal-web tagħna:

  • Importa l-libreriji meħtieġa.
  • Ftuħ ta 'Google Chrome tab.
  • Sejħa funzjoni li tibda l-bot, tgħaddiha l-ibliet u d-dati li se jintużaw meta tfittex biljetti.
  • Din il-funzjoni tieħu l-ewwel riżultati tat-tfittxija, magħżula skont l-aħjar, u tikklikkja buttuna biex tgħabbi aktar riżultati.
  • Funzjoni oħra tiġbor data mill-paġna kollha u tirritorna qafas tad-data.
  • Iż-żewġ passi preċedenti jsiru bl-użu ta’ tipi ta’ għażla skont il-prezz tal-biljett (irħis) u skont il-veloċità tat-titjira (l-aktar veloċi).
  • L-utent tal-iskript jintbagħat email li jkun fiha sommarju tal-prezzijiet tal-biljetti (biljetti irħas u prezz medju), u qafas tad-dejta b'informazzjoni magħżula bit-tliet indikaturi msemmija hawn fuq jiġi ffrankat bħala fajl Excel.
  • L-azzjonijiet kollha ta 'hawn fuq jitwettqu f'ċiklu wara perjodu ta' żmien speċifikat.

Għandu jiġi nnutat li kull proġett Selenium jibda b'sewwieq tal-web. jien nuża Chromedriver, Naħdem ma 'Google Chrome, iżda hemm għażliet oħra. PhantomJS u Firefox huma wkoll popolari. Wara li tniżżel is-sewwieq, trid tpoġġih fil-folder xieraq, u dan itemm il-preparazzjoni għall-użu tiegħu. L-ewwel linji tal-iskrittura tagħna jiftħu tab Chrome ġdida.

Żomm f'moħħok li fl-istorja tiegħi mhux qed nipprova niftaħ orizzonti ġodda biex insib offerti kbar fuq biljetti tal-ajru. Hemm metodi ħafna aktar avvanzati ta 'tiftix għal offerti bħal dawn. Irrid biss noffri lill-qarrejja ta 'dan il-materjal mod sempliċi iżda prattiku biex issolvi din il-problema.

Hawn hu l-kodiċi li tkellimna dwaru hawn fuq.

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)

Fil-bidu tal-kodiċi tista 'tara l-kmandi tal-importazzjoni tal-pakkett li jintużaw matul il-proġett tagħna. Allura, randint użat biex jagħmel il-bot "torqod" għal numru każwali ta 'sekondi qabel ma tibda operazzjoni ġdida ta' tfittxija. Normalment, ebda bot wieħed ma jista 'jagħmel mingħajr dan. Jekk tmexxi l-kodiċi ta 'hawn fuq, tinfetaħ tieqa Chrome, li l-bot se juża biex jaħdem mas-siti.

Ejja nagħmlu esperiment żgħir u niftħu l-websajt kayak.com f'tieqa separata. Se nagħżlu l-belt li minnha se ttiru, u l-belt li rridu naslu fiha, kif ukoll id-dati tat-titjira. Meta tagħżel id-dati, kun żgur li tintuża l-firxa ta '+-3 ijiem. Jien ktibt il-kodiċi b'kont meħud ta' dak li jipproduċi s-sit bi tweġiba għal tali talbiet. Jekk, pereżempju, għandek bżonn tfittex biljetti għal dati speċifikati biss, allura hemm probabbiltà kbira li jkollok timmodifika l-kodiċi tal-bot. Meta nitkellem dwar il-kodiċi, nipprovdi spjegazzjonijiet xierqa, imma jekk tħossok konfuż, għarrafni.

Issa kklikkja fuq il-buttuna tat-tfittxija u ħares lejn il-link fil-bar tal-indirizz. Għandu jkun simili għall-link li nuża fl-eżempju hawn taħt fejn il-varjabbli hija ddikjarata kayak, li jaħżen il-URL, u jintuża l-metodu get sewwieq tal-web. Wara li tikklikkja l-buttuna tat-tfittxija, ir-riżultati għandhom jidhru fuq il-paġna.

Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw
Meta użajt il-kmand get aktar minn darbtejn jew tliet darbiet fi ftit minuti, ġejt mitlub biex inlesti l-verifika billi tuża reCaptcha. Tista' tgħaddi dan il-kontroll manwalment u tkompli tesperimenta sakemm is-sistema tiddeċiedi li twettaq kontroll ġdid. Meta ttestjajt l-iskrittura, deher li l-ewwel sessjoni ta 'tfittxija dejjem marret bla xkiel, għalhekk jekk inti ridt tesperimenta bil-kodiċi, ikollok biss perjodikament tiċċekkja manwalment u ħalli l-kodiċi jaħdem, billi tuża intervalli twal bejn is-sessjonijiet ta' tfittxija. U, jekk taħseb dwarha, x'aktarx li persuna ma teħtieġx informazzjoni dwar il-prezzijiet tal-biljetti riċevuti f'intervalli ta '10 minuti bejn l-operazzjonijiet ta' tfittxija.

Ħidma ma 'paġna bl-użu ta' XPath

Allura, ftaħna tieqa u għabbejna s-sit. Biex tikseb prezzijiet u informazzjoni oħra, għandna bżonn nużaw it-teknoloġija XPath jew is-seletturi CSS. Iddeċidejt li nżomm ma' XPath u ma ħassx il-ħtieġa li nuża seletturi CSS, iżda huwa pjuttost possibbli li taħdem b'dan il-mod. In-navigazzjoni madwar paġna bl-użu ta 'XPath tista' tkun delikata, u anke jekk tuża t-tekniki li ddeskrivejt fihom dan artikolu, li kien jinvolvi l-ikkupjar tal-identifikaturi korrispondenti mill-kodiċi tal-paġna, indunajt li dan huwa, fil-fatt, mhux l-aħjar mod biex taċċessa l-elementi meħtieġa. Mill-mod, fi dan Il-ktieb jipprovdi deskrizzjoni eċċellenti tal-baŜi tal-ħidma ma 'paġni bl-użu ta' seletturi XPath u CSS. Dan huwa kif jidher il-metodu tas-sewwieq tal-web korrispondenti.

Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw
Allura, ejja nkomplu naħdmu fuq il-bot. Ejja nużaw il-kapaċitajiet tal-programm biex nagħżlu l-irħas biljetti. Fl-immaġni li ġejja, il-kodiċi tas-selettur XPath huwa enfasizzat bl-aħmar. Sabiex tara l-kodiċi, trid tikklikkja bil-lemin fuq l-element tal-paġna li inti interessat fih u tagħżel il-kmand Spezzjona mill-menu li jidher. Dan il-kmand jista 'jissejjaħ għal elementi tal-paġna differenti, li l-kodiċi tagħhom se jintwera u enfasizzat fit-telespettatur tal-kodiċi.

Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw
Ara l-kodiċi tal-paġna

Sabiex issib konferma tar-raġunament tiegħi dwar l-iżvantaġġi li tikkopja s-seletturi mill-kodiċi, oqgħod attent għall-karatteristiċi li ġejjin.

Dan huwa dak li tikseb meta tikkopja l-kodiċi:

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

Sabiex tikkopja xi ħaġa bħal din, trid tikklikkja bil-lemin fuq it-taqsima tal-kodiċi li inti interessat fiha u agħżel il-Kopja > Ikkopja kmand XPath mill-menu li jidher.

Hawn dak li użajt biex niddefinixxi l-buttuna irħas:

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

Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw
Ikkopja Kmand > Ikkopja XPath

Huwa pjuttost ovvju li t-tieni għażla tidher ħafna aktar sempliċi. Meta jintuża, ifittex element a li għandu l-attribut data-codeugwali għal price. Meta tuża l-ewwel għażla, l-element jiġi mfittex id li hija ugwali għal wtKI-price_aTab, u l-mogħdija XPath għall-element tidher qisha /div[1]/div/div/div[1]/div/span/span. Mistoqsija XPath bħal din għal paġna se tagħmel il-trick, iżda darba biss. Nista' ngħid li issa id se jinbidel il-ħin li jmiss il-paġna titgħabba. Sekwenza tal-karattri wtKI jinbidel b'mod dinamiku kull darba li l-paġna titgħabba, għalhekk il-kodiċi li jużaha se jkun inutli wara li l-paġna li jmiss terġa' titgħabba. Allura ħu ftit ħin biex tifhem XPath. Dan l-għarfien se jservik tajjeb.

Madankollu, għandu jiġi nnutat li l-ikkupjar tas-seletturi XPath jista 'jkun utli meta taħdem ma' siti pjuttost sempliċi, u jekk inti komdu b'dan, m'hemm xejn ħażin miegħu.

Issa ejja naħsbu dwar x'għandek tagħmel jekk ikollok bżonn tikseb ir-riżultati kollha tat-tfittxija f'diversi linji, ġewwa lista. Sempliċi ħafna. Kull riżultat huwa ġewwa oġġett bi klassi resultWrapper. It-tagħbija tar-riżultati kollha tista 'ssir f'linja simili għal dik murija hawn taħt.

Għandu jiġi nnutat li jekk tifhem dak ta 'hawn fuq, allura għandek tifhem faċilment il-biċċa l-kbira tal-kodiċi li aħna se nanalizzaw. Hekk kif jaħdem dan il-kodiċi, aħna naċċessaw dak li neħtieġu (fil-fatt, l-element li fih ikun imgeżwer ir-riżultat) billi tuża xi tip ta 'mekkaniżmu li jispeċifika l-mogħdija (XPath). Dan isir sabiex jinkiseb it-test tal-element u poġġih f'oġġett li minnu tista' tinqara d-dejta (l-ewwel użata flight_containers, allura - flights_list).

Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw
L-ewwel tliet linji jintwerew u nistgħu naraw b'mod ċar dak kollu li għandna bżonn. Madankollu, għandna modi aktar interessanti kif niksbu l-informazzjoni. Irridu nieħdu data minn kull element separatament.

Ikseb ix-xogħol!

L-eħfef mod biex tikteb funzjoni huwa li tgħabbi riżultati addizzjonali, għalhekk huwa minn fejn nibdew. Nixtieq li timmassimizza n-numru ta’ titjiriet li l-programm jirċievi informazzjoni dwarhom, mingħajr ma nqajjem suspetti fis-servizz li jwassal għal spezzjoni, għalhekk nikklikkja l-buttuna Agħbi aktar riżultati darba kull darba li tintwera l-paġna. F'dan il-kodiċi, għandek tagħti attenzjoni lill-blokk try, li żidt għax kultant il-buttuna ma titgħabbix sew. Jekk tiltaqa' ma' dan ukoll, ikkummenta s-sejħiet għal din il-funzjoni fil-kodiċi tal-funzjoni start_kayak, li se nħarsu lejha hawn taħt.

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

Issa, wara analiżi twila ta 'din il-funzjoni (xi kultant nista' nġarrab), aħna lesti li niddikjaraw funzjoni li tinbarax il-paġna.

Diġà ġbart ħafna minn dak li hu meħtieġ fil-funzjoni li ġejja msejħa page_scrape. Xi drabi d-dejta tal-mogħdija lura hija kkombinata, għalhekk nuża metodu sempliċi biex nisseparaha. Per eżempju, meta nuża varjabbli għall-ewwel darba section_a_list и section_b_list. Il-funzjoni tagħna tirritorna qafas tad-data flights_df, dan jippermettilna nisseparaw ir-riżultati miksuba minn metodi differenti ta 'għażla tad-dejta u aktar tard ngħaqqduhom.

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

Ippruvajt insemmi l-varjabbli sabiex il-kodiċi jinftiehem. Ftakar li varjabbli li jibdew bi a jappartjenu għall-ewwel stadju tat-triq, u b - għat-tieni. Ejja ngħaddu għall-funzjoni li jmiss.

Mekkaniżmi ta' appoġġ

Issa għandna funzjoni li tippermettilna tagħbija riżultati addizzjonali tat-tiftix u funzjoni biex tipproċessa dawk ir-riżultati. Dan l-artikolu seta' spiċċa hawn, peress li dawn iż-żewġ funzjonijiet jipprovdu dak kollu li għandek bżonn biex jinbarax paġni li tista 'tiftaħ lilek innifsek. Iżda għadna ma qisniex xi wħud mill-mekkaniżmi awżiljarji diskussi hawn fuq. Per eżempju, dan huwa l-kodiċi biex jintbagħtu emails u xi affarijiet oħra. Dan kollu jista 'jinstab fil-funzjoni start_kayak, li issa se nikkunsidraw.

Din il-funzjoni teħtieġ informazzjoni dwar bliet u dati. Billi tuża din l-informazzjoni, tifforma rabta f'varjabbli kayak, li tintuża biex tieħdok għal paġna li jkun fiha riżultati tat-tfittxija magħżula skont l-aħjar li jaqblu mal-mistoqsija. Wara l-ewwel sessjoni tal-brix, se naħdmu bil-prezzijiet fit-tabella fil-quċċata tal-paġna. Jiġifieri, insibu l-prezz minimu tal-biljett u l-prezz medju. Dan kollu, flimkien mal-previżjoni maħruġa mis-sit, se jintbagħat bl-email. Fuq il-paġna, it-tabella korrispondenti għandha tkun fir-rokna ta 'fuq tax-xellug. Ħidma ma 'din it-tabella, mill-mod, jista' jikkawża żball meta tfittex bl-użu ta 'dati eżatti, peress li f'dan il-każ it-tabella ma tintwerax fuq il-paġna.

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

Ittestjajt dan l-iskript bl-użu ta 'kont Outlook (hotmail.com). Ma ttestjajtx biex taħdem b'mod korrett b'kont tal-Gmail, din is-sistema tal-email hija popolari pjuttost, iżda hemm ħafna għażliet possibbli. Jekk tuża kont Hotmail, allura biex kollox jaħdem, għandek bżonn biss li ddaħħal id-dejta tiegħek fil-kodiċi.

Jekk trid tifhem x'qed isir eżatt f'taqsimiet speċifiċi tal-kodiċi għal din il-funzjoni, tista' tikkopjahom u tesperimenta magħhom. L-esperimentazzjoni bil-kodiċi hija l-uniku mod biex tifhimha tassew.

Sistema lesta

Issa li għamilna dak kollu li tkellimna dwaru, nistgħu noħolqu linja sempliċi li ssejjaħ il-funzjonijiet tagħna. L-iskrittura titlob dejta mill-utent dwar bliet u dati. Meta tkun qed tittestja b'ristartjar kostanti tal-iskript, mhux probabbli li trid iddaħħal din id-dejta manwalment kull darba, għalhekk il-linji korrispondenti, għall-ħin tal-ittestjar, jistgħu jiġu kkummentati billi ma tikkummentax dawk taħthom, li fihom id-dejta meħtieġa mill- skript huwa hardcoded.

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

Hekk tidher ġirja tat-test tal-iskrittura.
Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw
Test run tal-iskrittura

Riżultati ta '

Jekk wasalt sa issa, prosit! Issa għandek barraxa tal-web li taħdem, għalkemm diġà nista' nara ħafna modi kif ittejjeb. Pereżempju, jista 'jiġi integrat ma' Twilio sabiex jibgħat messaġġi minflok emails. Tista 'tuża VPN jew xi ħaġa oħra biex fl-istess ħin tirċievi riżultati minn diversi servers. Hemm ukoll problema perjodikament li tqum bil-verifika tal-utent tas-sit biex tara jekk hux persuna, iżda din il-problema tista 'tiġi solvuta wkoll. Fi kwalunkwe każ, issa għandek bażi li tista 'tespandi jekk tixtieq. Pereżempju, kun żgur li fajl Excel jintbagħat lill-utent bħala anness ma' email.

Python - assistent biex isib biljetti tal-ajru rħas għal dawk li jħobbu jivvjaġġaw

Utenti reġistrati biss jistgħu jipparteċipaw fl-istħarriġ. Idħol, ta 'xejn.

Tuża teknoloġiji tal-web scraping?

  • Iva

  • Nru

Ivvutaw 8-il utent. utent 1 astjena.

Sors: www.habr.com

Żid kumment