Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat

Panulis artikel, tarjamahan nu urang medarkeun kiwari, nyebutkeun yén tujuanana nyaéta pikeun ngobrol ngeunaan ngembangkeun hiji scraper web di Python ngagunakeun Selenium, nu maluruh harga tikét maskapai. Nalika milarian tikét, tanggal anu fleksibel dianggo (+- 3 dinten relatif ka tanggal anu ditangtukeun). scraper The ngaheéat hasil teangan dina file Excel sarta ngirimkeun jalma anu ngajalankeun pilarian hiji email kalawan kasimpulan naon maranéhna kapanggih. Tujuan tina proyék ieu nyaéta pikeun ngabantosan wisatawan mendakan tawaran anu pangsaéna.

Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat

Lamun, bari ngartos materi, Anjeun ngarasa leungit, cokot katingal di ieu artikel.

Naon anu urang badé milarian?

Anjeun bébas ngagunakeun sistem anu dijelaskeun di dieu sakumaha anu dipikahoyong. Salaku conto, kuring dianggo pikeun milarian wisata sabtu minggu sareng tiket ka kampung halaman kuring. Upami anjeun serius milarian tikét anu nguntungkeun, anjeun tiasa ngajalankeun naskah dina server (saderhana sérver, pikeun 130 rubles sabulan, cukup cocog pikeun ieu) jeung pastikeun yén éta ngajalankeun sakali atawa dua kali sapoé. Hasil teangan bakal dikirim ka anjeun ku email. Salaku tambahan, kuring nyarankeun nyetél sadayana supados naskah nyimpen file Excel kalayan hasil pamilarian dina polder Dropbox, anu bakal ngamungkinkeun anjeun ningali file sapertos ti mana waé sareng iraha waé.

Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat
Kuring henteu acan mendakan tarif anu aya kasalahan, tapi kuring pikir éta mungkin

Nalika milarian, sakumaha anu parantos disebatkeun, "tanggal fleksibel" dianggo; naskah mendakan tawaran anu aya dina tilu dinten ti tanggal anu dipasihkeun. Sanaos nalika ngajalankeun naskah, éta milarian tawaran ngan ukur dina hiji arah, éta gampang pikeun ngarobih supados tiasa ngumpulkeun data dina sababaraha arah penerbangan. Kalayan bantosanana, anjeun malah tiasa milarian tarif anu salah; panemuan sapertos kitu tiasa pikaresepeun pisan.

Naha anjeun peryogi scraper wéb anu sanés?

Nalika kuring mimiti ngamimitian ngikis wéb, jujur ​​kuring henteu resep pisan kana éta. Kuring hayang ngalakukeun leuwih proyék dina widang modeling duga, analisis finansial, jeung, jigana, dina widang analisa ngawarnaan emosi téks. Tapi tétéla éta pisan metot pikeun manggihan cara nyieun program anu ngumpulkeun data tina situs web. Salaku I delved kana topik ieu, abdi sadar yen web scraping teh "mesin" tina Internet.

Anjeun tiasa nganggap yén ieu mangrupikeun pernyataan anu wani teuing. Tapi mertimbangkeun yén Google dimimitian ku scraper web nu Larry Page dijieun maké Java jeung Python. Robot Google parantos ngajalajah Internét, nyobian masihan panggunana jawaban anu pangsaéna pikeun patarosanana. Web scraping boga kagunaan sajajalan, komo lamun museurkeun hal sejenna dina Élmu Data, anjeun bakal kudu sababaraha kaahlian scraping pikeun meunangkeun data nu peryogi analisa.

Kuring kapanggih sababaraha téhnik dipaké di dieu dina éndah nyaéta buku ngeunaan web scraping, nu kuring nembe kaala. Ieu ngandung loba conto basajan jeung gagasan pikeun aplikasi praktis naon geus diajar. Sajaba ti éta, aya bab pisan metot ngeunaan bypassing cék reCaptcha. Ieu janten warta pikeun kuring, sabab kuring henteu terang yén aya alat khusus bahkan sadayana jasa pikeun ngarengsekeun masalah sapertos kitu.

Naha anjeun resep ngarambat?!

Pikeun patarosan anu sederhana sareng henteu bahaya anu diajukeun dina judul bagian ieu, anjeun sering tiasa ngupingkeun jawaban anu positip, dipirig ku sababaraha carita tina perjalanan jalma anu ditaroskeun. Seuseueurna urang bakal satuju yén iinditan mangrupikeun cara anu saé pikeun neuleumkeun diri dina lingkungan budaya anyar sareng ngalegaan cakrawala anjeun. Nanging, upami anjeun naroskeun ka batur naha aranjeunna resep milarian tikét maskapai, kuring yakin yén jawabanna moal positip. Nyatana, Python ngabantosan kami di dieu.

Tugas kahiji anu kedah urang rengsekeun dina jalan nyiptakeun sistem pikeun milarian inpormasi ngeunaan tiket pesawat bakal milih platform anu cocog dimana urang bakal nyandak inpormasi. Ngarengsekeun masalah ieu teu gampang pikeun kuring, tapi tungtungna kuring milih layanan Kayak. Kuring nyobian jasa Momondo, Skyscanner, Expedia, sareng sababaraha anu sanés, tapi mékanisme panyalindungan robot dina sumber-sumber ieu teu tiasa ditembus. Saatos sababaraha usaha, salila kuring kungsi nungkulan lampu lalulintas, nyebrang pedestrian jeung sapédah, nyoba ngayakinkeun sistem nu kuring manusa, Kuring mutuskeun yén Kayak éta pangalusna cocog pikeun kuring, sanajan kanyataan yén sanajan loba teuing kaca dimuat. dina waktu anu singget, sarta cék ogé dimimitian. Kuring junun nyieun bot ngirim requests ka loka dina interval 4 ka 6 jam, sarta sagalana digawé rupa. Ti jaman ka jaman, kasusah timbul nalika gawé bareng Kayak, tapi lamun aranjeunna mimiti pestering anjeun kalawan cék, anjeun kudu boh nungkulan aranjeunna sacara manual lajeng ngajalankeun bot, atawa antosan sababaraha jam jeung cék kudu eureun. Upami diperlukeun, anjeun tiasa kalayan gampang adaptasi kode pikeun platform anu sanés, sareng upami anjeun ngalakukeun éta, anjeun tiasa ngalaporkeun dina koméntar.

Lamun nuju ngan ngamimitian kalawan web scraping tur teu nyaho naha sababaraha situs web bajoang jeung eta, teras sateuacan Anjeun proyék munggaran anjeun di wewengkon ieu, ngalakukeun diri ni'mat sarta ngalakukeun hiji pilarian Google dina kecap "web scraping tata titi" . percobaan Anjeun bisa mungkas sooner ti anjeun pikir lamun ngalakukeun web scraping unwisely.

Ngalalanyahan

Ieu gambaran umum ngeunaan naon anu bakal kajadian dina kode scraper wéb kami:

  • Impor perpustakaan anu diperyogikeun.
  • Muka tab Google Chrome.
  • Nelepon fungsi anu ngamimitian bot, ngalangkungan kota sareng kaping anu bakal dianggo nalika milarian tikét.
  • Pungsi ieu nyandak hasil pamilarian anu munggaran, diurutkeun dumasar kana anu pangsaéna, sareng ngaklik tombol pikeun ngamuat langkung seueur hasil.
  • Pungsi séjén ngumpulkeun data tina sakabéh kaca sarta mulih pigura data.
  • Dua léngkah saacanna dilakukeun ngagunakeun jinis asihan ku harga tiket (mirah) sareng ku laju penerbangan (panggancangna).
  • Pangguna naskah dikirim email anu ngandung kasimpulan harga tikét (tikét paling murah sareng harga rata-rata), sareng pigura data kalayan inpormasi anu disusun ku tilu indikator anu disebatkeun di luhur disimpen salaku file Excel.
  • Sadaya tindakan di luhur dilakukeun dina siklus saatos waktos anu ditangtukeun.

Perlu dicatet yén unggal proyék Selenium dimimitian ku supir wéb. Kuring make Chromedriver, Kuring digawekeun ku Google Chrome, tapi aya pilihan séjén. PhantomJS sareng Firefox ogé populér. Saatos unduh supir, anjeun kedah nempatkeun éta dina polder anu pas, sareng ieu parantos ngalengkepan persiapan pikeun dianggo. Baris mimiti naskah urang muka tab Chrome anyar.

Émut yén dina carita kuring kuring henteu nyobian muka cakrawala énggal pikeun milarian tawaran anu saé dina tiket pesawat. Aya metode anu langkung maju pikeun milarian tawaran sapertos kitu. Abdi ngan hoyong nawiskeun pamiarsa bahan ieu cara basajan tapi praktis pikeun ngajawab masalah ieu.

Ieu kode anu urang bahas di luhur.

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)

Dina awal kode anjeun tiasa ningali paréntah impor pakét anu dianggo sapanjang proyék kami. Janten, randint dipaké pikeun nyieun bot "turun saré" pikeun jumlah acak detik saméméh dimimitian operasi pilarian anyar. Biasana, teu hiji bot tunggal bisa ngalakukeun tanpa ieu. Upami anjeun ngajalankeun kodeu di luhur, jandela Chrome bakal dibuka, anu bakal dianggo ku bot pikeun damel sareng situs.

Hayu urang ngalakukeun percobaan saeutik tur muka ramatloka kayak.com dina jandela misah. Urang bakal milih kota ti mana urang bade ngapung, jeung kota nu urang hayang nepi ka, kitu ogé tanggal hiber. Nalika milih kaping, pastikeun yén rentang +-3 poé dipaké. Kuring nulis kode nyokot kana akun naon situs ngahasilkeun di respon kana requests misalna. Upami, contona, anjeun kedah milarian tikét ngan ukur kanggo tanggal anu ditangtukeun, maka kamungkinan kamungkinan anjeun kedah ngarobih kode bot. Nalika kuring ngobrol ngeunaan kode, Kuring nyadiakeun guaran luyu, tapi lamun ngarasa bingung, hayu atuh nyaho.

Ayeuna klik tombol milarian sareng tingali tautan dina palang alamat. Éta kedah sami sareng tautan anu kuring anggo dina conto di handap dimana variabel dinyatakeun kayak, nu nyimpen URL, sarta metoda dipaké get supir wéb. Saatos ngaklik tombol milarian, hasilna kedah muncul dina halaman.

Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat
Nalika kuring dipaké paréntah get leuwih ti dua atawa tilu kali dina sababaraha menit, kuring dipenta pikeun ngalengkepan verifikasi maké reCaptcha. Anjeun tiasa lulus cék ieu sacara manual sareng teraskeun ékspérimén dugi sistem mutuskeun pikeun ngajalankeun cék énggal. Nalika kuring diuji naskah, éta seemed kawas sési pilarian munggaran salawasna lancar, jadi lamun hayang ékspérimén kalawan kode, Anjeun ngan bakal kudu périodik pariksa sacara manual sarta ngantep kode ngajalankeun, ngagunakeun interval panjang antara sesi pilarian. Sareng, upami anjeun mikirkeun éta, jalma sigana henteu peryogi inpormasi ngeunaan harga tikét anu ditampi dina interval 10 menit antara operasi milarian.

Gawe sareng halaman nganggo XPath

Janten, kami muka jandela sareng ngamuat situs. Pikeun kéngingkeun harga sareng inpormasi anu sanés, urang kedah nganggo téknologi XPath atanapi pamilih CSS. Kuring mutuskeun lengket kalayan XPath sarta teu ngarasa perlu ngagunakeun CSS selectors, tapi éta rada mungkin pikeun digawé cara éta. Napigasi ngurilingan halaman nganggo XPath tiasa sesah, bahkan upami anjeun nganggo téknik anu dijelaskeun ku kuring ieu artikel, nu aub nyalin identifiers saluyu tina kode kaca, abdi sadar yén ieu téh, kanyataanna, teu cara optimal pikeun ngakses elemen perlu. Ku jalan kitu, di ieu Buku éta nyayogikeun pedaran anu saé ngeunaan dasar-dasar damel sareng halaman nganggo pamilih XPath sareng CSS. Ieu mangrupikeun metode supir wéb anu cocog.

Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat
Janten, hayu urang teraskeun damel dina bot. Hayu urang nganggo kamampuan program pikeun milih tiket anu paling murah. Dina gambar di handap ieu, kodeu pamilih XPath disorot beureum. Pikeun ningali kodeu, anjeun kedah klik katuhu dina unsur halaman anu anjeun pikahoyong sareng pilih paréntah Inspect tina ménu anu muncul. Paréntah ieu tiasa disebat pikeun elemen halaman anu béda, kodeu anu bakal ditingalikeun sareng disorot dina panempo kode.

Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat
Témbongkeun kode kaca

Dina raraga neangan konfirmasi tina alesan kuring ngeunaan kalemahan nyalin selectors tina kode, nengetan fitur di handap ieu.

Ieu anu anjeun kéngingkeun nalika anjeun nyalin kodeu:

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

Pikeun nyalin sapertos kieu, anjeun kedah klik-katuhu dina bagian kode anu anjeun pikahoyong sareng pilih Copy> Copy XPath paréntah tina ménu anu muncul.

Ieu naon anu kuring biasa ngartikeun tombol Murah:

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

Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat
Salin Komando > Salin XPath

Ieu rada atra yén pilihan kadua Sigana leuwih basajan. Nalika dianggo, éta milarian unsur a anu ngagaduhan atribut data-code, sarua price. Lamun ngagunakeun pilihan kahiji, unsur searched id nu sarua jeung wtKI-price_aTab, Jeung jalur XPath ka elemen Sigana mah /div[1]/div/div/div[1]/div/span/span. Paménta XPath sapertos kieu ka halaman bakal ngalakukeun trik, tapi ngan sakali. Abdi tiasa nyarios ayeuna éta id bakal robah dina waktos salajengna kaca dimuat. Runtuyan karakter wtKI robah dinamis unggal waktos kaca dimuat, jadi kode nu ngagunakeun eta bakal aya gunana sanggeus kaca salajengna ngamuat. Janten nyandak sababaraha waktos ngartos XPath. pangaweruh ieu bakal ngawula ka anjeun ogé.

Nanging, éta kedah diperhatoskeun yén nyalin pamilih XPath tiasa mangpaat nalika damel sareng situs anu saderhana, sareng upami anjeun teu nyaman sareng ieu, teu aya anu lepat.

Ayeuna hayu urang pikirkeun naon anu kudu dilakukeun upami anjeun kedah kéngingkeun sadaya hasil pamilarian dina sababaraha baris, dina daptar. Basajan pisan. Unggal hasil aya di jero hiji obyék kalayan kelas resultWrapper. Ngamuat sadaya hasil tiasa dilakukeun dina loop anu sami sareng anu dipidangkeun di handap ieu.

Ieu kudu dicatet yén lamun ngartos di luhur, anjeun kudu gampang ngartos lolobana kode nu urang bakal analisa. Nalika kode ieu dijalankeun, urang ngaksés naon anu urang peryogikeun (saleresna, unsur dimana hasilna dibungkus) nganggo sababaraha mékanisme jalur-spésifik (XPath). Hal ieu dilakukeun pikeun meunangkeun téks unsur sareng nempatkeunna dina obyék dimana data tiasa dibaca (mimiti dianggo). flight_containers, satuluyna - flights_list).

Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat
Tilu garis kahiji dipintonkeun sareng urang jelas tiasa ningali sadayana anu urang peryogikeun. Nanging, urang gaduh cara anu langkung narik pikeun kéngingkeun inpormasi. Urang kedah nyandak data tina unggal unsur nyalira.

Meunang gawe!

Cara panggampangna pikeun nulis fungsi nyaéta pikeun ngamuat hasil tambahan, ku kituna urang bakal ngamimitian. Abdi hoyong ngamaksimalkeun jumlah penerbangan nu program narima informasi ngeunaan, tanpa raising kacurigaan dina layanan nu ngakibatkeun hiji inspeksi, jadi kuring klik Beban langkung hasilna tombol sakali unggal waktos kaca dipintonkeun. Dina kode ieu, anjeun kedah nengetan blok try, nu kuring ditambahkeun sabab kadang tombol teu dimuat leres. Lamun ogé sapatemon ieu, mairan kaluar nelepon ka fungsi ieu dina kode fungsi start_kayak, anu bakal urang tingali di handap.

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

Ayeuna, sanggeus analisa panjang fungsi ieu (kadangkala kuring bisa meunang dibawa jauh), kami siap dibewarakeun fungsi anu bakal kerok kaca.

Kuring geus geus dikumpulkeun lolobana naon anu diperlukeun dina fungsi handap disebut page_scrape. Kadang-kadang data jalur balik digabungkeun, jadi kuring make metoda basajan pikeun misahkeun eta. Contona, nalika kuring ngagunakeun variabel pikeun kahiji kalina section_a_list и section_b_list. Fungsi kami ngabalikeun pigura data flights_df, Hal ieu ngamungkinkeun urang pikeun misahkeun hasil anu dicandak tina metode asihan data anu béda-béda sareng engké ngagabungkeunana.

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

Kuring diusahakeun ngaranan variabel supados kode bakal kaharti. Inget yén variabel dimimitian ku a milik tahap kahiji tina jalur, jeung b - ka kadua. Hayu urang ngaléngkah ka fungsi salajengna.

Mékanisme rojongan

Urang ayeuna gaduh fungsi anu ngamungkinkeun urang pikeun ngamuat hasil pamilarian tambahan sareng fungsi pikeun ngolah hasil éta. Artikel ieu bisa geus réngsé di dieu, saprak dua fungsi ieu nyadiakeun sagalana nu peryogi pikeun kerok kaca nu bisa muka sorangan. Tapi kami henteu acan nganggap sababaraha mékanisme bantu anu dibahas di luhur. Salaku conto, ieu mangrupikeun kode pikeun ngirim email sareng sababaraha hal anu sanés. Sadaya ieu tiasa dipendakan dina fungsina start_kayak, nu ayeuna urang bakal mertimbangkeun.

Pikeun fungsi ieu jalan, anjeun peryogi inpormasi ngeunaan kota sareng kaping. Ngagunakeun informasi ieu, éta ngabentuk tumbu dina variabel kayak, nu dipaké pikeun mawa anjeun ka kaca nu bakal ngandung hasil teangan disusun dumasar cocok pangalusna maranéhanana pikeun query. Saatos sési scraping munggaran, urang bakal bisa dipaké jeung harga dina tabel di luhur kaca. Nyaéta, urang bakal mendakan harga tiket minimum sareng harga rata-rata. Sadaya ieu, sareng prediksi anu dikaluarkeun ku situs, bakal dikirim ku email. Dina kaca, tabel anu cocog kedah aya di belah kénca juru luhur. Gawe sareng tabel ieu, ku jalan kitu, tiasa nyababkeun kasalahan nalika milarian nganggo tanggal pasti, sabab dina hal ieu tabel henteu ditingalikeun dina halaman éta.

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

Kuring nguji naskah ieu nganggo akun Outlook (hotmail.com). Kuring henteu acan nguji éta pikeun dianggo leres sareng akun Gmail, sistem email ieu cukup populér, tapi aya seueur pilihan anu mungkin. Upami anjeun nganggo akun Hotmail, teras supados sadayana tiasa jalan, anjeun ngan ukur kedah ngalebetkeun data anjeun kana kodeu.

Upami anjeun hoyong ngartos naon anu dilakukeun dina bagian khusus kodeu pikeun fungsi ieu, anjeun tiasa nyalin sareng ékspérimén sareng aranjeunna. Ékspérimén sareng kode mangrupikeun hiji-hijina cara pikeun leres-leres ngartos éta.

Sistim siap

Ayeuna urang geus rengse sagalana urang ngobrol ngeunaan, urang bisa nyieun loop basajan nu nelepon fungsi urang. Skrip nyuhunkeun data ti pangguna ngeunaan kota sareng kaping. Nalika nguji kalayan balikan deui naskah, anjeun moal mungkin hoyong ngalebetkeun data ieu sacara manual unggal waktos, ku kituna garis anu saluyu, pikeun waktos tés, tiasa dikoméntarkeun ku ngaleungitkeun koméntar anu aya di handapna, dimana data anu diperyogikeun ku éta. naskah geus 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.....')

Ieu mangrupikeun tés uji skrip.
Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat
Uji coba naskah

hasil

Upami anjeun parantos dugi ka ieu, ucapan salamet! Anjeun ayeuna gaduh scraper wéb anu tiasa dianggo, sanaos kuring parantos ningali seueur cara pikeun ningkatkeun éta. Salaku conto, éta tiasa dihijikeun sareng Twilio supados ngirim pesen téks tibatan email. Anjeun tiasa nganggo VPN atanapi anu sanés pikeun sakaligus nampi hasil tina sababaraha server. Aya ogé masalah anu timbul périodik sareng mariksa pangguna situs pikeun ningali naha anjeunna jalma, tapi masalah ieu ogé tiasa direngsekeun. Dina naon waé, ayeuna anjeun gaduh dasar anu tiasa dilegakeun upami anjeun hoyong. Contona, pastikeun yén file Excel dikirim ka pamaké salaku gagantel kana surelek.

Python - asisten dina manggihan tikét hawa murah pikeun maranéhanana anu resep ngarambat

Ngan pamaké nu kadaptar bisa ilubiung dina survey. Daptar, Punten.

Naha anjeun nganggo téknologi scraping wéb?

  • yen

  • teu

8 pamaké milih. 1 pamaké abstained.

sumber: www.habr.com

Tambahkeun komentar