Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan

Penulis artikel, terjemahan sing diterbitake dina iki, ujar manawa tujuane yaiku kanggo ngobrol babagan pangembangan scraper web ing Python nggunakake Selenium, sing nggoleki rega tiket pesawat. Nalika nggoleki tiket, tanggal fleksibel digunakake (+- 3 dina relatif marang tanggal sing ditemtokake). Scraper nyimpen asil panelusuran ing file Excel lan ngirim wong sing nggoleki email kanthi ringkesan apa sing ditemokake. Tujuan proyek iki yaiku mbantu para wisatawan nemokake tawaran sing paling apik.

Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan

Yen, nalika ngerti materi, sampeyan aran ilang, njupuk dipikir ing iki artikel.

Apa sing kita goleki?

Sampeyan bebas nggunakake sistem sing diterangake ing kene sing dikarepake. Contone, aku digunakake kanggo nggoleki tur akhir minggu lan tiket menyang kampung halaman. Yen sampeyan serius golek tiket sing duwe bathi, sampeyan bisa mbukak skrip ing server (prasaja server, kanggo 130 rubel sasi, cukup cocok kanggo iki) lan priksa manawa mlaku sepisan utawa kaping pindho dina. Asil panelusuran bakal dikirim menyang sampeyan liwat email. Kajaba iku, aku nyaranake nyetel kabeh supaya skrip nyimpen file Excel kanthi asil panelusuran ing folder Dropbox, sing bakal ngidini sampeyan ndeleng file kasebut saka ngendi wae lan kapan wae.

Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan
Aku wis ora ketemu tariffs karo kasalahan durung, nanging aku iku bisa

Nalika nggoleki, kaya sing wis kasebut, "tanggal fleksibel" digunakake; skrip nemokake tawaran ing telung dina saka tanggal sing diwenehake. Sanajan nalika mbukak skrip, mung nggoleki tawaran ing siji arah, nanging gampang diowahi supaya bisa ngumpulake data ing sawetara arah penerbangan. Kanthi bantuan, sampeyan bisa uga golek tarif sing salah; temuan kasebut bisa uga menarik banget.

Napa sampeyan butuh scraper web liyane?

Nalika aku pisanan miwiti web scraping, aku jujur ​​ora kasengsem ing. Aku pengin nindakake luwih akeh proyek ing bidang modeling prediktif, analisis finansial, lan, bisa uga, ing bidang nganalisa pewarnaan emosional teks. Nanging ternyata menarik banget kanggo mangerteni carane nggawe program sing ngumpulake data saka situs web. Nalika aku nggoleki topik iki, aku nyadari yen scraping web minangka "mesin" Internet.

Sampeyan bisa uga mikir yen iki statement banget kandel. Nanging nimbang manawa Google diwiwiti kanthi scraper web sing digawe Larry Page nggunakake Java lan Python. Robot Google wis njelajah Internet, nyoba menehi jawaban sing paling apik kanggo para pangguna. Web scraping nduweni panggunaan tanpa wates, lan sanajan sampeyan kasengsem ing babagan liya ing Ilmu Data, sampeyan butuh sawetara katrampilan scraping kanggo entuk data sing kudu dianalisis.

Aku ketemu sawetara saka Techniques digunakake kene ing apik banget buku babagan web scraping, sing aku bubar entuk. Isine akeh conto prasaja lan gagasan kanggo aplikasi praktis saka apa sing wis sinau. Kajaba iku, ana bab sing menarik banget kanggo ngliwati cek reCaptcha. Iki minangka warta kanggo aku, amarga aku ora ngerti manawa ana alat khusus lan uga kabeh layanan kanggo ngrampungake masalah kasebut.

Apa sampeyan seneng lelungan?!

Kanggo pitakonan sing prasaja lan ora mbebayani sing diajukake ing judhul bagean iki, sampeyan bisa kerep krungu jawaban positif, diiringi sawetara crita saka lelungan wong sing ditakoni. Umume kita bakal setuju yen lelungan minangka cara sing apik kanggo nyemplungake lingkungan budaya anyar lan nggedhekake wawasan. Nanging, yen sampeyan takon wong apa dheweke seneng nggoleki tiket pesawat, aku yakin yen jawabane ora bakal positif. Nyatane, Python teka kanggo mbantu kita ing kene.

Tugas pisanan sing kudu diatasi nalika nggawe sistem kanggo nggoleki informasi babagan tiket pesawat yaiku milih platform sing cocog kanggo njupuk informasi. Ngatasi masalah iki ora gampang kanggo kula, nanging ing pungkasan aku milih layanan Kayak. Aku nyoba layanan Momondo, Skyscanner, Expedia, lan sawetara liyane, nanging mekanisme pangayoman robot ing sumber daya iki ora bisa ditembus. Sawise pirang-pirang usaha, sajrone aku kudu ngatasi lampu lalu lintas, nyebrang pejalan kaki lan sepeda, nyoba ngyakinake sistem yen aku manungsa, aku mutusake yen Kayak paling cocog kanggo aku, sanajan kasunyatane sanajan akeh kaca sing dimuat. ing wektu cendhak, lan kir uga miwiti. Aku bisa nggawe panjalukan ngirim bot menyang situs kasebut kanthi interval 4 nganti 6 jam, lan kabeh bisa digunakake. Saka wektu kanggo wektu, kangelan njedhul nalika nggarap Kayak, nanging yen padha miwiti pestering sampeyan karo mriksa, sampeyan kudu salah siji menehi hasil karo manual lan banjur miwiti bot, utawa ngenteni sawetara jam lan mriksa kudu mandheg. Yen perlu, sampeyan bisa kanthi gampang ngganti kode kasebut kanggo platform liyane, lan yen sampeyan nindakake, sampeyan bisa nglaporake ing komentar.

Yen sampeyan lagi miwiti scraping web lan ora ngerti sebabe sawetara situs web berjuang karo, banjur sadurunge sampeyan miwiti proyek pisanan ing wilayah iki, tindakake dhewe lan nindakake panelusuran Google ing tembung "web scraping etiket" . Eksperimen sampeyan bisa rampung luwih cepet tinimbang sing sampeyan pikirake yen sampeyan ngikis web kanthi ora wicaksana.

Miwiti

Mangkene ringkesan umum babagan apa sing bakal kedadeyan ing kode scraper web kita:

  • Ngimpor perpustakaan sing dibutuhake.
  • Mbukak tab Google Chrome.
  • Telpon fungsi sing miwiti bot, ngliwati kutha lan tanggal sing bakal digunakake nalika nggoleki tiket.
  • Fungsi iki njupuk asil panelusuran pisanan, diurutake miturut paling apik, lan klik tombol kanggo mbukak asil liyane.
  • Fungsi liyane ngumpulake data saka kabeh kaca lan ngasilake pigura data.
  • Rong langkah sadurunge ditindakake nggunakake jinis ngurutake miturut rega tiket (murah) lan kanthi kacepetan penerbangan (paling cepet).
  • Pangguna skrip dikirim email sing ngemot ringkesan rega tiket (tiket paling murah lan rega rata-rata), lan pigura data kanthi informasi sing diurutake miturut telung indikator sing kasebut ing ndhuwur disimpen minangka file Excel.
  • Kabeh tumindak ing ndhuwur dileksanakake ing siklus sawise wektu tartamtu.

Perlu dicathet yen saben proyek Selenium diwiwiti kanthi driver web. Aku nggunakake Chromedriver, Aku nggarap Google Chrome, nanging ana opsi liyane. PhantomJS lan Firefox uga populer. Sawise ndownload driver, sampeyan kudu nyelehake ing folder sing cocog, lan iki ngrampungake persiapan kanggo nggunakake. Baris pisanan skrip kita mbukak tab Chrome anyar.

Elinga yen ing critaku, aku ora nyoba mbukak cakrawala anyar kanggo nemokake tawaran sing apik babagan tiket pesawat. Ana cara sing luwih maju kanggo nggoleki tawaran kasebut. Aku mung pengin menehi pembaca materi iki cara sing prasaja nanging praktis kanggo ngatasi masalah iki.

Punika kode sing kita rembugan ing ndhuwur.

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)

Ing wiwitan kode sampeyan bisa ndeleng printah impor paket sing digunakake ing saindhenging project kita. Dadi, randint digunakake kanggo nggawe bot "turu" kanthi acak sawetara detik sadurunge miwiti operasi telusuran anyar. Biasane, bot siji ora bisa nindakake tanpa iki. Yen sampeyan mbukak kode ing ndhuwur, jendhela Chrome bakal mbukak, sing bakal digunakake bot kanggo nggarap situs.

Ayo nindakake eksperimen cilik lan mbukak situs web kayak.com ing jendela sing kapisah. Kita bakal milih kutha saka ngendi kita arep mabur, lan kutha sing arep dituju, uga tanggal penerbangan. Nalika milih tanggal, priksa manawa kisaran +-3 dina digunakake. Aku nulis kode njupuk menyang akun apa situs mrodhuksi kanggo nanggepi panjalukan kuwi. Yen, contone, sampeyan kudu nggoleki tiket mung kanggo tanggal sing ditemtokake, mula ana kemungkinan gedhe sampeyan kudu ngowahi kode bot. Nalika aku pirembagan bab kode, Aku nyedhiyani panjelasan cocok, nanging yen sampeyan aran bingung, mugi kula ngerti.

Saiki klik tombol telusuran lan deleng link ing bilah alamat. Sampeyan kudu padha karo link sing digunakake ing conto ing ngisor iki ing ngendi variabel kasebut diumumake kayak, sing nyimpen URL, lan cara sing digunakake get driver web. Sawise ngeklik tombol telusuran, asil bakal katon ing kaca.

Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan
Nalika aku nggunakake printah get luwih saka loro utawa telu ing sawetara menit, aku dijaluk ngrampungake verifikasi nggunakake reCaptcha. Sampeyan bisa ngliwati mriksa iki kanthi manual lan terus nyoba nganti sistem mutusake kanggo nindakake mriksa anyar. Nalika aku nyoba skrip, kayane sesi telusuran pisanan tansah lancar, dadi yen sampeyan pengin eksprimen karo kode kasebut, sampeyan mung kudu mriksa kanthi manual kanthi manual lan ngidini kode kasebut mlaku, nggunakake interval sing dawa ing antarane sesi telusuran. Lan, yen sampeyan mikir babagan iki, wong ora butuh informasi babagan rega tiket sing ditampa kanthi interval 10 menit ing antarane operasi telusuran.

Nggarap kaca nggunakake XPath

Dadi, kita mbukak jendhela lan mbukak situs kasebut. Kanggo entuk rega lan informasi liyane, kita kudu nggunakake teknologi XPath utawa pamilih CSS. Aku mutusaké kanggo kelet karo XPath lan ora aran perlu kanggo nggunakake pamilih CSS, nanging iku cukup bisa kanggo bisa. Navigasi ing kaca nggunakake XPath bisa uga angel, lan sanajan sampeyan nggunakake teknik sing dakgambarake iki artikel, kang melu nyalin pengenal cocog saka kode kaca, Aku temen maujud sing iki, nyatane, ora cara optimal kanggo ngakses unsur perlu. Miturut cara, ing iki Buku kasebut menehi katrangan sing apik babagan dhasar nggarap kaca kanthi nggunakake pamilih XPath lan CSS. Iki minangka cara driver web sing cocog.

Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan
Dadi, ayo terus nggarap bot. Ayo nggunakake kemampuan program kanggo milih tiket sing paling murah. Ing gambar ing ngisor iki, kode pamilih XPath disorot abang. Kanggo ndeleng kode, sampeyan kudu klik-tengen ing unsur kaca sing kasengsem lan pilih printah Priksa saka menu sing katon. Printah iki bisa diarani unsur kaca sing beda-beda, kode sing bakal ditampilake lan disorot ing panampil kode.

Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan
Ndeleng kode kaca

Kanggo nemokake konfirmasi saka alesan babagan kekurangan nyalin pamilih saka kode, mbayar manungsa waé kanggo fitur ing ngisor iki.

Iki sing sampeyan entuk nalika sampeyan nyalin kode:

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

Kanggo nyalin kaya iki, sampeyan kudu klik-tengen ing bagean kode sing sampeyan minati lan pilih Copy> Copy XPath printah saka menu sing katon.

Mangkene apa sing dakkarepake kanggo nemtokake tombol Paling Murah:

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

Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan
Copy Command > Copy XPath

Cukup jelas yen pilihan kapindho katon luwih gampang. Nalika digunakake, nggoleki unsur a sing nduweni atribut data-code, padha karo price. Nalika nggunakake pilihan pisanan, unsur ditelusuri id kang padha karo wtKI-price_aTab, lan path XPath menyang unsur katon kaya /div[1]/div/div/div[1]/div/span/span. Pitakon XPath kaya iki menyang kaca bakal nindakake trik, nanging mung sapisan. Aku bisa ngomong saiki id bakal ngganti wektu sabanjuré kaca dimuat. Urutan karakter wtKI owah-owahan kanthi dinamis saben-saben kaca dimuat, mula kode sing digunakake bakal ora ana gunane sawise kaca sabanjure dimuat maneh. Dadi njupuk sawetara wektu kanggo ngerti XPath. Kawruh iki bakal migunani kanggo sampeyan.

Nanging, kudu dicathet yen nyalin pamilih XPath bisa migunani nalika nggarap situs sing cukup prasaja, lan yen sampeyan seneng karo iki, ora ana sing salah.

Saiki ayo dipikirake apa sing kudu ditindakake yen sampeyan kudu entuk kabeh asil panelusuran ing sawetara baris, ing dhaptar. Prasaja banget. Saben asil ana ing obyek kanthi kelas resultWrapper. Loading kabeh asil bisa rampung ing daur ulang padha karo sing kapacak ing ngisor iki.

Sampeyan kudu nyatet yen sampeyan ngerti ing ndhuwur, sampeyan kudu gampang ngerti paling kode sing bakal analisa. Nalika kode iki mlaku, kita ngakses apa kita kudu (nyatane, unsur kang asil wis kebungkus) nggunakake sawetara jinis mekanisme path-nemtokake (XPath). Iki ditindakake kanggo entuk teks saka unsur kasebut lan dilebokake ing obyek sing bisa diwaca data (pisanan digunakake flight_containers, banjur - flights_list).

Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan
Telung baris pisanan ditampilake lan kita bisa ndeleng kanthi jelas kabeh sing dibutuhake. Nanging, kita duwe cara sing luwih menarik kanggo entuk informasi. Kita kudu njupuk data saka saben unsur kanthi kapisah.

Ayo kerja!

Cara paling gampang kanggo nulis fungsi yaiku mbukak asil tambahan, mula ing kana kita bakal miwiti. Aku kaya kanggo nggedhekake nomer penerbangan sing program nampa informasi bab, tanpa mundhakaken anggepan ing layanan sing ndadékaké kanggo pengawasan, supaya aku klik tombol Muat liyane asil sapisan saben kaca ditampilake. Ing kode iki, sampeyan kudu menehi perhatian marang blok kasebut try, sing ditambahake amarga kadhangkala tombol ora dimuat kanthi bener. Yen sampeyan uga nemoni iki, komentar metu telpon kanggo fungsi iki ing kode fungsi start_kayak, sing bakal kita deleng ing ngisor iki.

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

Saiki, sawise analisis dawa babagan fungsi iki (kadhangkala aku bisa digawa lunga), kita siyap ngumumake fungsi sing bakal ngikis kaca kasebut.

Aku wis diklumpukake paling saka apa sing perlu ing fungsi ing ngisor iki disebut page_scrape. Kadang data path bali digabungake, aku nggunakake cara prasaja kanggo misahake. Contone, nalika aku nggunakake variabel kanggo pisanan section_a_list и section_b_list. Fungsi kita ngasilake pigura data flights_df, iki ngidini kita misahake asil sing dipikolehi saka macem-macem cara ngurutake data lan mengko gabungke.

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

Aku nyoba jeneng variabel supaya kode bisa dingerteni. Elinga yen variabel diwiwiti karo a kagungane tataran pisanan path, lan b - kanggo kaloro. Ayo pindhah menyang fungsi sabanjure.

Mekanisme dhukungan

Saiki kita duwe fungsi sing ngidini kita mbukak asil panelusuran tambahan lan fungsi kanggo ngolah asil kasebut. Artikel iki bisa rampung ing kene, amarga rong fungsi kasebut nyedhiyakake kabeh sing dibutuhake kanggo ngikis kaca sing bisa dibukak dhewe. Nanging kita durung nganggep sawetara mekanisme tambahan sing dibahas ing ndhuwur. Contone, iki kode kanggo ngirim email lan sawetara liyane. Kabeh iki bisa ditemokake ing fungsi kasebut start_kayak, sing saiki bakal kita nimbang.

Kanggo fungsi iki, sampeyan butuh informasi babagan kutha lan tanggal. Nggunakake informasi iki, mbentuk pranala ing variabel kayak, sing digunakake kanggo nggawa sampeyan menyang kaca sing bakal ngemot asil panelusuran sing diurutake miturut sing paling cocog karo pitakon kasebut. Sawise sesi scraping pisanan, kita bakal nggarap prices ing meja ing sisih ndhuwur kaca. Yaiku, kita bakal nemokake rega tiket minimal lan rega rata-rata. Kabeh iki, bebarengan karo prediksi sing diterbitake dening situs, bakal dikirim liwat email. Ing kaca, tabel sing cocog kudu ana ing pojok kiwa ndhuwur. Nggarap tabel iki, kanthi cara, bisa nyebabake kesalahan nalika nggoleki nggunakake tanggal sing tepat, amarga ing kasus iki tabel ora ditampilake ing kaca kasebut.

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

Aku nyoba script iki nggunakake akun Outlook (hotmail.com). Aku durung nyoba supaya bisa digunakake kanthi bener karo akun Gmail, sistem email iki cukup populer, nanging ana akeh pilihan. Yen sampeyan nggunakake akun Hotmail, supaya kabeh bisa digunakake, sampeyan mung kudu ngetik data menyang kode.

Yen sampeyan pengin ngerti apa sing ditindakake ing bagean tartamtu saka kode kanggo fungsi iki, sampeyan bisa nyalin lan nyoba. Eksperimen karo kode minangka cara mung kanggo ngerti.

Sistem siap

Saiki kita wis rampung kabeh kita ngomong bab, kita bisa nggawe daur ulang prasaja sing nelpon fungsi kita. Skrip njaluk data saka pangguna babagan kutha lan tanggal. Nalika nguji kanthi miwiti maneh skrip, mesthine sampeyan ora pengin nglebokake data iki kanthi manual saben-saben, saengga baris sing cocog, kanggo wektu tes, bisa dikomentari kanthi ora menehi komentar ing ngisor iki, ing ngendi data sing dibutuhake dening script wis hardcoded.

city_from = input('From which city? ')
city_to = input('Where to? ')
date_start = input('Search around which departure date? Please use YYYY-MM-DD format only ')
date_end = input('Return when? Please use YYYY-MM-DD format only ')

# city_from = 'LIS'
# city_to = 'SIN'
# date_start = '2019-08-21'
# date_end = '2019-09-07'

for n in range(0,5):
    start_kayak(city_from, city_to, date_start, date_end)
    print('iteration {} was complete @ {}'.format(n, strftime("%Y%m%d-%H%M")))
    
    # Ждём 4 часа
    sleep(60*60*4)
    print('sleep finished.....')

Iki minangka test run saka skrip.
Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan
Test run saka skrip

Hasil

Yen sampeyan wis tekan adoh, sugeng! Sampeyan saiki duwe scraper web sing bisa digunakake, sanajan aku wis bisa ndeleng akeh cara kanggo nambah. Contone, bisa digabungake karo Twilio supaya ngirim pesen teks tinimbang email. Sampeyan bisa nggunakake VPN utawa liya kanggo nampa asil bebarengan saka sawetara server. Ana uga masalah periodik njedhul karo mriksa pangguna situs kanggo ndeleng apa iku wong, nanging masalah iki uga bisa ditanggulangi. Ing kasus apa wae, saiki sampeyan duwe basis sing bisa ditambahake yen sampeyan pengin. Contone, priksa manawa file Excel dikirim menyang pangguna minangka lampiran menyang email.

Python - asisten nemokake tiket pesawat murah kanggo sing seneng lelungan

Mung pangguna pangguna sing bisa melu survey. mlebunggih.

Apa sampeyan nggunakake teknologi scraping web?

  • Ya

  • Ora

8 pangguna milih. 1 pangguna abstain.

Source: www.habr.com

Add a comment