Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд

Муаллифи мақола, ки тарҷумаи онро имрӯз нашр мекунем, мегӯяд, ки ҳадафи он сӯҳбат дар бораи таҳияи веб скрепер дар Python бо истифода аз Selenium аст, ки нархи чиптаҳои ҳавопайморо ҷустуҷӯ мекунад. Ҳангоми ҷустуҷӯи чиптаҳо санаҳои тағйирпазир истифода мешаванд (+- 3 рӯз нисбат ба санаҳои муайяншуда). Скрепер натиҷаҳои ҷустуҷӯро дар файли Excel захира мекунад ва ба шахсе, ки ҷустуҷӯро иҷро кардааст, бо мухтасари он чизе, ки онҳо ёфтаанд, ба почтаи электронӣ мефиристад. Ҳадафи ин лоиҳа кӯмак ба сайёҳон дар пайдо кардани аҳдҳои беҳтарин аст.

Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд

Агар ҳангоми фаҳмидани мавод шумо худро гумшуда ҳис кунед, ба он назар андозед ин мақола.

Мо чиро меҷӯем?

Шумо озодед, ки системаи дар ин ҷо тавсифшударо мувофиқи хоҳишатон истифода баред. Масалан, ман онро барои ҷустуҷӯи сафарҳои рӯзҳои истироҳат ва чиптаҳо ба зодгоҳам истифода кардам. Агар шумо дар бораи дарёфти чиптаҳои фоидаовар ҷиддӣ бошед, шумо метавонед скриптро дар сервер иҷро кунед (оддӣ сервер, барои 130 рубл дар як моҳ, барои ин хеле мувофиқ аст) ва боварӣ ҳосил кунед, ки он дар як рӯз як ё ду маротиба кор мекунад. Натиҷаҳои ҷустуҷӯ ба шумо тавассути почтаи электронӣ фиристода мешаванд. Илова бар ин, ман тавсия медиҳам, ки ҳама чизро танзим кунед, то скрипт файли Excel-ро бо натиҷаҳои ҷустуҷӯ дар ҷузвдони Dropbox захира кунад, ки ба шумо имкон медиҳад, ки чунин файлҳоро аз ҳама ҷо ва дар вақти дилхоҳ дидан кунед.

Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд
Ман то ҳол тарофаҳоро бо хатогиҳо наёфтаам, аммо ман фикр мекунам, ки ин имконпазир аст

Ҳангоми ҷустуҷӯ, тавре ки аллакай зикр гардид, "санаи тағйирёбанда" истифода мешавад; скрипт пешниҳодҳоеро пайдо мекунад, ки дар давоми се рӯзи санаҳои додашуда мебошанд. Гарчанде ки ҳангоми иҷро кардани скрипт, он танҳо дар як самт пешниҳодҳоро ҷустуҷӯ мекунад, онро тағир додан осон аст, то он метавонад маълумотро дар бораи якчанд самтҳои парвоз ҷамъ кунад. Бо ёрии он шумо ҳатто метавонед тарифҳои хаторо ҷустуҷӯ кунед, чунин бозёфтҳо метавонанд хеле ҷолиб бошанд.

Чаро ба шумо скреперҳои дигари веб лозим аст?

Вақте ки ман бори аввал ба скрепинги веб сар кардам, ростқавлона ман ба он махсусан таваҷҷӯҳ надоштам. Ман мехостам лоиҳаҳои бештареро дар соҳаи моделсозии пешгӯишаванда, таҳлили молиявӣ ва эҳтимолан дар соҳаи таҳлили ранги эмотсионалии матнҳо иҷро кунам. Аммо маълум шуд, ки фаҳмидани тарзи сохтани барномае, ки маълумотро аз вебсайтҳо ҷамъ мекунад, хеле ҷолиб буд. Вақте ки ман ин мавзӯъро омӯхтам, ман фаҳмидам, ки скрепинг "муҳаррики" Интернет аст.

Шояд шумо фикр кунед, ки ин изҳороти хеле далерона аст. Аммо ба назар гиред, ки Google бо веб скрепер оғоз кард, ки Ларри Пейҷ бо истифода аз Java ва Python сохта шудааст. Роботҳои Google интернетро меомӯзанд ва кӯшиш мекунанд, ки ба корбаронаш ҷавобҳои беҳтаринро ба саволҳои худ пешниҳод кунанд. Веб скрепинг дорои истифодаи беохир аст ва ҳатто агар шумо ба чизи дигаре дар Data Science таваҷҷӯҳ дошта бошед, барои ба даст овардани маълумоте, ки шумо бояд таҳлил кунед, ба шумо баъзе малакаҳои скрепинг лозим аст.

Ман баъзе аз техникаи истифода дар ин ҷо дар олиҷаноб ёфт китоб дар бораи веб скрепинг, ки ман ба наздикӣ ба даст овардам. Дар он бисёр мисолҳо ва ғояҳои оддӣ барои татбиқи амалии чизҳои омӯхтаатон мавҷуданд. Илова бар ин, як боби хеле ҷолиб дар бораи гузаштан аз чекҳои reCaptcha мавҷуд аст. Ин барои ман ҳамчун хабар омад, зеро ман ҳатто намедонистам, ки асбобҳои махсус ва ҳатто тамоми хидматҳо барои ҳалли чунин мушкилот вуҷуд доранд.

Оё шумо саёҳатро дӯст медоред?!

Ба саволи оддӣ ва безараре, ки дар сарлавҳаи ин бахш дода шудааст, шумо метавонед аксар вақт ҷавоби мусбӣ шунид, ки бо ҳамроҳии як ҷуфт ҳикояҳо аз сафарҳои шахсе, ки ин савол ба ӯ дода шудааст. Аксари мо розӣ мешавем, ки саёҳат як роҳи олиҷанобест барои дар муҳити нави фарҳангӣ ғарқ шудан ва васеъ кардани уфуқҳои шумо. Аммо, агар шумо аз касе пурсед, ки оё онҳо ҷустуҷӯи чиптаҳои ҳавопайморо дӯст медоранд, ман боварӣ дорам, ки ҷавоб он қадар мусбат нахоҳад буд. Аслан, Python дар ин ҷо ба кӯмаки мо меояд.

Вазифаи аввалине, ки мо бояд дар роҳи ташкили системаи ҷустуҷӯи маълумот дар бораи чиптаҳои ҳавопаймо ҳал кунем, ин интихоби платформаи мувофиқе мебошад, ки мо аз он маълумот мегирем. Ҳалли ин мушкил бароям осон набуд, вале дар ниҳоят хидмати каякро интихоб кардам. Ман хидматҳои Momondo, Skyscanner, Expedia ва чанде дигарро санҷидаам, аммо механизмҳои муҳофизати роботҳо дар ин захираҳо ғайриимкон буданд. Пас аз якчанд кӯшишҳо, ки дар давоми он ман маҷбур шудам, ки бо чароғҳои светофор, гузаргоҳҳои пиёдагард ва дучархаҳо сару кор дошта, системаҳоро бовар кунонам, ки ман одам ҳастам, ман қарор додам, ки кайак барои ман беҳтар аст, сарфи назар аз он ки ҳатто агар саҳифаҳои аз ҳад зиёд бор карда шаванд ҳам. дар як муддати кутох, ва тафтиш низ огоз меёбад. Ман тавонистам, ки бот бо фосилаи 4 то 6 соат дархостҳо ба сайт фиристад ва ҳама чиз хуб кор кард. Баъзан ҳангоми кор бо Kayak мушкилот ба миён меоянд, аммо агар онҳо шуморо бо чекҳо хашмгин кунанд, шумо бояд ё бо онҳо дастӣ кор кунед ва пас ботро оғоз кунед ё чанд соат интизор шавед ва чекҳо бояд қатъ шаванд. Агар лозим бошад, шумо метавонед рамзро барои платформаи дигар ба осонӣ мутобиқ кунед ва агар ин тавр кунед, шумо метавонед дар шарҳҳо гузориш диҳед.

Агар шумо ҳоло бо скрепинги веб оғоз карда истода бошед ва намедонед, ки чаро баъзе вебсайтҳо бо он мубориза мебаранд, пас пеш аз оғози лоиҳаи аввалини худ дар ин самт, ба худ як некӣ кунед ва аз рӯи калимаҳои "этикети веб скрепинг" ҷустуҷӯ кунед. . Таҷрибаҳои шумо метавонанд зудтар аз он ки шумо фикр кунед, ба итмом расад, агар шумо беақлона веб скрепинг кунед.

саршавӣ

Дар ин ҷо шарҳи умумии он дар коди скреперҳои веби мо чӣ мешавад:

  • Китобхонаҳои лозимиро ворид кунед.
  • Кушодани ҷадвали Google Chrome.
  • Функсияеро занг занед, ки ботро оғоз мекунад ва ба он шаҳрҳо ва санаҳоеро, ки ҳангоми ҷустуҷӯи чиптаҳо истифода мешаванд, гузаронед.
  • Ин функсия аввалин натиҷаҳои ҷустуҷӯро мегирад, ки аз рӯи беҳтаринҳо мураттаб шудаанд ва тугмаро пахш мекунад, то натиҷаҳои бештар бор кунад.
  • Функсияи дигар маълумотро аз тамоми саҳифа ҷамъ мекунад ва чаҳорчӯбаи маълумотро бармегардонад.
  • Ду қадами қаблӣ бо истифода аз навъҳои ҷудокунӣ аз рӯи нархи чипта (арзон) ва суръати парвоз (зудтарин) иҷро карда мешаванд.
  • Ба корбари скрипт паёми электронӣ фиристода мешавад, ки дорои хулосаи нархҳои чипта (арзонтарин чиптаҳо ва нархи миёна) мебошад ва чаҳорчӯбаи маълумот бо маълумот аз рӯи се нишондиҳандаи дар боло зикршуда ҳамчун файли Excel захира карда мешавад.
  • Ҳамаи амалҳои дар боло зикршуда дар як давра пас аз як давраи муайян иҷро карда мешаванд.

Бояд қайд кард, ки ҳар як лоиҳаи Selenium бо драйвери веб оғоз меёбад. ман истифода мебарам Chromedriver, Ман бо Google Chrome кор мекунам, аммо имконоти дигар вуҷуд дорад. PhantomJS ва Firefox низ маъмуланд. Пас аз зеркашии драйвер, шумо бояд онро дар папкаи мувофиқ ҷойгир кунед ва ин омодагии истифодаи онро ба анҷом мерасонад. Сатрҳои аввали скрипти мо ҷадвали нави Chrome-ро мекушоянд.

Дар хотир доред, ки дар ҳикояи худ ман кӯшиш намекунам, ки уфуқҳои навро барои дарёфти аҳдҳои бузург дар чиптаҳои ҳавопаймо кушоям. Усулҳои хеле пешрафтаи ҷустуҷӯи чунин пешниҳодҳо мавҷуданд. Ман танҳо мехоҳам ба хонандагони ин мавод роҳи оддӣ, вале амалии ҳалли ин мушкилотро пешниҳод кунам.

Ин аст коде, ки мо дар боло гуфта будем.

from time import sleep, strftime
from random import randint
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import smtplib
from email.mime.multipart import MIMEMultipart

# Используйте тут ваш путь к chromedriver!
chromedriver_path = 'C:/{YOUR PATH HERE}/chromedriver_win32/chromedriver.exe'

driver = webdriver.Chrome(executable_path=chromedriver_path) # Этой командой открывается окно Chrome
sleep(2)

Дар оғози код шумо метавонед фармонҳои воридоти бастаҳоро бинед, ки дар тамоми лоиҳаи мо истифода мешаванд. Пас, randint истифода бурда мешавад, ки пеш аз оғози амалиёти нави ҷустуҷӯ ботро дар тӯли якчанд сония "хоб кунад". Одатан, ҳеҷ як бот бе ин кор карда наметавонад. Агар шумо рамзи дар боло зикршударо иҷро кунед, равзанаи Chrome кушода мешавад, ки бот аз он барои кор бо сайтҳо истифода хоҳад кард.

Биёед каме таҷриба кунем ва вебсайти kayak.com -ро дар равзанаи алоҳида кушоем. Мо шаҳреро, ки аз он парвоз карданӣ ҳастем ва шаҳре, ки ба он расидан мехоҳем, инчунин санаи парвозро интихоб мекунем. Ҳангоми интихоби санаҳо, боварӣ ҳосил кунед, ки доираи +-3 рӯз истифода мешавад. Ман кодро бо дарназардошти он навиштам, ки сайт дар посух ба чунин дархостҳо чӣ истеҳсол мекунад. Агар, масалан, ба шумо лозим аст, ки чиптаҳоро танҳо барои санаҳои муайян ҷустуҷӯ кунед, пас эҳтимоли зиёд вуҷуд дорад, ки шумо бояд рамзи ботро тағир диҳед. Вақте ки ман дар бораи код гап мезанам, ман шарҳҳои мувофиқ медиҳам, аммо агар шумо ошуфта бошед, ба ман хабар диҳед.

Акнун тугмаи ҷустуҷӯро клик кунед ва ба истиноди сатри суроғаҳо нигаред. Он бояд ба истиноде, ки ман дар мисоли зер истифода мекунам, ки дар он тағирёбанда эълон шудааст, монанд бошад kayak, ки URL-ро нигоҳ медорад ва усул истифода мешавад get драйвери веб. Пас аз пахш кардани тугмаи ҷустуҷӯ, натиҷаҳо бояд дар саҳифа пайдо шаванд.

Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд
Вақте ки ман фармонро истифода кардам get зиёда аз ду ё се маротиба дар давоми чанд дақиқа, аз ман хоҳиш карда шуд, ки санҷишро бо истифода аз reCaptcha анҷом диҳам. Шумо метавонед ин чекро дастӣ гузаронед ва то он даме, ки система барои гузаронидани чеки нав қарор қабул кунад, озмоишро идома диҳед. Вақте ки ман скриптро озмоиш кардам, ба назар чунин менамуд, ки сеанси ҷустуҷӯии аввал ҳамеша осон буд, бинобар ин, агар шумо хоҳед, ки бо код озмоиш кунед, шумо бояд танҳо давра ба давра дастӣ тафтиш кунед ва кодро бо истифода аз фосилаҳои тӯлонӣ байни сеансҳои ҷустуҷӯ иҷозат диҳед. Ва, агар шумо дар ин бора фикр кунед, ба гумон аст, ки шахс дар бораи нархи чиптаҳо дар фосилаи 10 дақиқа байни амалиёти ҷустуҷӯӣ маълумот талаб кунад.

Кор бо саҳифа бо истифода аз XPath

Ҳамин тавр, мо тирезаро кушодем ва сайтро бор кардем. Барои гирифтани нарх ва маълумоти дигар, мо бояд технологияи XPath ё селекторҳои CSS-ро истифода барем. Ман қарор додам, ки бо XPath пайваст шавам ва зарурати истифодаи селекторҳои CSS-ро ҳис накардам, аммо бо ин роҳ кор кардан комилан имконпазир аст. Гузариш дар атрофи саҳифа бо истифода аз XPath метавонад душвор бошад ва ҳатто агар шумо усулҳои дар боло тавсифшударо истифода баред ин мақола, ки нусхабардории идентификаторҳои мувофиқро аз коди саҳифа дар бар мегирифт, ман фаҳмидам, ки ин аслан роҳи беҳтарини дастрасӣ ба унсурҳои зарурӣ нест. Воқеан, дар ин Дар китоб тавсифи аълои асосҳои кор бо саҳифаҳо бо истифода аз интихобкунандагони XPath ва CSS оварда шудааст. Усули мувофиқи драйвери веб ин аст.

Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд
Пас, биёед корро дар бот идома диҳем. Биёед имкониятҳои барномаро барои интихоби арзонтарин чиптаҳо истифода барем. Дар тасвири зерин, рамзи интихобкунандаи XPath бо сурх нишон дода шудааст. Барои дидани код, шумо бояд элементи саҳифаеро, ки ба шумо манфиатдор аст, тугмаи рости мушро пахш кунед ва аз менюи пайдошуда фармони Тафтишро интихоб кунед. Ин фармонро барои унсурҳои гуногуни саҳифа даъват кардан мумкин аст, ки коди онҳо дар намоишгари кодҳо нишон дода ва таъкид карда мешавад.

Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд
Рамзи саҳифаро бинед

Барои тасдиқи далелҳои ман дар бораи камбудиҳои нусхабардории селекторҳо аз код, ба хусусиятҳои зерин диққат диҳед.

Ин аст он чизе ки шумо ҳангоми нусхабардории код ба даст меоред:

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

Барои нусхабардорӣ кардани чизе ба ин монанд, шумо бояд ба қисмати рамзи ба шумо таваҷҷӯҳ зоҳир кардани тугмаи рости муш клик кунед ва аз менюи пайдошуда фармони Нусхабардорӣ > Нусхабардории XPath-ро интихоб кунед.

Ин аст он чизе ки ман барои муайян кардани тугмаи арзонтарин истифода кардам:

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

Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд
Фармони нусхабардорӣ > Нусхабардории XPath

Маълум аст, ки варианти дуюм хеле соддатар аст. Ҳангоми истифода, он элементеро меҷӯяд, ки дорои атрибут аст data-codeбаробар ба price. Ҳангоми истифодаи варианти аввал, элемент ҷустуҷӯ карда мешавад id ки ба он баробар аст wtKI-price_aTab, ва роҳи XPath ба элемент ба назар мерасад /div[1]/div/div/div[1]/div/span/span. Дархости XPath ба ин саҳифа ҳиллаеро иҷро мекунад, аммо танҳо як маротиба. Ман ҳоло гуфта метавонам, ки id дафъаи дигар бор карда шудани саҳифа тағйир меёбад. пайдарпайии аломатҳо wtKI ҳар боре, ки саҳифа бор карда мешавад, ба таври динамикӣ тағир меёбад, аз ин рӯ коде, ки онро истифода мебарад, пас аз боркунии саҳифаи навбатӣ бефоида хоҳад буд. Пас, барои фаҳмидани XPath каме вақт ҷудо кунед. Ин дониш ба шумо хуб хизмат мекунад.

Бо вуҷуди ин, бояд қайд кард, ки нусхабардории интихобкунандагони XPath метавонад ҳангоми кор бо сайтҳои хеле содда муфид бошад ва агар шумо бо ин бароҳат бошед, ҳеҷ чизи нодурусте нест.

Акнун биёед фикр кунем, ки чӣ бояд кард, агар шумо бояд ҳамаи натиҷаҳои ҷустуҷӯро дар якчанд сатр, дар дохили рӯйхат гиред. Хеле содда. Ҳар як натиҷа дар дохили объект бо синф аст resultWrapper. Боркунии ҳамаи натиҷаҳоро метавон дар як ҳалқаи шабеҳ ба оне, ки дар зер нишон дода шудааст, анҷом дод.

Бояд қайд кард, ки агар шумо гуфтаҳои дар боло зикршударо фаҳмед, пас шумо бояд аксари рамзҳоеро, ки мо таҳлил мекунем, ба осонӣ фаҳмед. Вақте ки ин код иҷро мешавад, мо бо истифода аз як навъ механизми муайянкунандаи роҳ (XPath) он чизеро, ки ба мо лозим аст (воқеъ, ба унсуре, ки натиҷа печонида шудааст) дастрас мекунем. Ин барои ба даст овардани матни элемент ва ҷойгир кардани он дар объекте анҷом дода мешавад, ки маълумотро аз он хондан мумкин аст (аввал истифода мешавад). flight_containers, пас - flights_list).

Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд
Се сатри аввал нишон дода мешавад ва мо ҳама чизи лозимаро равшан мебинем. Бо вуҷуди ин, мо роҳҳои ҷолибтар барои гирифтани маълумот дорем. Мо бояд маълумотро аз ҳар як элемент алоҳида гирем.

Ба кор равед!

Роҳи осонтарини навиштани функсия ин бор кардани натиҷаҳои иловагӣ мебошад, бинобар ин мо аз он ҷо оғоз мекунем. Ман мехоҳам шумораи парвозҳоеро, ки барнома дар бораи онҳо маълумот мегирад, бе афзоиши шубҳа дар хидмате, ки боиси санҷиш мегардад, зиёд кунам, аз ин рӯ ман тугмаи боркунии натиҷаҳои бештарро ҳар боре, ки саҳифа намоиш дода мешавад, пахш мекунам. Дар ин код, шумо бояд ба блок диққат диҳед try, ки ман илова кардам, зеро баъзан тугма дуруст бор намекунад. Агар шумо низ ба ин дучор шавед, зангҳоро ба ин функсия дар коди функсия шарҳ диҳед start_kayak, ки мо дар поён дида мебароем.

# Загрузка большего количества результатов для того, чтобы максимизировать объём собираемых данных
def load_more():
    try:
        more_results = '//a[@class = "moreButton"]'
        driver.find_element_by_xpath(more_results).click()
        # Вывод этих заметок в ходе работы программы помогает мне быстро выяснить то, чем она занята
        print('sleeping.....')
        sleep(randint(45,60))
    except:
        pass

Акнун, пас аз таҳлили тӯлонии ин функсия (баъзан ман метавонам аз он даст кашам), мо омодаем, ки функсияеро эълон кунем, ки саҳифаро канда кунад.

Ман аллакай аксари он чизеро, ки дар функсияи зерин лозим аст, ҷамъ овардам page_scrape. Баъзан маълумоти роҳи баргардонидашуда якҷоя карда мешавад, аз ин рӯ ман барои ҷудо кардани он усули оддиро истифода мебарам. Масалан, вақте ки ман тағирёбандаҳоро бори аввал истифода мебарам section_a_list и section_b_list. Функсияи мо чаҳорчӯбаи маълумотро бармегардонад flights_df, ин ба мо имкон медиҳад, ки натиҷаҳоро аз усулҳои гуногуни ҷудокунии маълумот ҷудо кунем ва баъдтар онҳоро якҷоя кунем.

def page_scrape():
    """This function takes care of the scraping part"""
    
    xp_sections = '//*[@class="section duration"]'
    sections = driver.find_elements_by_xpath(xp_sections)
    sections_list = [value.text for value in sections]
    section_a_list = sections_list[::2] # так мы разделяем информацию о двух полётах
    section_b_list = sections_list[1::2]
    
    # Если вы наткнулись на reCaptcha, вам может понадобиться что-то предпринять.
    # О том, что что-то пошло не так, вы узнаете исходя из того, что вышеприведённые списки пусты
    # это выражение if позволяет завершить работу программы или сделать ещё что-нибудь
    # тут можно приостановить работу, что позволит вам пройти проверку и продолжить скрапинг
    # я использую тут SystemExit так как хочу протестировать всё с самого начала
    if section_a_list == []:
        raise SystemExit
    
    # Я буду использовать букву A для уходящих рейсов и B для прибывающих
    a_duration = []
    a_section_names = []
    for n in section_a_list:
        # Получаем время
        a_section_names.append(''.join(n.split()[2:5]))
        a_duration.append(''.join(n.split()[0:2]))
    b_duration = []
    b_section_names = []
    for n in section_b_list:
        # Получаем время
        b_section_names.append(''.join(n.split()[2:5]))
        b_duration.append(''.join(n.split()[0:2]))

    xp_dates = '//div[@class="section date"]'
    dates = driver.find_elements_by_xpath(xp_dates)
    dates_list = [value.text for value in dates]
    a_date_list = dates_list[::2]
    b_date_list = dates_list[1::2]
    # Получаем день недели
    a_day = [value.split()[0] for value in a_date_list]
    a_weekday = [value.split()[1] for value in a_date_list]
    b_day = [value.split()[0] for value in b_date_list]
    b_weekday = [value.split()[1] for value in b_date_list]
    
    # Получаем цены
    xp_prices = '//a[@class="booking-link"]/span[@class="price option-text"]'
    prices = driver.find_elements_by_xpath(xp_prices)
    prices_list = [price.text.replace('$','') for price in prices if price.text != '']
    prices_list = list(map(int, prices_list))

    # stops - это большой список, в котором первый фрагмент пути находится по чётному индексу, а второй - по нечётному
    xp_stops = '//div[@class="section stops"]/div[1]'
    stops = driver.find_elements_by_xpath(xp_stops)
    stops_list = [stop.text[0].replace('n','0') for stop in stops]
    a_stop_list = stops_list[::2]
    b_stop_list = stops_list[1::2]

    xp_stops_cities = '//div[@class="section stops"]/div[2]'
    stops_cities = driver.find_elements_by_xpath(xp_stops_cities)
    stops_cities_list = [stop.text for stop in stops_cities]
    a_stop_name_list = stops_cities_list[::2]
    b_stop_name_list = stops_cities_list[1::2]
    
    # сведения о компании-перевозчике, время отправления и прибытия для обоих рейсов
    xp_schedule = '//div[@class="section times"]'
    schedules = driver.find_elements_by_xpath(xp_schedule)
    hours_list = []
    carrier_list = []
    for schedule in schedules:
        hours_list.append(schedule.text.split('n')[0])
        carrier_list.append(schedule.text.split('n')[1])
    # разделяем сведения о времени и о перевозчиках между рейсами a и b
    a_hours = hours_list[::2]
    a_carrier = carrier_list[1::2]
    b_hours = hours_list[::2]
    b_carrier = carrier_list[1::2]

    
    cols = (['Out Day', 'Out Time', 'Out Weekday', 'Out Airline', 'Out Cities', 'Out Duration', 'Out Stops', 'Out Stop Cities',
            'Return Day', 'Return Time', 'Return Weekday', 'Return Airline', 'Return Cities', 'Return Duration', 'Return Stops', 'Return Stop Cities',
            'Price'])

    flights_df = pd.DataFrame({'Out Day': a_day,
                               'Out Weekday': a_weekday,
                               'Out Duration': a_duration,
                               'Out Cities': a_section_names,
                               'Return Day': b_day,
                               'Return Weekday': b_weekday,
                               'Return Duration': b_duration,
                               'Return Cities': b_section_names,
                               'Out Stops': a_stop_list,
                               'Out Stop Cities': a_stop_name_list,
                               'Return Stops': b_stop_list,
                               'Return Stop Cities': b_stop_name_list,
                               'Out Time': a_hours,
                               'Out Airline': a_carrier,
                               'Return Time': b_hours,
                               'Return Airline': b_carrier,                           
                               'Price': prices_list})[cols]
    
    flights_df['timestamp'] = strftime("%Y%m%d-%H%M") # время сбора данных
    return flights_df

Ман кӯшиш кардам, ки тағирёбандаҳоро номбар кунам, то код фаҳмо бошад. Дар хотир доред, ки тағирёбандаҳо аз a ба мархалаи якуми рох тааллук доранд ва b - ба дуюм. Биёед ба вазифаи навбатӣ гузарем.

Механизмҳои дастгирӣ

Ҳоло мо функсияе дорем, ки ба мо имкон медиҳад, ки натиҷаҳои ҷустуҷӯи иловагиро бор кунем ва функсияи коркарди ин натиҷаҳоро бор кунем. Ин мақола метавонист дар ин ҷо ба итмом расад, зеро ин ду функсия ҳама чизро барои харидани саҳифаҳое, ки шумо метавонед худатон кушоед, таъмин мекунад. Вале мо хануз баъзе механизмхои ёрирасонро, ки дар боло мухокима карда шуда будем, дида бароем. Масалан, ин рамзи фиристодани почтаи электронӣ ва баъзе чизҳои дигар аст. Ҳамаи инро дар функсия пайдо кардан мумкин аст start_kayak, ки мо ҳоло онро баррасӣ хоҳем кард.

Барои кор кардани ин функсия ба шумо маълумот дар бораи шаҳрҳо ва санаҳо лозим аст. Бо истифода аз ин маълумот, он пайвандеро дар тағирёбанда ташкил медиҳад kayak, ки барои он истифода мешавад, ки шуморо ба саҳифае мебарад, ки дар он натиҷаҳои ҷустуҷӯ аз рӯи мувофиқати беҳтаринашон ба дархост мураттаб карда шудаанд. Пас аз сессияи аввалини скрепинг, мо бо нархҳо дар ҷадвал дар болои саҳифа кор хоҳем кард. Махз, мо нархи минималии чипта ва нархи миёнаро пайдо мекунем. Ҳамаи ин дар баробари пешгӯии интишоркардаи сайт тавассути почтаи электронӣ фиристода мешавад. Дар саҳифа ҷадвали мувофиқ бояд дар кунҷи чапи болои ҷойгир бошад. Кор бо ин ҷадвал, дар омади гап, метавонад ҳангоми ҷустуҷӯи санаҳои дақиқ хатогӣ ба вуҷуд орад, зеро дар ин ҳолат ҷадвал дар саҳифа намоиш дода намешавад.

def start_kayak(city_from, city_to, date_start, date_end):
    """City codes - it's the IATA codes!
    Date format -  YYYY-MM-DD"""
    
    kayak = ('https://www.kayak.com/flights/' + city_from + '-' + city_to +
             '/' + date_start + '-flexible/' + date_end + '-flexible?sort=bestflight_a')
    driver.get(kayak)
    sleep(randint(8,10))
    
    # иногда появляется всплывающее окно, для проверки на это и его закрытия можно воспользоваться блоком try
    try:
        xp_popup_close = '//button[contains(@id,"dialog-close") and contains(@class,"Button-No-Standard-Style close ")]'
        driver.find_elements_by_xpath(xp_popup_close)[5].click()
    except Exception as e:
        pass
    sleep(randint(60,95))
    print('loading more.....')
    
#     load_more()
    
    print('starting first scrape.....')
    df_flights_best = page_scrape()
    df_flights_best['sort'] = 'best'
    sleep(randint(60,80))
    
    # Возьмём самую низкую цену из таблицы, расположенной в верхней части страницы
    matrix = driver.find_elements_by_xpath('//*[contains(@id,"FlexMatrixCell")]')
    matrix_prices = [price.text.replace('$','') for price in matrix]
    matrix_prices = list(map(int, matrix_prices))
    matrix_min = min(matrix_prices)
    matrix_avg = sum(matrix_prices)/len(matrix_prices)
    
    print('switching to cheapest results.....')
    cheap_results = '//a[@data-code = "price"]'
    driver.find_element_by_xpath(cheap_results).click()
    sleep(randint(60,90))
    print('loading more.....')
    
#     load_more()
    
    print('starting second scrape.....')
    df_flights_cheap = page_scrape()
    df_flights_cheap['sort'] = 'cheap'
    sleep(randint(60,80))
    
    print('switching to quickest results.....')
    quick_results = '//a[@data-code = "duration"]'
    driver.find_element_by_xpath(quick_results).click()  
    sleep(randint(60,90))
    print('loading more.....')
    
#     load_more()
    
    print('starting third scrape.....')
    df_flights_fast = page_scrape()
    df_flights_fast['sort'] = 'fast'
    sleep(randint(60,80))
    
    # Сохранение нового фрейма в Excel-файл, имя которого отражает города и даты
    final_df = df_flights_cheap.append(df_flights_best).append(df_flights_fast)
    final_df.to_excel('search_backups//{}_flights_{}-{}_from_{}_to_{}.xlsx'.format(strftime("%Y%m%d-%H%M"),
                                                                                   city_from, city_to, 
                                                                                   date_start, date_end), index=False)
    print('saved df.....')
    
    # Можно следить за тем, как прогноз, выдаваемый сайтом, соотносится с реальностью
    xp_loading = '//div[contains(@id,"advice")]'
    loading = driver.find_element_by_xpath(xp_loading).text
    xp_prediction = '//span[@class="info-text"]'
    prediction = driver.find_element_by_xpath(xp_prediction).text
    print(loading+'n'+prediction)
    
    # иногда в переменной loading оказывается эта строка, которая, позже, вызывает проблемы с отправкой письма
    # если это прозошло - меняем её на "Not Sure"
    weird = '¯_(ツ)_/¯'
    if loading == weird:
        loading = 'Not sure'
    
    username = '[email protected]'
    password = 'YOUR PASSWORD'

    server = smtplib.SMTP('smtp.outlook.com', 587)
    server.ehlo()
    server.starttls()
    server.login(username, password)
    msg = ('Subject: Flight Scrapernn
Cheapest Flight: {}nAverage Price: {}nnRecommendation: {}nnEnd of message'.format(matrix_min, matrix_avg, (loading+'n'+prediction)))
    message = MIMEMultipart()
    message['From'] = '[email protected]'
    message['to'] = '[email protected]'
    server.sendmail('[email protected]', '[email protected]', msg)
    print('sent email.....')

Ман ин скриптро бо истифода аз ҳисоби Outlook (hotmail.com) санҷидам. Ман онро барои дуруст кор кардан бо ҳисоби Gmail озмоиш накардаам, ин системаи почтаи электронӣ хеле маъмул аст, аммо имконоти зиёде мавҷуданд. Агар шумо ҳисоби Hotmail-ро истифода баред, пас барои он ки ҳама чиз кор кунад, шумо бояд танҳо маълумоти худро ба код ворид кунед.

Агар шумо хоҳед фаҳмед, ки дар бахшҳои мушаххаси код барои ин функсия маҳз чӣ кор карда мешавад, шумо метавонед онҳоро нусхабардорӣ кунед ва бо онҳо озмоиш кунед. Таҷриба бо код ягона роҳи воқеии фаҳмидани он аст.

Системаи тайёр

Акнун, ки мо ҳама чизеро, ки дар бораи он гуфта будем, иҷро кардем, мо метавонем як ҳалқаи оддиеро созем, ки функсияҳои моро даъват мекунад. Скрипт аз корбар маълумотро дар бораи шаҳрҳо ва санаҳо талаб мекунад. Ҳангоми санҷиш бо бозоғозкунии доимии скрипт, шумо гумон нестед, ки ҳар дафъа ин маълумотро дастӣ ворид кунед, бинобар ин сатрҳои мувофиқро барои вақти санҷиш метавон бо роҳи бекор кардани шарҳҳои поёнии онҳо шарҳ дод, ки дар онҳо маълумот ба скрипт сахт код карда шудааст.

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

Ин аст, ки санҷиши скрипт чӣ гуна ба назар мерасад.
Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд
Иҷрои санҷиши скрипт

Натиҷаҳо

Агар шумо ин корро карда бошед, табрик! Шумо ҳоло веб скрепер доред, гарчанде ки ман аллакай роҳҳои зиёде барои беҳтар кардани онро дида метавонам. Масалан, он метавонад бо Twilio муттаҳид карда шавад, то он ба ҷои почтаи электронӣ паёмҳои матнӣ фиристад. Шумо метавонед VPN ё чизи дигареро истифода баред, то ҳамзамон натиҷаҳоро аз якчанд серверҳо гиред. Инчунин мушкилоте ба миён меояд, ки ҳангоми тафтиш кардани корбари сайт барои муайян кардани он, ки ӯ шахс аст, аммо ин мушкилотро низ ҳал кардан мумкин аст. Дар ҳар сурат, ҳоло шумо базае доред, ки агар хоҳед, онро васеъ карда метавонед. Масалан, боварӣ ҳосил кунед, ки файли Excel ба корбар ҳамчун замимаи почтаи электронӣ фиристода мешавад.

Python - ёрдамчии ҷустуҷӯи чиптаҳои арзон барои онҳое, ки сафар карданро дӯст медоранд

Танҳо корбарони сабтиномшуда метавонанд дар пурсиш иштирок кунанд. даромад, Лутфан.

Оё шумо технологияҳои скрепинги вебро истифода мебаред?

  • он

  • нест

8 корбар овоз доданд. 1 корбар худдорӣ кард.

Манбаъ: will.com

Илова Эзоҳ