Autori i artikujt që po publikojmë sot thotë se qëllimi i tij është të flasë për zhvillimin e një web-scraper në Python duke përdorur Selenium, i cili kërkon çmimet e biletave të avionëve. Gjatë kërkimit për bileta përdoren datat fleksibile (+- 3 ditë nga datat e caktuara). Scraper ruan rezultatet e kërkimit në një skedar Excel dhe i dërgon një email atij që e ekzekuton me informacionin e përgjithshëm për atë që arriti të gjejë. Qëllimi i këtij projekti është ndihma për udhëtarët në gjetjen e ofertave më të favorshme.
Nëse, duke u marrë me materialin, ndiheni të humbur — shikoni në artikullin.
Çfarë do të kërkojmë?
Jeni të lirë të përdorni sistemin e përshkruar këtu ashtu siç dëshironi. Unë, për shembull, e kam përdorur atë për të kërkuar ekskursione fundjavash dhe bileta për qytetin tim të lindjes. Nëse jeni serioz për të gjetur bileta të favorshme — mund të ekzekutoni skriptin në një server (një i thjeshtë, për 130 rubla në muaj, është mëse i mjaftueshëm për këtë) dhe të bëni që ai të ekzekutohet një apo dy herë në ditë. Rezultatet e kërkimit do t'ju vijnë në email. Për më tepër, unë rekomandoj të konfiguroni gjithçka në mënyrë që skripti të ruajë një skedar Excel me rezultatet e kërkimit në një dosje Dropbox, që do t'ju lejojë të shikoni skedarët e tillë nga kudo dhe në çdo kohë. Unë ende nuk kam gjetur tarifa me gabime, por besoj se kjo është e mundur.

Я пока не нашёл тарифов с ошибками, но полагаю, что это возможно
Gjatë kërkimit, siç është thënë, përdoret "data fleksibile", skripti gjen oferta që ndodhen brenda tre ditëve nga datat e caktuara. Megjithatë, kur ekzekutohet skripti, kërkimi bëhet vetëm për një drejtim, nuk është e vështirë ta përmirësosh atë për të mbledhur të dhëna për disa drejtime fluturimesh. Me ndihmën e tij mund të kërkoni deri edhe tarifa me gabime, gjetjet e tilla mund të jenë mjaft interesante.
Pse nevojitet një web-scraper tjetër?
Kur fillova të merrem me web scraping, sinqerisht, nuk ishte shumë ergjatuar për mua. Dëshiroja të bëja më shumë projekte në fushën e modelimit parashikues, analitikës financiare, dhe ndoshta në analizën e ngjyrave emocionale të teksteve. Por doli se ishte shumë interesante të merresh me krijimin e një programi që mbledh të dhëna nga faqet e internetit. Ndërsa thellohesha në këtë temë, kuptova se pikërisht web scraping është "motorri" i internetit.
Ndoshta do të vendosni se kjo është një deklaratë e guximshme. Por mendoni për faktin se kompania Google filloi me një web-scraper që Larry Page krijoi duke përdorur Java dhe Python. Robotët e Google eksplorojnë dhe vazhdojnë të eksplorojnë internetin, duke u përpjekur të ofrojnë përdoruesve të tyre përgjigjet më të mira për pyetjet e tyre. Web scraping ka një numër të pafund aplikimesh, dhe edhe nëse ju në fushën e Data Science interesoheni për diçka tjetër, për të marrë të dhëna për analiza do t'ju nevojiten disa aftësi scraping.
Disa nga teknikët e përdorur këtu i kam gjetur në një të shkëlqyer për web scraping, që e kam marrë kohët e fundit. Ajo përmban shumë shembuj të thjeshtë dhe ide për aplikimin praktik të mësimeve të marra. Për më tepër, ka një kapitull shumë interesant mbi kapërcimin e verifikimeve reCaptcha. Për mua ky ishte një zbulim, pasi nuk dija që ekzistojnë mjete të veçanta dhe madje shërbime të tëra për zgjidhjen e detyrave të tilla.
A doni të udhëtoni?!
Një pyetje e thjeshtë dhe mjaft e padëmshme, e cila u paraqit në titullin e këtij seksioni, shpesh merr një përgjigje pozitive, e shoqëruar me disa histori nga udhëtimet e atij të cilit ia bëhet pyetja. Shumica prej nesh do të bien dakord se udhëtimet janë një mënyrë e shkëlqyer për t'u zhytur në kultura të reja dhe për të zgjeruar horizontet tona. Megjithatë, nëse i bëni dike pyetje nëse i pëlqen të kërkojë bileta avioni, jam i sigurt se përgjigjja do të jetë shumë më pak pozitive. Në fakt, këtu na vjen në ndihmë Python.
Detyra e parë që duhet të zgjidhim në rrugën e krijimit të një sistemi kërkese për informacion rreth biletave të avionëve është zgjedhja e një platforme të përshtatshme nga e cila do të marrim informacionin. Zgjidhja e kësaj detyre nuk ishte e lehtë, por përfundimisht zgjodha shërbimin Kayak. Provova shërbimet Momondo, Skyscanner, Expedia, dhe disa të tjera, por mekanizmat e mbrojtjes nga robotët në këto burime ishin të pamposhtur. Pas disa përpjekjeve, gjatë të cilave, për të bindur sistemet se isha njeri, më duhej të merresha me semaforë, kalime këmbësorësh dhe biçikleta, vendosa se Kayak ishte shërbimi më i përshtatshëm për mua, pavarësisht se edhe këtu, nëse ngarkon shumë faqe brenda një kohe të shkurtër, fillojnë kontrollet. Arrita të bëja që bodi të dërgonte kërkesa në faqe në intervale nga 4 deri në 6 orë, dhe gjithçka funksiononte mirë. Herë pas here, ndodhin vështirësi gjatë punës me Kayak, por nëse ju shqetësojnë kontrollet, duhet të zgjidhni ose të merren me to manualisht, më pas të nisni botin, ose të prisni disa orë dhe kontrollet duhet të ndalojnë. Nëse është e nevojshme, mund ta përshtatni kodin për një platformë tjetër, dhe nëse bëni këtë — mund ta përcillni atë në komentet.
Nëse sapo po filloni të njihni web scraping dhe nuk e dini pse disa faqe interneti luftojnë me të gjitha forcat, para se të filloni projektin tuaj të parë në këtë fushë — bëni vetes një favore dhe kërkoni në Google materiale me fjalët "etiketa e web scraping-ut". Eksperimentet tuaja mund të përfundojnë më shpejt se sa mendoni, në rastin që angazhoheni me web scraping in ë mënyrë të pamenduar.
Fillimi i punës
Ja një përmbledhje e përgjithshme e asaj që do të ndodhë në kodin tonë të web scraper-it:
- Importimi i librarive të nevojshme.
- Hapja e një skede në Google Chrome.
- Thirrja e funksionit që nis botin, duke i kaluar qytetet dhe datat që do të përdoren gjatë kërkimit të biletave.
- Ky funksion merr rezultatet e para të kërkimit, të renditura sipas kriterit më tërheqës (best), dhe klikon në butonin për ngarkimin e rezultateve shtesë.
- Një funksion tjetër mbledh të dhënat nga e gjithë faqja dhe kthehet një frame të dhënash.
- Dy hapat e mëparshëm kryhen duke përdorur lloje renditjeje sipas çmimeve të biletave (cheap) dhe sipas shpejtësisë së fluturimit (fastest).
- Përdoruesit e skriptit iu dërgohet një email që përmban një përmbledhje të shkurtër të çmimeve të biletave (biletat më të lira dhe çmimi mesatar), dhe frame-i i të dhënave të renditura sipas tri kritereve të përmendura më lart ruhet si një skedë Excel.
- Të gjitha veprimet e mësipërme kryhen në një cikël nëpërmjet një intervali të caktuar kohor.
Duhet të theksohet se çdo projekt Selenium fillon me web-driver-in. Unë përdor , punoj me Google Chrome, por ka edhe mundësi të tjera. PhantomJS dhe Firefox janë gjithashtu të njohura. Pas shkarkimit të driver-it, duhet ta vendosni në dosjen e duhur, dhe përgatitja për përdorimin e tij përfundon këtu. Në rreshtat e parë të skriptit tonë hapet një skedë e re Chrome.
Kujdesi që po tregoj këtu nuk synon të hapë horizonte të reja për kërkimin e ofertave të favorshme për biletat e avionëve. Ekzistojnë teknika më të avancuara për të kërkuar këtë lloj oferte. Mua më intereson të ofroj lexuesve të këtij materiali një mënyrë të thjeshtë, por praktikisht të aplikueshme për zgjidhjen e kësaj detyre.
Ja kodi për të cilin folëm më sipër.
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
# Përdorni këtu rrugën tuaj për chromedriver!
chromedriver_path = 'C:/{YOUR PATH HERE}/chromedriver_win32/chromedriver.exe'
driver = webdriver.Chrome(executable_path=chromedriver_path) # Ky komandë hap dritaren e Chrome
sleep(2) Në fillim të kodit mund të shihni komandat e importit të pakove që përdoren gjatë gjithë projektit tonë. Kështu, randint përdoret për të bërë që boti "të fle" për një numër të rastësishëm sekondash përpara se të fillojë një operacion të ri kërkimi. Normalisht, asnjë bot nuk e shmang këtë. Nëse ekzekutoni kodin e mësipërm, do të hapet një dritare Chrome, e cila do të përdoret nga boti për të punuar me faqet.
Do të kryejmë një eksperiment të vogël dhe do të hapim në një dritare të veçantë faqen kayak.com. Do të zgjedhim qytetin nga i cili do të fluturojmë, dhe qytetin në të cilin dëshirojmë të shkojmë, si dhe datat e fluturimeve. Kur të zgjedhim datat, do të sigurohemi që të përdorim një interval prej +-3 ditësh. Kam shkruar kodin duke marrë parasysh se çfarë ofron faqja në përgjigje të kërkesave të tilla. Ndërsa flas për kodin, bëj përshkrime përkatëse, por nëse ndiheni të ngatërruar, mos hezitoni të më informoni.
Tani shtypim butonin për të filluar kërkimin dhe shikojmë lidhjen në shiritin adresës. Ajo duhet të jetë e ngjashme me lidhjen që unë përdor si shembull më poshtë, aty ku shpallet variabli kayak, i cili ruan URL-në, dhe përdoret metoda merr e web-driverit. Pas klikimit në butonin e kërkimit, rezultatet duhet të shfaqen në faqe.
![]()
Kur përdora komandën merr më shumë se dy-tre herë brenda disa minutash, më propozonin të kaloj një verifikim duke përdorur reCaptcha. Ky verifikim mund të kalojë manualisht dhe të vazhdoj eksperimentet deri sa sistemi të vendosë të bëjë një verifikim të ri. Kur testova skriptin, ndjeva se seanca e parë e kërkimit gjithmonë kalonte pa probleme, kështu që, nëse dëshironi të eksperimentoni me kodin, do t'ju duhet të kaloni manualisht verifikimin dhe ta lini kodin të ekzekutohet, duke përdorur intervale të gjata midis seancave të kërkimit. Po ashtu, nëse mendoni mirë, një njeri vështirë se do të ketë nevojë për informacion mbi çmimet e biletave që janë marrë me intervale 10-minutëshe mes operacioneve të kërkimit.
Puna me faqen duke përdorur XPath
Pra, kemi hapur dritaren dhe ngarkuar faqen. Për të marrë informacion mbi çmimet dhe detaje të tjera, duhet të përdorim teknologjinë XPath ose CSS selectors. Kam vendosur të ndalem te XPath dhe nuk kam ndjerë nevojën për të përdorur CSS selectors, por është tërësisht e mundshme të punohet edhe kështu. Navigimi në faqe me përdorimin e XPath mund të jetë një detyrë e vështirë, dhe edhe nëse përdorni metodat që kam përshkruar në artikullin, ku përdorej kopjimi i identifikuesve përkatës nga kodi i faqes, e kuptova se këto në të vërtetë nuk ishin mënyra optimale për të arritur elementët e nevojshëm. Në fakt, në libër mund të gjeni një përshkrim të shkëlqyer të bazave të punës me faqet duke përdorur XPath dhe CSS selectors. Ja si duket metoda përkatëse e web-driverit.
![]()
Pra, vazhdojmë punën mbi robotin. Do të përdorim mundësitë e programit për të zgjedhur biletat më të lira. Në imazhin e ardhshëm, kodi i selektorit XPath është theksuar me të kuqe. Për të parë kodin, duhet të klikoni me të djathtën në elementin e interesit dhe të zgjidhni komandën Shiko kodin (Inspect) nga menuja që shfaqet. Kjo komandë mund të thirret për elemente të ndryshme në faqe, kodi i të cilave do të shfaqet dhe do të theksohet në dritaren e shikimit të kodit.

Shikimi i kodit të faqes
Për të gjetur konfirmimin e argumenteve të mia mbi mangësitë e kopjimit të selektorëve nga kodi, vini re këto veçori.
Ja çfarë ndodh kur kopjohet kodi:
//*[@id="wtKI-price_aTab"]/div[1]/div/div/div[1]/div/span/spanPër të kopjuar diçka të tillë, duhet të klikoni me të djathtën në pjesën e interesit të kodit dhe të zgjidhni në menu komandën Kopjo > Kopjo XPath.
Ja çfarë kam përdorur për të identifikuar butonin Cheapest:
cheap_results = ‘//a[@data-code = "price"]’ 
Komanda Kopjo > Kopjo XPath
Është krejtësisht e qartë se varianti i dytë duket shumë më e thjeshtë. Me përdorimin e tij, bëhet kërkimi i elementit a, i cili ka atributin data-code, i barabartë me price. Me përdorimin e variantit të parë bëhet kërkimi i elementit id i cili është wtKI-price_aTab, ndërkohë që rruga XPath deri në element duket si /div[1]/div/div/div[1]/div/span/span. Një kërkesë e tillë XPath në faqe do të bëjë punën e vet, por - vetëm një herë. Mund ta them tani se id do të ndryshojë me ngarkimin e ardhshëm të faqes. Sekuenca e simboleve wtKI ndryshohet në mënyrë dinamike me çdo ngarkim të faqes, si rezultat kodi në të cilin ajo përdoret do të bëhet i pavlefshëm pas një rifreskimi të radhës të faqes. Prandaj, kushtojini pak kohë për të kuptuar XPath. Këto njohuri do t'ju shërbejnë mirë.
Megjithatë, duhet theksuar se kopjimi i selektorëve XPath mund të jetë i dobishëm kur punoni me faqe mjaft të thjeshta, dhe nëse ju përshtatet kjo, nuk ka asnjë problem me të.
Tani le të mendojmë se si të veprojmë nëse duam të marrim të gjitha rezultatet e kërkimit në disa rreshta, brenda një liste. Mjafton. Çdo rezultat është brenda një objekti me klasën resultWrapper. Shkarkimi i të gjitha rezultateve mund të bëhet në një cikël të ngjashëm me atë që do të shihet më poshtë.
Duhet të theksohet se nëse ju është e qartë ajo që u tha më lart, atëherë duhet të kuptoni pa ndonjë problem shumicën e kodit që ne do të shqyrtojmë. Gjatë punës me këtë kod, në atë që na nevojitet (në fakt — ky është elementi që përfshin rezultatin), ne qasemi nëpërmjet një mekanizmi për të treguar rrugën (XPath). Kjo bëhet për të marrë tekstin e elementit dhe për ta vendosur atë në një objekt, nga i cili mund të lexojmë të dhënat (së pari përdoret flight_containers, pastaj — flights_list).

Të parat tre rreshta shfaqen dhe ne mund të shohim qartë gjithçka që na nevojitet. Megjithatë, kemi dhe mënyra më interesante për të marrë informacion. Na nevojitet të marrim të dhënat nga çdo element ndaras.
Në punë!
Më lehtë është të shkruani një funksion për të shkarkuar rezultate shtesë, ndaj do të fillojmë me të. Doja të maksimizoja numrin e flukseve për të cilat programi merr informacione, pa e kthyer shërbimin në dyshim, kështu që unë klikoj një herë në butonin 'Load more results' sa herë që shfaqet një faqe. Në këtë kod, ia vlen të kushtohet vëmendje bllokut provo, të cilin e shtova sepse ndonjëherë butoni nuk shkarkohet siç duhet. Nëse ju përballeni me këtë problem, komenton funksionin në kodin e funksionit start_kayak, të cilin do ta shqyrtojmë më poshtë.
# Загрузка большего количества результатов для того, чтобы максимизировать объём собираемых данных
def load_more():
try:
more_results = '//a[@class = "moreButton"]'
driver.find_element_by_xpath(more_results).click()
# Вывод этих заметок в ходе работы программы помогает мне быстро выяснить то, чем она занята
print('sleeping.....')
sleep(randint(45,60))
except:
passTani, pas një analize të gjatë të këtij funksioni (herë pas here mund të ndikohem), ne jemi gati të shpallim një funksion që do të merret me skrapimin e faqes.
Unë tashmë kam mbledhur pjesën më të madhe të asaj që nevojitet, në funksionin e ardhshëm, të quajtur page_scrape. Ndonjëherë të dhënat e kthyera për fazat e rrugës janë të bashkuara, për t'i ndarë ato përdor një metodë të thjeshtë. Për shembull, kur përdor për herë të parë variablat section_a_list dhe section_b_list. Funksioni ynë kthen një kornizë të dhënash flights_df, kjo na lejon të ndajmë rezultatin e marrjes duke përdorur metoda të ndryshme të renditjes së të dhënave dhe më vonë — t'i bashkojmë ato.
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 Kam përpiqur të emërtoj variablat në mënyrë që kodi të jetë i kuptueshëm. Mos harroni se variablat që fillojnë me a kanë të bëjnë me fazën e parë të rrugës, ndërsa b ka të bëjë me të dytën. Të kalojmë në funksionin e ardhshëm.
Mekanizmat ndihmës
Tani kemi një funksion që lejon shkarkimin e rezultateve shtesë të kërkimit dhe një funksion për përpunimin e këtyre rezultateve. Kjo artikull mund të ishte përfunduar këtu, pasi këto dy funksione ofrojnë gjithçka të nevojshme për skrapimin e faqeve që mund të hapen vetë. Por ne ende nuk kemi shqyrtuar disa mekanizma ndihmës, për të cilat u fol më lart. Për shembull — është kodi për të dërguar email dhe disa gjëra të tjera. Të gjitha këto mund të gjenden në funksionin start_kayak, të cilin tani do ta shqyrtojmë.
Për të funksionuar ky funksion ka nevojë për informacione rreth qyteteve dhe datave. Ai, duke përdorur këto informacione, formon një lidhje në variablën kayak, e cila përdoret për të kaluar në faqen ku do të jenë rezultatet e kërkimit, të renditura sipas përshtatshmërisë së tyre me kërkesën. Pas seancës së parë të skrapimit, ne do të punojmë me çmimet që ndodhen në tabelën, në pjesën e sipërme të faqes. Në veçanti, do të gjejmë çmimin minimal të biletës dhe çmimin mesatar. Të gjitha këto, së bashku me parashikimin e bërë nga faqja, do të dërgohen me email. Në faqen përkatëse, tabela duhet të jetë në qoshen e majtë të sipërme. Punimi me këtë tabelë, nga ana tjetër, mund të shkaktojë një gabim gjatë kërkimit me data të sakta, pasi në këtë rast tabela në faqe nuk shfaqet.
def start_kayak(city_from, city_to, date_start, date_end):
"""Kodet e qyteteve - janë kodet IATA!
Formati i datës - 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))
# ndonjëherë shfaqet një dritare pop-up, për ta kontrolluar dhe mbyllur mund të përdorim blokun 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('duke ngarkuar më shumë.....')
# load_more()
print('duke filluar skrapimin e parë.....')
df_flights_best = page_scrape()
df_flights_best['sort'] = 'best'
sleep(randint(60,80))
# Do të marrim çmimin më të ulët nga tabela, e cila ndodhet në pjesën e sipërme të faqes
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('duke kaluar në rezultatet më të lira.....')
cheap_results = '//a[@data-code = "price"]'
driver.find_element_by_xpath(cheap_results).click()
sleep(randint(60,90))
print('duke ngarkuar më shumë.....')
# load_more()
print('duke filluar skrapimin e dytë.....')
df_flights_cheap = page_scrape()
df_flights_cheap['sort'] = 'cheap'
sleep(randint(60,80))
print('duke kaluar në rezultatet më të shpejta.....')
quick_results = '//a[@data-code = "duration"]'
driver.find_element_by_xpath(quick_results).click()
sleep(randint(60,90))
print('duke ngarkuar më shumë.....')
# load_more()
print('duke filluar skrapimin e tretë.....')
df_flights_fast = page_scrape()
df_flights_fast['sort'] = 'fast'
sleep(randint(60,80))
# Ruajtja e kuadratit të ri në një skedar Excel, emri i të cilit reflekton qytetet dhe datat
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('ruajtur df.....')
# Mund të kontrolloni se si parashikimi i dhënë nga faqja përputhet me realitetin
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)
# ndonjëherë në variablën loading ndodhet kjo frazë, e cila më vonë shkakton probleme me dërgimin e emailit
# nëse ndodhi, e ndryshojmë në "Not Sure"
weird = '¯_(ツ)_/¯'
if loading == weird:
loading = 'Jo i sigurt'
username = 'YOUREMAIL@hotmail.com'
password = 'YOUR PASSWORD'
server = smtplib.SMTP('smtp.outlook.com', 587)
server.ehlo()
server.starttls()
server.login(username, password)
msg = ('Subject: Flight Scrapernn
Çmimi më i lirë: {}nÇmimi mesatar: {}nnRekomandimi: {}nnFundi i mesazhit'.format(matrix_min, matrix_avg, (loading+'n'+prediction)))
message = MIMEMultipart()
message['From'] = 'YOUREMAIL@hotmail.com'
message['to'] = 'YOUROTHEREMAIL@domain.com'
server.sendmail('YOUREMAIL@hotmail.com', 'YOUROTHEREMAIL@domain.com', msg)
print('e dërguar email.....')E kam testuar këtë skenar duke përdorur një llogari Outlook (hotmail.com). Nuk e kam kontrolluar për funksionimin e tij me llogarinë Gmail, kjo sistem postimi është shumë popullor, por ka shumë variante të mundshme. Nëse përdorni llogarinë Hotmail, atëherë për të bërë që gjithçka të funksionojë, ju mjafton të vendosni të dhënat tuaja në kod.
Nëse dëshironi të kuptoni se çfarë ekzekutohet në pjesë të veçanta të kodit të kësaj funksioni, mund t'i kopjoni ato dhe të eksperimentoni me to. Eksperimentimi me kodin është mënyra e vetme për ta kuptuar mirë.
Sistemi i gatshëm
Tani, kur është bërë gjithçka që kemi diskutuar, mund të krijojmë një cikël të thjeshtë ku thirremi funksionet tona. Skripti pyet përdoruesin për të dhënat e qyteteve dhe datave. Kur testoni me ripërtëritje të vazhdueshme të skriptit, ndoshta nuk do të donit të jepni këto të dhëna manualisht çdo herë, kështu që rreshtat përkatës, për kohën e testimit, mund të komentohen, duke hequr komentimin te ato që kanë të dhënat e nevojshme të koduara.
city_from = input('Nga cili qytet? ')
city_to = input('Ku të? ')
date_start = input('Rreth cilës datë nisjeje të kërkoni? Ju lutemi përdorni vetëm formatin YYYY-MM-DD ')
date_end = input('Kur ktheheni? Ju lutemi përdorni vetëm formatin YYYY-MM-DD ')
# 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('iterimi {} përfundoi @ {}'.format(n, strftime("%Y%m%d-%H%M")))
# Presim 4 orë
sleep(60*60*4)
print('prerja e mbaroi.....') Ja si duket një fillim testimi i skenarit.

Fillimi i testimit të skenarit
Përfundimet
Nëse e keni arritur këtë pikë — urime! Tani keni një skraper funksional të uebit, edhe pse unë shoh shumë mundësi për ta përmirësuar atë. Për shembull, mund ta integroni me Twilio, në mënyrë që në vend të emaileve, të dërgoni mesazhe tekstuale. Mund të përdorni një VPN ose diçka tjetër për të marrë njëkohësisht rezultate nga disa serverë. Ka gjithashtu një problem të përkohshëm me verifikimin nëse përdoruesi i faqes është njeri, por ky problem gjithashtu mund të zgjidhet. Në çdo rast, tani keni një bazë që, nëse dëshironi, mund ta zgjeroni. Për shembull, të bëni që skedari Excel të dërgohet si një shtesë në emailin e përdoruesit.
Vetëm përdoruesit e regjistruar mund të marrin pjesë në anketë. , ju lutemi.
A po përdorni teknologjitë e skrapimit të uebit?
Po
Jo
8 përdorues kanë votuar. 1 përdorues është abstenuar.
Burimi: habr.com
