Artikli autor, kelle tõlget me täna avaldame, ütleb, et tema eesmärk on rääkida Pythonis Seleniumi kasutamisega loodud veebiskreiperi arendamisest, mis otsib lennupiletite hindu. Piletite otsimisel kasutatakse paindlikke kuupäevi (+- 3 päeva määratud kuupäevadest). Skreiper salvestab otsingu tulemused Exceli faili ja saadab e-posti teel sellele, kes selle käivitas, üldise teabe selle kohta, mida ta suutis leida. Selle projekti eesmärk on aidata reisijatel leida kõige soodsamaid pakkumisi.
Kui tunned, et kaotad materjaliga tegeledes ära - vaata artiklit.
Mida me otsime?
Oled vabalt kutse eespool kirjeldatud süsteemi kasutada, nagu soovid. Mina näiteks olen kasutanud seda nädalavahetuse reiside ja piletite otsimiseks oma kodulinna. Kui oled tõsiselt piletite otsimisele pühendunud - saad skripti käivitada serveris (lihtne , 130 rubla kuus, sobib selleks hästi) ja seadistada nii, et see käivituks üks või kaks korda päevas. Otsingu tulemused saadetakse sulle e-posti teel. Samuti soovitan seada kõik nii, et skript salvestaks otsingu tulemused Exceli faili Dropbox kausta, mis võimaldab sul neid faile vaadata igal ajal ja igast kohast.

Ma pole veel leidnud vigu sisaldavaid hindu, kuid arvan, et see on võimalik.
Otsingus, nagu juba mainitud, kasutatakse „paindlikku kuupäeva”, skript leiab pakkumisi, mis asuvad kolme päeva ulatuses määratud kuupäevadest. Kuigi skripti käivitamisel otsitakse pakkumisi ainult ühes sihtkohas, ei ole selle kohandamine mitme lennusuuna andmete kogumiseks keeruline. Sellega on võimalik isegi otsida vigaseid hindu, sarnased leiud võivad olla väga huvitavad.
Miks on vajalik järjekordne veebiskreiper?
Kui ma esmakordselt veebiskrapingu tegemisega alustasin, ei tundunud see mulle ausalt öeldes eriti huvitav. Soovisin teha rohkem projekte prognoosimudelite, rahandusanalüüsi ja võib-olla ka tekstide emotsionaalse analüüsi vallas. Kuid selgus, et see on väga huvitav - mõista, kuidas luua programm, mis kogub andmeid veebisaitidelt. Süvenedes sellesse teema, sain aru, et just veebiskraping on interneti "mootor".
Võib-olla arvate, et see on liiga julge väide. Kuid mõelge sellele, et Google'i ettevõte sai alguse veebiskraperist, mille Larry Page lõi Java ja Python'i abil. Google'i robotid uurivad ja uurivad Internetti, püüdes pakkuda oma kasutajatele parimaid vastuseid nende küsimustele. Veebiskrapingul on lõpmatult palju rakendusi, ja isegi kui teid huvitab andmeteaduse valdkonnas midagi muud, vajate te analüüsi jaoks andmete hankimiseks mõningaid skrapingu oskusi.
Mõned siin kasutatud tehnikatest leidsin ma suurepärasest veebiskrapingu kohta, mille juurde hiljuti sain. Seal on palju lihtsaid näiteid ja ideid õppimise praktiliseks rakendamiseks. Lisaks on seal väga huvitav peatükk reCaptchade kontrollide ületamisest. Minu jaoks oli see uudis, kuna ma ei teadnud üldse, et on olemas spetsiaalsed tööriistad ja isegi terved teenused sarnaste ülesannete lahendamiseks.
Kas teile meeldib reisida?!
Lihtsale ja üsna kahjutule küsimusele, mis on selle jaotise pealkirjas, saab sageli positiivse vastuse, millele on lisatud paar reisilugu küsijalt. Enamik meist nõustub, et reisimine on suurepärane võimalus sukelduda uutesse kultuurikeskkondadesse ja laiendada oma silmaringi. Siiski, kui küsida kellegi käest, kas talle meeldib lennupiletite otsimine, olen kindel, et vastus sellele on juba kaugel positiivsest. Tegelikult aitab meid siinkohal Python.
Esimene ülesanne, mille peame lahendama lennupiletite otsingusüsteemi loomisel, on sobiva platvormi valimine, kust me teavet saame. Selle probleemi lahendamine ei olnud lihtne, kuid lõpuks valisin Kayaki teenuse. Olin proovinud Momondo, Skyscanner, Expedia ja veel mõnda, kuid nende ressursside robotite kaitsemehhanismid olid ületamatud. Pärast mitmeid katseid, kus pidin veenma süsteeme, et olen inimene, pidin tegelema valgusfooride, ülekäiguradade ja jalgratastega. Otsustasin, et Kayak sobib mulle kõige paremini, vaatamata sellele, et ka siin, kui laadida liiga palju lehti lühikese aja jooksul, algavad kontrollid. Suutsin teha nii, et bot saadaks päringud veebisaidile intervallidega 4 kuni 6 tundi ja kõik töötas normaalselt. Aeg-ajalt tekivad Kayakiga töötades raskused, kuid kui teid hakkavad kontrollid piinama, peate kas nende probleemidega käsitsi tegelema ja seejärel boti käivitama või ootama mitu tundi, pärast mida kontrollid peaksid lõppema. Kui soovite, saate kindlasti kohandada koodi teisele platvormile ja kui te seda teete, andke sellest kommentaarides teada.
Kui olete veebiskrapinguga alles algamas ja ei tea, miks mõned veebisaidid selle vastu võitlevad, siis enne oma esimesse projekti asumist – tehke endale teenus ja otsige Google'ist materjale sõnadega „web scraping etiquette“. Teie eksperimendid võivad lõppeda kiiremini, kui arvate, kui tegelete veebiskrapinguga arutult.
Esimene samm
Siin on ülevaade sellest, mis meie veebiskraperi koodis toimuma hakkab:
- Vajalikud teegid imporditakse.
- Ava Google Chrome'i vahekaart.
- Käivitamisfunktsiooni kutse, edastades talle linnad ja kuupäevad, mida lennupiletite otsimisel kasutada.
- See funktsioon saab esimesed otsingutulemused, mis on sorteeritud kõige atraktiivsemate (best) järgi, ja vajutab nuppu, et laadida täiendavaid tulemusi.
- Veel üks funktsioon kogub kogu lehe andmed ja tagastab andmeraami.
- Kaks eelnevat sammu teostatakse piletihindade (cheap) ja lennu kestuse (fastest) sortimisviiside kasutamisega.
- Kasutajale saadetakse e-kiri, milles on lühike ülevaade piletihindadest (odavaimad piletid ja keskmine hind), samuti andmekaader, mille andmed on järjestatud kolme eespool nimetatud näitaja järgi, salvestatakse Exceli failina.
- Kõik eespool kirjeldatud toimingud viiakse läbi tsüklis kindla ajavahemiku järel.
Tuleb märkida, et iga Seleniumi projekt algab veebidraiverist. Kasutan , töötades Google Chrome'iga, kuid on ka teisi variante. Suure populaarsuse on saavutanud ka PhantomJS ja Firefox. Pärast draiveri allalaadimist tuleb see paigutada vastavasse kausta, sellega valmistamine kasutamiseks lõpeb. Skripti esimeses osas avatakse uus Chrome'i vahekaart.
Pange tähele, et ma oma jutustuses ei püüa avada uusi horisonte soodushindade leidmiseks lennupiletite jaoks. On olemas palju arenenumaid tehnikaid sarnaste pakkumiste leidmiseks. Soovin lihtsalt pakkuda käesoleva materjali lugejatele lihtsat, kuid praktikas rakendatavat lahendust sellele ülesandele.
Siin on kood, millest me eespool rääkisime.
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
# Kasutage siin oma teed chromedriver'ile!
chromedriver_path = 'C:/{YOUR PATH HERE}/chromedriver_win32/chromedriver.exe'
driver = webdriver.Chrome(executable_path=chromedriver_path) # Selle käsuga avaneb Chrome'i aken
sleep(2) Koodi alguses on näha pakettide importimise käske, mida kasutatakse kogu meie projektis. Nii on randint kasutatakse selleks, et bot "magaks" juhuslikult arvu sekundite võrra enne uue otsingutegevuse alustamist. Tüüpiliselt ei saa ükski bot ilma selleta hakkama. Kui käivitada eelnevalt antud kood, avaneb Chrome'i aken, mida bot kasutab veebisaitidega töötamiseks.
Teeme väikese eksperimendi ja avame eraldi aknas saidi kayak.com. Valime linna, kust kavatseme lennata, ja linna, kuhu soovime jõuda, samuti lennukuupäevad. Kuupäevade valimisel kontrollime, et vahemik oleks +-3 päeva. Olen kirjutanud koodi, arvestades seda, mida sait sellistele päringutele vastab. Kui teil on näiteks vaja otsida pileteid ainult kindlatel kuupäevadel, on väga tõenäoline, et peate boti koodi kohandama. Rääkides koodist, teen vastavad selgitused, kuid kui tunnete, et olete segaduses, andke mulle teada.
Nüüd vajutame otsingu käivitamise nupule ja vaatame aadressiribal linki. See peaks olema sarnane allolevas näites kasutatavale lingile, kus kuulutatakse välja muutuja kayak, mis hoiab URL-i ja kus kasutatakse meetodit get veebijuhendist. Otsingu nupule vajutamisel peaksid lehel ilmuma tulemused.
![]()
Kui kasutasin käsku get rohkem kui kaks-kolm korda mõne minuti jooksul, pakuti mulle reCaptcha kontrolli läbimist. Selle kontrolli võib läbida käsitsi ja jätkata katsetamist, kuni süsteem otsustab korraldada uue kontrolli. Kui ma skripti testisin, jäi mulje, et esimene otsing seanss läheb alati probleemideta, seega, kui soovite koodiga eksperimenteerida, peate lihtsalt perioodiliselt käsitsi kontrolli läbima ja jätma koodi jooksma, kasutades pikki intervallide otsingu seansside vahel. Ja kui tõsiselt mõelda, ei ole inimesel tõenäoliselt vaja pileti hindade kohta teavet, mis on saadud 10-minutiliste intervallidega otsinguoperatsioonide vahel.
Töötamine lehega kasutades XPath
Nii, me avasime akna ja laadisime saidi. Et saada teavet hindade ja muu kohta, peame kasutama XPath-i või CSS-valijate tehnoloogiat. Otsustasin jääda XPathi juurde ja ei tundnud vajadust CSS-valijate kasutamiseks, aga on täiesti võimalik töötada ka nii. Lehe sirvimine XPath-i abil võib osutuda keeruliseks ning isegi kui kasutate neid meetodeid, mida ma olen kirjeldanud, on see ... artiklis, kus rakendati lehe koodist vastavate identifikaatorite kopeerimist, mõistsin, et see ei ole tegelikult optimaalne viis vajalikest elementidest pääsemiseks. Muide, raamatust leiate suurepärase kirjelduse, kuidas lehti töödelda kasutades XPath-i ja CSS-valijate. Nii näeb välja vastav veebisõiduki meetod.
![]()
Nii et jätkame boti kallal töötamist. Kasutame programmi võimalusi, et leida kõige odavamaid pileteid. Järgmises pildis on punasega esile tõstetud XPath valija kood. Koodi vaatamiseks peate parema hiireklõpsuga valima huvipakkuva lehe elemendi ja valima ilmuvast menüüst käsu Vaata kood (Inspect). Seda käsku saab kutsuda erinevate lehe elementide jaoks, mille kood kuvatakse ja tõstetakse esile koodivaate aknas.

Lehe koodi vaatamine
Kinnitus, et minu järeldustes on tõsi kopeerimise puuduste kohta, leiate järgmiste omaduste kaudu.
Nii see välja näeb pärast koodi kopeerimist:
//*[@id="wtKI-price_aTab"]/div[1]/div/div/div[1]/div/span/spanSarnase kopeerimise jaoks peate parema hiireklõpsuga klõpsama huvitaval koodiosal ja valima ilmuvast menüüst käsu Koopia > Koopia XPath.
Nii nägi välja see, mida kasutasin Cheapest-nupu määramiseks:
cheap_results = '//'a[@data-code = "price"]' 
Käsk Koopia > Koopia XPath
On täiesti ilmne, et teine variant näeb välja oluliselt lihtsam. Selle kasutamisel otsitakse elementi a, millel on atribuut data-code, mis on võrdne price. Esimese variandi kasutamine otsib elementi, mille id on id wtKI-price_aTab , ja XPath tee elemendini näeb välja järgmine:. Selletaoline XPath-päring lehele teeb oma töö, kuid - vaid üks kord. Ma võin kohe öelda, et /div[1]/div/div/div[1]/div/span/spanmuutub järgmise lehe laadimisega. Sümbolite jada id wtKI muutub dünaamiliselt iga lehe laadimise korral, ja seetõttu on kood, millega see on seotud, pärast järjekordset lehe taaskäivitamist kasutu. Seetõttu kulutage veidi aega XPathiga tutvumisele. Need teadmised tulevad teile kasuks. Kuid tuleb märkida, et XPath-valijate kopeerimine võib olla kasulik, kui töötatakse piisavalt lihtsate veebisaitidega, ja kui see teile sobib, pole selles midagi halba.
Siiski tuleb märkida, et XPath-valijate kopeerimine võib osutuda kasulikuks lihtsate veebisaitide puhul, ja kui see teile sobib, siis pole selles midagi halba.
Nüüd mõtleme, kuidas saada kõiki otsingutulemusi mitmes reas, nimekirja sees. See on väga lihtne. Iga tulemus asub klassiga objekti sees resultWrapper. Kõikide tulemuste laadimine võib toimuda tsüklis, mis näeb välja nagu allpool toodud.
Tuleb märkida, et kui teil on eelmised selged, siis peate probleemideta aru saama enamus koodist, mida me analüüsime. Selle koodi töö käigus, et jõuda meie vajadusteni (tõepoolest — see on element, kuhu tulemus on mähitud), kasutame mingit mehhanismi tee määramiseks (XPath). Seda tehakse, et saada elemendi tekst ja panna see objekti, kust saab andmeid lugeda (alustatakse flight_containers, seejärel — flights_list).

Kuvatakse esimesed kolm rida ja me saame selgelt näha kõike, mis meil vajalik. Siiski on meil palju huvitavamaid viise, kuidas teavet hankida. Peame võtma andmed igast elemendist eraldi.
Lööme käima!
Lihtsaim on kirjutada funktsioon täiendavate tulemustega laadimiseks, seega alustame sellest. Soovin maksimeerida lendude arvu, mille kohta programm infot saab, ja samas mitte tekitada teenuses kahtlusi, mis võivad viia kontrollini, seega klõpsan korduvasti nuppu Load more results iga kord, kui leht kuvatakse. Selle koodi puhul tasub tähelepanu pöörata blokkile proovige, mille lisasin, kuna mõnikord nupp ei laadi korralikult. Kui ka teie selle probleemiga kokku puutute — kommenteerige selle funktsiooni kutsed funktsioonis start_kayak, mida me allpool käsitleme.
# Загрузка большего количества результатов для того, чтобы максимизировать объём собираемых данных
def load_more():
try:
more_results = '//a[@class = "moreButton"]'
driver.find_element_by_xpath(more_results).click()
# Вывод этих заметок в ходе работы программы помогает мне быстро выяснить то, чем она занята
print('sleeping.....')
sleep(randint(45,60))
except:
passNüüd, pärast seda funktsiooni põhjalikku analüüsi (mõnikord ma võin liialdada), oleme valmis kuulutama funktsiooni, mis tegeleb lehe kraapimisega.
Olen juba kogunud suure osa vajalikust järgmises funktsioonis, mille nimeks on page_scrape. Mõnikord, kui tagastatud andmed tee etappidest osutuvad ühendatud olevaks, kasutan nende eraldamiseks lihtsat meetodit. Näiteks, kui kasutan esmakordselt muutujaid section_a_list ja section_b_list. Meie funktsioon tagastab andmeframes flights_df, mis võimaldab meil eraldada tulemused, mis saadakse erinevate andmete sortimisviiside kasutamisega, ja hiljem — need kokku liita.
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 Ma olen püüdnud nimetada muutujaid nii, et kood oleks arusaadav. Pidage meeles, et muutujad, mis algavad sõnaga a viitavad tee esimeses etapis, samas kui b — teises. Liigume järgmise funktsiooni juurde.
Abimehhanismid
Nüüd on meil funktsioon, mis võimaldab laadida täiendavaid otsingu tulemusi, ja funktsioon nende tulemuste töötlemiseks. Seda artiklit võiks siin lõpetada, sest need kaks funktsiooni annavad kõik vajalikud vahendid lehtede kraapimiseks, mida saab iseseisvalt avada. Kuid me pole veel arutanud teatud abimehhanisme, millest varem rääkisime. Näiteks on see kood e-posti saatmiseks ja veel mõned asjad. Kõike seda saab leida funktsioonis start_kayak, mida me praegu vaatame.
Selle funktsiooni tööks on vajalikud andmed linnade ja kuupäevade kohta. Ta kasutab neid andmeid, et luua link muutujas kayak, mida kasutatakse lehe külastamiseks, kus on otsingu tulemused, järjestatud nende parima vastavuse järgi päringule. Pärast esimest kraapimise sessiooni töötame hindadega, mis asuvad tabelis lehe ülaosas. Täpsemalt, leiame pileti minimaalse hinna ja keskmise hinna. Kõik see, koos saidi antud prognoosiga, saadetakse e-posti teel. Lehel peaks vastav tabel olema vasakus ülanurgas. Tabeliga töötamine võib muide põhjustada viga otsimisel, kui kasutatakse täpseid kuupäevi, kuna sel juhul tabel lehel ei kuvatakse.
def start_kayak(city_from, city_to, date_start, date_end):
"""Linna koodid - need on IATA koodid!
Kuupäeva formaat - AAAA-KK-PÄEV"""
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))
# mõnikord ilmub hüpikaken, selle avastamiseks ja sulgemiseks saab kasutada try blokki
try:
xp_popup_close = '//*[@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('laeb rohkem.....')
# load_more()
print('algab esimene kraapimine.....')
df_flights_best = page_scrape()
df_flights_best['sort'] = 'best'
sleep(randint(60,80))
# Võtame tabelist, mis asub lehe ülaosas, kõige madalama hinna
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('lülitame odavama tulemuse juurde.....')
cheap_results = '//*[@data-code = "price"]'
driver.find_element_by_xpath(cheap_results).click()
sleep(randint(60,90))
print('laeb rohkem.....')
# load_more()
print('algab teine kraapimine.....')
df_flights_cheap = page_scrape()
df_flights_cheap['sort'] = 'cheap'
sleep(randint(60,80))
print('lülitame kiiremate tulemuste juurde.....')
quick_results = '//*[@data-code = "duration"]'
driver.find_element_by_xpath(quick_results).click()
sleep(randint(60,90))
print('laeb rohkem.....')
# load_more()
print('algab kolmas kraapimine.....')
df_flights_fast = page_scrape()
df_flights_fast['sort'] = 'fast'
sleep(randint(60,80))
# Uue raami salvestamine Exceli faili, mille nimi kajastab linnu ja kuupäevi
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('salvestatud df.....')
# Saab jälgida, kuidas saidi prognoos võrreldes reaalsusega käitub
xp_loading = '//*[@id="advice"]'
loading = driver.find_element_by_xpath(xp_loading).text
xp_prediction = '//*[@class="info-text"]'
prediction = driver.find_element_by_xpath(xp_prediction).text
print(loading+'n'+prediction)
# mõnikord on muutuja loading sees see string, mis hiljem põhjustab probleeme kirja saatmisega
# kui see juhtub - muudame selle "Not Sure"
weird = '¯_(ツ)_/¯'
if loading == weird:
loading = 'Pole kindel'
username = 'YOURMAIL@hotmail.com'
password = 'YOUR PASSWORD'
server = smtplib.SMTP('smtp.outlook.com', 587)
server.ehlo()
server.starttls()
server.login(username, password)
msg = ('Teema: Lennulehte Kraapiminenn
Odavaim lend: {}nKeskmine hind: {}nnSoovitus: {}nnSõnumi lõpp'.format(matrix_min, matrix_avg, (loading+'n'+prediction)))
message = MIMEMultipart()
message['From'] = 'YOURMAIL@hotmail.com'
message['to'] = 'YOUROTHERMAIL@domain.com'
server.sendmail('YOURMAIL@hotmail.com', 'YOUROTHERMAIL@domain.com', msg)
print('saadetud email.....')Ma testisin seda skripti Outlooki (hotmail.com) kontoga. Ma ei kontrollinud selle töökindlust Gmaili kontoga, kuigi see e-posti süsteem on väga populaarne, kuid valikuid on palju. Kui kasutate Hotmaili kontot, siis piisab, kui sisestate koodis oma andmed, et kõik töötaks.
Kui soovite aru saada, mis täpselt toimub funktsiooni erinevates osades, võite need kopeerida ja nendega katsetada. Koodi katsetamine on ainus viis selle tõeliselt mõistmiseks.
Valmis süsteem
Nüüd, kui oleme teinud kõik, millest rääkisime, saame luua lihtsa tsükli, kus kutsume esile meie funktsioonid. Skript küsib kasutajalt linnade ja kuupäevade andmeid. Kui testite skripti pideva uuesti käivitamisega, ei taha te tõenäoliselt igakord neid andmeid käsitsi sisestada, seega võite testimise ajaks vastavad read kommenteerida, eemaldades kommentaarid nende ridade pealt, kus on kindlalt määratletud skripti vajalikud andmed.
city_from = input('Kust linnast? ')
city_to = input('Kuhu? ')
date_start = input('Otsige millise lahkumiskuupäeva ümber? Palun kasutage ainult YYYY-MM-DD formaati ')
date_end = input('Millal tagasi? Palun kasutage ainult YYYY-MM-DD formaati ')
# 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('iteratsioon {} on lõpetatud @ {}'.format(n, strftime("%Y%m%d-%H%M")))
# Ootame 4 tundi
sleep(60*60*4)
print('unetus on lõppenud.....') Nii näeb välja skripti testkäivitus.

Skripti testkäivitus
Summary
Kui olete siia maani jõudnud, siis õnnitleme! Nüüd on teil töötav veebiskrapp, kuigi ma näen juba mitmeid võimalusi selle täiustamiseks. Näiteks saate selle integreerida Twilioga, et see, e-kirjade asemel, saadaks tekstsõnumeid. Võite kasutada VPN-i või midagi muud, et korraga saada tulemusi mitmelt serverilt. On ka aeg-ajalt esinev probleem saidi kasutaja kontrollimisega, et kas ta on inimene, kuid ka selle probleemi saab lahendada. Igal juhul on teil nüüd alus, mida võite soovi korral laiendada. Näiteks, et Exceli fail saadetaks kasutajale e-kirja manuses.
Ainult registreeritud kasutajad saavad küsitluses osaleda. , palun.
Kas kasutate veebiskrappimise tehnoloogiaid?
Jah
Ei
Hääletas 8 kasutajat. 1 kasutaja jäi erapooletuks.
Allikas: habr.com
