Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio

Dywed awdur yr erthygl, yr ydym yn ei gyhoeddi heddiw, mai ei nod yw siarad am ddatblygiad sgraper gwe yn Python gan ddefnyddio Seleniwm, sy'n chwilio am brisiau tocynnau hedfan. Wrth chwilio am docynnau, defnyddir dyddiadau hyblyg (+ - 3 diwrnod o gymharu â'r dyddiadau penodedig). Mae'r sgraper yn arbed y canlyniadau chwilio mewn ffeil Excel ac yn anfon e-bost at y person a redodd y chwiliad gyda chrynodeb o'r hyn a ddarganfuwyd. Nod y prosiect hwn yw helpu teithwyr i ddod o hyd i'r bargeinion gorau.

Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio

Os ydych chi'n teimlo ar goll wrth ddeall y deunydd, edrychwch arno hyn erthygl.

Beth ydyn ni'n mynd i chwilio amdano?

Rydych chi'n rhydd i ddefnyddio'r system a ddisgrifir yma fel y dymunwch. Er enghraifft, defnyddiais ef i chwilio am deithiau penwythnos a thocynnau i fy nhref enedigol. Os ydych chi o ddifrif am ddod o hyd i docynnau proffidiol, gallwch chi redeg y sgript ar y gweinydd (syml gweinydd, am 130 rubles y mis, yn eithaf addas ar gyfer hyn) a gwnewch yn siŵr ei fod yn rhedeg unwaith neu ddwywaith y dydd. Bydd canlyniadau chwilio yn cael eu hanfon atoch trwy e-bost. Yn ogystal, rwy'n argymell sefydlu popeth fel bod y sgript yn arbed ffeil Excel gyda chanlyniadau chwilio mewn ffolder Dropbox, a fydd yn caniatáu ichi weld ffeiliau o'r fath o unrhyw le ac ar unrhyw adeg.

Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio
Nid wyf wedi dod o hyd i dariffau gyda gwallau eto, ond rwy'n meddwl ei fod yn bosibl

Wrth chwilio, fel y soniwyd eisoes, defnyddir “dyddiad hyblyg”; mae'r sgript yn dod o hyd i gynigion sydd o fewn tri diwrnod i'r dyddiadau a roddwyd. Er wrth redeg y sgript, mae'n chwilio am gynigion mewn un cyfeiriad yn unig, mae'n hawdd ei addasu fel y gall gasglu data ar sawl cyfeiriad hedfan. Gyda'i help, gallwch hyd yn oed chwilio am dariffau gwallus; gall canfyddiadau o'r fath fod yn ddiddorol iawn.

Pam mae angen sgraper gwe arall arnoch chi?

Pan ddechreuais i sgrapio gwe am y tro cyntaf, a dweud y gwir nid oedd gennyf ddiddordeb arbennig ynddo. Roeddwn i eisiau gwneud mwy o brosiectau ym maes modelu rhagfynegol, dadansoddi ariannol, ac, o bosibl, ym maes dadansoddi lliw emosiynol testunau. Ond mae'n troi allan ei bod yn ddiddorol iawn darganfod sut i greu rhaglen sy'n casglu data o wefannau. Wrth i mi ymchwilio i'r pwnc hwn, sylweddolais mai crafu gwe yw “peiriant” y Rhyngrwyd.

Efallai eich bod yn meddwl bod hwn yn ddatganiad rhy feiddgar. Ond ystyriwch fod Google wedi dechrau gyda sgrapiwr gwe a greodd Larry Page gan ddefnyddio Java a Python. Mae robotiaid Google wedi bod yn archwilio'r Rhyngrwyd, gan geisio rhoi'r atebion gorau i'w cwestiynau i'w defnyddwyr. Mae gan sgrapio gwe ddefnyddiau diddiwedd, a hyd yn oed os oes gennych ddiddordeb mewn rhywbeth arall mewn Gwyddor Data, bydd angen rhai sgiliau sgrapio arnoch i gael y data y mae angen i chi ei ddadansoddi.

Fe wnes i ddarganfod rhai o'r technegau a ddefnyddir yma yn fendigedig y llyfr am sgrapio gwe, a gefais yn ddiweddar. Mae'n cynnwys llawer o enghreifftiau syml a syniadau ar gyfer cymhwyso'r hyn rydych wedi'i ddysgu yn ymarferol. Yn ogystal, mae yna bennod ddiddorol iawn ar osgoi gwiriadau reCaptcha. Daeth hyn yn newyddion i mi, gan nad oeddwn hyd yn oed yn gwybod bod yna offer arbennig a hyd yn oed gwasanaethau cyfan ar gyfer datrys problemau o'r fath.

Ydych chi'n hoffi teithio?!

I'r cwestiwn syml a braidd yn ddiniwed a ofynnir yn nheitl yr adran hon, gallwch glywed ateb cadarnhaol yn aml, ynghyd â chwpl o straeon o deithiau'r person y gofynnwyd iddo. Byddai’r rhan fwyaf ohonom yn cytuno bod teithio yn ffordd wych o ymgolli mewn amgylcheddau diwylliannol newydd ac ehangu eich gorwelion. Fodd bynnag, os gofynnwch i rywun a ydynt yn hoffi chwilio am docynnau hedfan, yr wyf yn siŵr na fydd yr ateb mor gadarnhaol. Fel mater o ffaith, mae Python yn dod i'n cymorth yma.

Y dasg gyntaf y mae angen i ni ei datrys ar y ffordd i greu system ar gyfer chwilio gwybodaeth am docynnau awyr fydd dewis platfform addas y byddwn yn cymryd gwybodaeth ohono. Nid oedd datrys y broblem hon yn hawdd i mi, ond yn y diwedd dewisais y gwasanaeth Caiac. Rhoddais gynnig ar wasanaethau Momondo, Skyscanner, Expedia, ac ychydig o rai eraill, ond roedd y mecanweithiau amddiffyn robotiaid ar yr adnoddau hyn yn anhreiddiadwy. Ar ôl sawl ymgais, pan fu'n rhaid i mi ddelio â goleuadau traffig, croesfannau cerddwyr a beiciau, gan geisio argyhoeddi'r systemau fy mod yn ddynol, penderfynais mai Caiac oedd fwyaf addas i mi, er gwaethaf y ffaith, hyd yn oed os yw Gormod o dudalennau'n cael eu llwytho. mewn amser byr, ac mae gwiriadau hefyd yn dechrau. Llwyddais i wneud i'r bot anfon ceisiadau i'r wefan bob 4 i 6 awr, a gweithiodd popeth yn iawn. O bryd i'w gilydd, mae anawsterau'n codi wrth weithio gyda Caiac, ond os ydyn nhw'n dechrau eich poeni â sieciau, yna mae angen i chi naill ai ddelio â nhw â llaw ac yna lansio'r bot, neu aros ychydig oriau a dylai'r gwiriadau ddod i ben. Os oes angen, gallwch chi addasu'r cod ar gyfer platfform arall yn hawdd, ac os gwnewch hynny, gallwch chi roi gwybod amdano yn y sylwadau.

Os ydych chi newydd ddechrau sgrapio gwe a ddim yn gwybod pam mae rhai gwefannau'n cael trafferth ag ef, yna cyn i chi ddechrau eich prosiect cyntaf yn y maes hwn, gwnewch ffafr i chi'ch hun a gwnewch chwiliad Google ar y geiriau "web scraping etiquette" . Efallai y bydd eich arbrofion yn dod i ben yn gynt nag y credwch os gwnewch sgrapio gwe yn annoeth.

Dechrau Arni

Dyma drosolwg cyffredinol o'r hyn fydd yn digwydd yn ein cod sgrapio gwe:

  • Mewnforio'r llyfrgelloedd gofynnol.
  • Yn agor tab Google Chrome.
  • Ffoniwch swyddogaeth sy'n cychwyn y bot, gan basio'r dinasoedd a'r dyddiadau a ddefnyddir wrth chwilio am docynnau.
  • Mae'r swyddogaeth hon yn cymryd y canlyniadau chwilio cyntaf, wedi'u didoli yn ôl y gorau, ac yn clicio botwm i lwytho mwy o ganlyniadau.
  • Mae swyddogaeth arall yn casglu data o'r dudalen gyfan ac yn dychwelyd ffrâm ddata.
  • Perfformir y ddau gam blaenorol gan ddefnyddio mathau didoli yn ôl pris tocyn (rhad) ac yn ôl cyflymder hedfan (cyflymaf).
  • Anfonir e-bost at ddefnyddiwr y sgript sy'n cynnwys crynodeb o brisiau tocynnau (tocynnau rhataf a phris cyfartalog), a chaiff ffrâm ddata gyda gwybodaeth wedi'i didoli yn ôl y tri dangosydd uchod ei chadw fel ffeil Excel.
  • Mae'r holl gamau gweithredu uchod yn cael eu perfformio mewn cylch ar ôl cyfnod penodol o amser.

Dylid nodi bod pob prosiect Seleniwm yn dechrau gyda gyrrwr gwe. Rydw i'n defnyddio Chromedriver, Rwy'n gweithio gyda Google Chrome, ond mae opsiynau eraill. Mae PhantomJS a Firefox hefyd yn boblogaidd. Ar ôl lawrlwytho'r gyrrwr, mae angen i chi ei roi yn y ffolder priodol, ac mae hyn yn cwblhau'r paratoad ar gyfer ei ddefnyddio. Mae llinellau cyntaf ein sgript yn agor tab Chrome newydd.

Cadwch mewn cof nad wyf yn fy stori yn ceisio agor gorwelion newydd ar gyfer dod o hyd i fargeinion gwych ar docynnau awyr. Mae yna ddulliau llawer mwy datblygedig ar gyfer chwilio am gynigion o'r fath. Rwyf am gynnig ffordd syml ond ymarferol i ddarllenwyr y deunydd hwn ddatrys y broblem hon.

Dyma'r cod y buom yn siarad amdano uchod.

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)

Ar ddechrau'r cod gallwch weld y gorchmynion mewnforio pecyn a ddefnyddir trwy gydol ein prosiect. Felly, randint a ddefnyddir i wneud i'r bot “syrthio i gysgu” am nifer ar hap o eiliadau cyn dechrau gweithrediad chwilio newydd. Fel arfer, ni all un bot wneud heb hyn. Os ydych chi'n rhedeg y cod uchod, bydd ffenestr Chrome yn agor, y bydd y bot yn ei defnyddio i weithio gyda gwefannau.

Gadewch i ni wneud ychydig o arbrawf ac agor gwefan kayak.com mewn ffenestr ar wahân. Byddwn yn dewis y ddinas yr ydym yn mynd i hedfan ohoni, a'r ddinas yr ydym am ei chyrraedd, yn ogystal â'r dyddiadau hedfan. Wrth ddewis dyddiadau, gwnewch yn siŵr bod yr ystod o +-3 diwrnod yn cael ei ddefnyddio. Ysgrifennais y cod gan ystyried yr hyn y mae'r wefan yn ei gynhyrchu mewn ymateb i geisiadau o'r fath. Os, er enghraifft, mae angen i chi chwilio am docynnau ar gyfer dyddiadau penodol yn unig, yna mae'n debygol iawn y bydd yn rhaid i chi addasu'r cod bot. Pan fyddaf yn siarad am y cod, rhoddaf esboniadau priodol, ond os ydych yn teimlo'n ddryslyd, rhowch wybod i mi.

Nawr cliciwch ar y botwm chwilio ac edrychwch ar y ddolen yn y bar cyfeiriad. Dylai fod yn debyg i'r ddolen a ddefnyddiaf yn yr enghraifft isod lle mae'r newidyn yn cael ei ddatgan kayak, sy'n storio'r URL, a defnyddir y dull get gyrrwr gwe. Ar ôl clicio ar y botwm chwilio, dylai canlyniadau ymddangos ar y dudalen.

Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio
Pan ddefnyddiais y gorchymyn get fwy na dwy neu dair gwaith o fewn ychydig funudau, gofynnwyd i mi gwblhau dilysu gan ddefnyddio reCaptcha. Gallwch chi basio'r gwiriad hwn â llaw a pharhau i arbrofi nes bod y system yn penderfynu rhedeg gwiriad newydd. Pan brofais y sgript, roedd yn ymddangos bod y sesiwn chwilio gyntaf bob amser yn mynd yn esmwyth, felly os oeddech am arbrofi gyda'r cod, dim ond yn achlysurol y byddai'n rhaid i chi wirio â llaw a gadael i'r cod redeg, gan ddefnyddio cyfnodau hir rhwng sesiynau chwilio. Ac, os meddyliwch am y peth, mae'n annhebygol y bydd angen gwybodaeth ar berson am brisiau tocynnau a dderbynnir bob 10 munud rhwng gweithrediadau chwilio.

Gweithio gyda thudalen gan ddefnyddio XPath

Felly, fe wnaethom agor ffenestr a llwytho'r wefan. I gael prisiau a gwybodaeth arall, mae angen i ni ddefnyddio technoleg XPath neu ddetholwyr CSS. Penderfynais gadw at XPath a doeddwn i ddim yn teimlo'r angen i ddefnyddio dewiswyr CSS, ond mae'n eithaf posibl gweithio felly. Gall llywio o gwmpas tudalen gan ddefnyddio XPath fod yn anodd, a hyd yn oed os ydych chi'n defnyddio'r technegau a ddisgrifiais ynddynt hwn erthygl, a oedd yn cynnwys copïo'r dynodwyr cyfatebol o god y dudalen, sylweddolais mai dyma, mewn gwirionedd, nid y ffordd orau i gael mynediad at yr elfennau angenrheidiol. Gyda llaw, mewn hwn Mae'r llyfr yn rhoi disgrifiad rhagorol o hanfodion gweithio gyda thudalennau gan ddefnyddio detholwyr XPath a CSS. Dyma sut olwg sydd ar y dull gyrrwr gwe cyfatebol.

Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio
Felly, gadewch i ni barhau i weithio ar y bot. Gadewch i ni ddefnyddio galluoedd y rhaglen i ddewis y tocynnau rhataf. Yn y ddelwedd ganlynol, mae cod dewisydd XPath wedi'i amlygu mewn coch. Er mwyn gweld y cod, mae angen i chi dde-glicio ar yr elfen dudalen y mae gennych ddiddordeb ynddi a dewis y gorchymyn Archwilio o'r ddewislen sy'n ymddangos. Gellir galw'r gorchymyn hwn ar gyfer gwahanol elfennau tudalen, a bydd y cod yn cael ei arddangos a'i amlygu yn y syllwr cod.

Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio
Gweld cod tudalen

Er mwyn dod o hyd i gadarnhad o'm rhesymu ynghylch anfanteision copïo detholwyr o god, rhowch sylw i'r nodweddion canlynol.

Dyma beth gewch chi pan fyddwch chi'n copïo'r cod:

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

Er mwyn copïo rhywbeth fel hyn, mae angen i chi dde-glicio ar yr adran o'r cod y mae gennych ddiddordeb ynddi a dewis y gorchymyn Copi> Copi XPath o'r ddewislen sy'n ymddangos.

Dyma beth ddefnyddiais i ddiffinio'r botwm rhataf:

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

Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio
Copi Gorchymyn > Copïo XPath

Mae'n eithaf amlwg bod yr ail opsiwn yn edrych yn llawer symlach. Pan gaiff ei ddefnyddio, mae'n chwilio am elfen a sydd â'r priodoledd data-codeyn hafal i price. Wrth ddefnyddio'r opsiwn cyntaf, chwilir yr elfen id sy'n hafal i wtKI-price_aTab, ac mae llwybr XPath i'r elfen yn edrych fel /div[1]/div/div/div[1]/div/span/span. Bydd ymholiad XPath fel hwn i dudalen yn gwneud y tric, ond dim ond unwaith. Gallaf ddweud hynny ar hyn o bryd id yn newid y tro nesaf y bydd y dudalen yn cael ei llwytho. Dilyniant cymeriad wtKI yn newid yn ddeinamig bob tro y bydd y dudalen yn cael ei llwytho, felly bydd y cod sy'n ei ddefnyddio yn ddiwerth ar ôl ail-lwytho'r dudalen nesaf. Felly cymerwch amser i ddeall XPath. Bydd y wybodaeth hon yn eich gwasanaethu'n dda.

Fodd bynnag, dylid nodi y gall copïo detholwyr XPath fod yn ddefnyddiol wrth weithio gyda gwefannau eithaf syml, ac os ydych chi'n gyfforddus â hyn, nid oes dim o'i le.

Nawr, gadewch i ni feddwl beth i'w wneud os oes angen i chi gael yr holl ganlyniadau chwilio mewn sawl llinell, y tu mewn i restr. Syml iawn. Mae pob canlyniad y tu mewn i wrthrych gyda dosbarth resultWrapper. Gellir llwytho'r holl ganlyniadau mewn dolen debyg i'r un a ddangosir isod.

Dylid nodi, os ydych chi'n deall yr uchod, yna dylech chi ddeall y rhan fwyaf o'r cod y byddwn yn ei ddadansoddi yn hawdd. Wrth i'r cod hwn redeg, rydym yn cyrchu'r hyn sydd ei angen arnom (mewn gwirionedd, yr elfen y mae'r canlyniad wedi'i lapio ynddo) gan ddefnyddio rhyw fath o fecanwaith pennu llwybr (XPath). Gwneir hyn er mwyn cael testun yr elfen a'i osod mewn gwrthrych y gellir darllen data ohono (defnyddiwyd gyntaf flight_containers, yna - flights_list).

Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio
Mae'r tair llinell gyntaf yn cael eu harddangos a gallwn weld yn glir bopeth sydd ei angen arnom. Fodd bynnag, mae gennym ffyrdd mwy diddorol o gael gwybodaeth. Mae angen inni gymryd data o bob elfen ar wahân.

Ewch i'r gwaith!

Y ffordd hawsaf i ysgrifennu swyddogaeth yw llwytho canlyniadau ychwanegol, felly dyna lle byddwn yn dechrau. Hoffwn wneud y mwyaf o nifer yr hediadau y mae'r rhaglen yn derbyn gwybodaeth amdanynt, heb godi amheuon yn y gwasanaeth sy'n arwain at arolygiad, felly rwy'n clicio ar y botwm Llwytho mwy o ganlyniadau unwaith bob tro y bydd y dudalen yn cael ei harddangos. Yn y cod hwn, dylech roi sylw i'r bloc try, a ychwanegais oherwydd weithiau nid yw'r botwm yn llwytho'n iawn. Os byddwch chi'n dod ar draws hyn hefyd, gwnewch sylwadau ar alwadau i'r swyddogaeth hon yn y cod swyddogaeth start_kayak, y byddwn yn edrych arno isod.

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

Nawr, ar ôl dadansoddiad hir o'r swyddogaeth hon (weithiau gallaf fynd dros ben llestri), rydym yn barod i ddatgan swyddogaeth a fydd yn sgrapio'r dudalen.

Rwyf eisoes wedi casglu'r rhan fwyaf o'r hyn sydd ei angen yn y swyddogaeth ganlynol o'r enw page_scrape. Weithiau mae'r data llwybr a ddychwelwyd yn cael ei gyfuno, felly rwy'n defnyddio dull syml i'w wahanu. Er enghraifft, pan fyddaf yn defnyddio newidynnau am y tro cyntaf section_a_list и section_b_list. Mae ein swyddogaeth yn dychwelyd ffrâm ddata flights_df, mae hyn yn ein galluogi i wahanu'r canlyniadau a gafwyd o wahanol ddulliau didoli data a'u cyfuno'n ddiweddarach.

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

Ceisiais enwi'r newidynnau fel y byddai'r cod yn ddealladwy. Cofiwch fod newidynnau yn dechrau gyda a perthyn i gam cyntaf y llwybr, a b - i'r ail. Gadewch i ni symud ymlaen i'r swyddogaeth nesaf.

Mecanweithiau cymorth

Bellach mae gennym swyddogaeth sy'n ein galluogi i lwytho canlyniadau chwilio ychwanegol a swyddogaeth i brosesu'r canlyniadau hynny. Gallai'r erthygl hon fod wedi dod i ben yma, gan fod y ddwy swyddogaeth hyn yn darparu popeth sydd ei angen arnoch i sgrapio tudalennau y gallwch chi eu hagor eich hun. Ond nid ydym eto wedi ystyried rhai o'r mecanweithiau ategol a drafodwyd uchod. Er enghraifft, dyma'r cod ar gyfer anfon e-byst a rhai pethau eraill. Gellir dod o hyd i hyn i gyd yn y swyddogaeth start_kayak, y byddwn yn awr yn ei ystyried.

Er mwyn i'r swyddogaeth hon weithio, mae angen gwybodaeth arnoch am ddinasoedd a dyddiadau. Gan ddefnyddio'r wybodaeth hon, mae'n ffurfio dolen mewn newidyn kayak, a ddefnyddir i fynd â chi i dudalen a fydd yn cynnwys canlyniadau chwilio wedi'u trefnu yn ôl eu cyfatebiad gorau i'r ymholiad. Ar ôl y sesiwn sgrapio gyntaf, byddwn yn gweithio gyda'r prisiau yn y tabl ar frig y dudalen. Sef, byddwn yn dod o hyd i'r isafswm pris tocyn a'r pris cyfartalog. Bydd hyn i gyd, ynghyd â'r rhagfynegiad a gyhoeddwyd gan y wefan, yn cael ei anfon trwy e-bost. Ar y dudalen, dylai'r tabl cyfatebol fod yn y gornel chwith uchaf. Gall gweithio gyda'r tabl hwn, gyda llaw, achosi gwall wrth chwilio gan ddefnyddio union ddyddiadau, oherwydd yn yr achos hwn nid yw'r tabl yn cael ei arddangos ar y dudalen.

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

Profais y sgript hon gan ddefnyddio cyfrif Outlook (hotmail.com). Nid wyf wedi ei brofi i weithio'n gywir gyda chyfrif Gmail, mae'r system e-bost hon yn eithaf poblogaidd, ond mae yna lawer o opsiynau posibl. Os ydych chi'n defnyddio cyfrif Hotmail, yna er mwyn i bopeth weithio, does ond angen i chi nodi'ch data yn y cod.

Os ydych chi eisiau deall beth yn union sy'n cael ei wneud mewn adrannau penodol o'r cod ar gyfer y swyddogaeth hon, gallwch eu copïo ac arbrofi â nhw. Arbrofi gyda'r cod yw'r unig ffordd i'w ddeall yn wirioneddol.

System barod

Nawr ein bod wedi gwneud popeth y buom yn siarad amdano, gallwn greu dolen syml sy'n galw ein swyddogaethau. Mae'r sgript yn gofyn am ddata gan y defnyddiwr am ddinasoedd a dyddiadau. Wrth brofi gydag ailgychwyn cyson y sgript, mae'n annhebygol y byddwch am fewnbynnu'r data hwn â llaw bob tro, felly gellir gwneud sylwadau ar y llinellau cyfatebol, ar gyfer yr amser profi, trwy ddadwneud y rhai isod, lle mae'r data sydd ei angen ar y mae'r sgript wedi'i chod caled.

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

Dyma sut olwg sydd ar rediad prawf o'r sgript.
Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio
Prawf rhediad y sgript

Canlyniadau

Os ydych chi wedi cyrraedd mor bell â hyn, llongyfarchiadau! Bellach mae gennych sgraper gwe sy'n gweithio, er y gallaf weld llawer o ffyrdd i'w wella eisoes. Er enghraifft, gellir ei integreiddio â Twilio fel ei fod yn anfon negeseuon testun yn lle e-byst. Gallwch ddefnyddio VPN neu rywbeth arall i dderbyn canlyniadau gan sawl gweinydd ar yr un pryd. Mae yna hefyd broblem yn codi o bryd i'w gilydd wrth wirio defnyddiwr y wefan i weld a yw'n berson, ond gellir datrys y broblem hon hefyd. Beth bynnag, nawr mae gennych chi sylfaen y gallwch chi ei ehangu os dymunwch. Er enghraifft, gwnewch yn siŵr bod ffeil Excel yn cael ei hanfon at y defnyddiwr fel atodiad i e-bost.

Python - cynorthwy-ydd i ddod o hyd i docynnau awyr rhad i'r rhai sydd wrth eu bodd yn teithio

Dim ond defnyddwyr cofrestredig all gymryd rhan yn yr arolwg. Mewngofnodios gwelwch yn dda.

Ydych chi'n defnyddio technolegau sgrapio gwe?

  • Oes

  • Dim

Pleidleisiodd 8 o ddefnyddwyr. Ymatalodd 1 defnyddiwr.

Ffynhonnell: hab.com

Ychwanegu sylw