Python - un asistente para atopar billetes de avión económicos para os que aman viaxar

O autor do artigo, cuxa tradución publicamos hoxe, di que o seu obxectivo é falar do desenvolvemento dun web scraper en Python mediante Selenium, que busca os prezos dos billetes de avión. Ao buscar entradas, utilízanse datas flexibles (+- 3 días en relación ás datas especificadas). O rascador garda os resultados da busca nun ficheiro Excel e envía á persoa que realizou a busca un correo electrónico cun resumo do que atopou. O obxectivo deste proxecto é axudar aos viaxeiros a atopar as mellores ofertas.

Python - un asistente para atopar billetes de avión económicos para os que aman viaxar

Se, mentres comprendes o material, te sentes perdido, bótalle unha ollada isto artigo.

Que imos buscar?

Podes usar o sistema descrito aquí como queiras. Por exemplo, useino para buscar excursións de fin de semana e entradas para a miña cidade natal. Se queres buscar billetes rendibles, podes executar o script no servidor (simple servidor, por 130 rublos ao mes, é bastante axeitado para iso) e asegúrate de que funcione unha ou dúas veces ao día. Os resultados da busca enviaranse por correo electrónico. Ademais, recomendo configurar todo para que o script garde un ficheiro de Excel cos resultados da busca nun cartafol de Dropbox, o que che permitirá ver estes ficheiros desde calquera lugar e en calquera momento.

Python - un asistente para atopar billetes de avión económicos para os que aman viaxar
Aínda non atopei tarifas con erros, pero creo que é posible

Ao buscar, como xa se mencionou, utilízase unha "data flexible"; o script atopa ofertas que están dentro dos tres días das datas indicadas. Aínda que ao executar o script, busca ofertas só nunha dirección, é fácil modificalo para que poida recoller datos en varias direccións de voo. Coa súa axuda, incluso pode buscar tarifas erróneas; tales achados poden ser moi interesantes.

Por que necesitas outro raspador web?

Cando comecei a raspar web, sinceramente non estaba especialmente interesado nel. Quería facer máis proxectos no campo do modelado preditivo, da análise financeira e, posiblemente, no da análise da cor emocional dos textos. Pero resultou que era moi interesante descubrir como crear un programa que recolla datos de sitios web. Mentres profundizaba neste tema, decateime de que o rascado web é o "motor" de Internet.

Podes pensar que esta é unha afirmación demasiado atrevida. Pero considera que Google comezou cun raspador web que Larry Page creou usando Java e Python. Os robots de Google estiveron explorando Internet, intentando ofrecer aos seus usuarios as mellores respostas ás súas preguntas. O rascado web ten usos infinitos e, aínda que che interese noutra cousa en Data Science, necesitarás algunhas habilidades de rascado para obter os datos que necesitas analizar.

Atopei algunhas das técnicas utilizadas aquí nun marabilloso o libro sobre o web scraping, que adquirei recentemente. Contén moitos exemplos sinxelos e ideas para a aplicación práctica do aprendido. Ademais, hai un capítulo moi interesante sobre o paso das comprobacións de reCaptcha. Isto veume como unha noticia, xa que nin sequera sabía que había ferramentas especiais e mesmo servizos enteiros para resolver este tipo de problemas.

Gústache viaxar?!

Á pregunta sinxela e bastante inofensiva formulada no título deste apartado, adoita escoitarse unha resposta positiva, acompañada dun par de historias das viaxes da persoa á que se lle preguntou. A maioría de nós estaríamos de acordo en que viaxar é unha boa forma de mergullarse en novos ambientes culturais e ampliar os seus horizontes. Non obstante, se lle preguntas a alguén se lle gusta buscar billetes de avión, estou seguro de que a resposta non será tan positiva. De feito, Python vén na nosa axuda aquí.

A primeira tarefa que debemos resolver no camiño para crear un sistema de busca de información sobre billetes de avión será seleccionar unha plataforma adecuada da que tomaremos información. Resolver este problema non foi doado para min, pero ao final escollín o servizo de Kayak. Probei os servizos de Momondo, Skyscanner, Expedia e algúns outros, pero os mecanismos de protección do robot destes recursos eran impenetrables. Despois de varios intentos, durante os cales tiven que lidiar con semáforos, pasos de peóns e bicicletas, intentando convencer aos sistemas de que era humano, decidín que Kayak era o máis axeitado para min, a pesar de que aínda que se cargasen demasiadas páxinas. en pouco tempo, e tamén comezan os controis. Conseguín que o bot enviara solicitudes ao sitio a intervalos de 4 a 6 horas e todo funcionou ben. De cando en vez, xorden dificultades ao traballar con Kayak, pero se comezan a molestarche coas comprobacións, entón tes que tratalas manualmente e despois lanzar o bot ou esperar unhas horas e as comprobacións deberían deterse. Se é necesario, podes adaptar facilmente o código a outra plataforma e, se o fas, podes denuncialo nos comentarios.

Se estás comezando co raspado web e non sabes por que algúns sitios web loitan con el, antes de comezar o teu primeiro proxecto nesta área, fai un favor e busca en Google as palabras "etiqueta de raspado web". . É posible que os teus experimentos rematen antes do que pensas se fas un raspado web de forma imprudente.

introdución

Aquí tes unha visión xeral do que ocorrerá no noso código de raspador web:

  • Importa as bibliotecas necesarias.
  • Abrir unha pestana de Google Chrome.
  • Chama a unha función que inicia o bot, pasándolle as cidades e datas que se utilizarán á hora de buscar entradas.
  • Esta función toma os primeiros resultados da busca, ordenados polo mellor, e fai clic nun botón para cargar máis resultados.
  • Outra función recolle datos de toda a páxina e devolve un marco de datos.
  • Os dous pasos anteriores realízanse utilizando tipos de clasificación por prezo do billete (barato) e por velocidade de voo (máis rápido).
  • Envíase ao usuario do script un correo electrónico que contén un resumo dos prezos das entradas (billets máis baratos e prezo medio) e gárdase como ficheiro Excel un marco de datos coa información ordenada polos tres indicadores anteriormente mencionados.
  • Todas as accións anteriores realízanse nun ciclo despois dun período de tempo especificado.

Nótese que cada proxecto de Selenium comeza cun controlador web. Eu uso Chromedriver, traballo con Google Chrome, pero hai outras opcións. PhantomJS e Firefox tamén son populares. Despois de descargar o controlador, cómpre colocalo no cartafol apropiado, e isto completa a preparación para o seu uso. As primeiras liñas do noso script abren unha nova pestana de Chrome.

Teña en conta que na miña historia non intento abrir novos horizontes para atopar grandes ofertas en billetes de avión. Existen métodos moito máis avanzados para buscar tales ofertas. Só quero ofrecer aos lectores deste material unha forma sinxela pero práctica de resolver este problema.

Aquí está o código do que falamos anteriormente.

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)

Ao comezo do código podes ver os comandos de importación de paquetes que se usan ao longo do noso proxecto. Entón, randint úsase para facer que o bot se "durmise" durante un número aleatorio de segundos antes de iniciar unha nova operación de busca. Normalmente, nin un só bot pode prescindir diso. Se executas o código anterior, abrirase unha xanela de Chrome, que o bot utilizará para traballar cos sitios.

Fagamos un pequeno experimento e abramos o sitio web kayak.com nunha ventá separada. Seleccionaremos a cidade desde a que imos voar e a cidade á que queremos chegar, así como as datas dos voos. Ao escoller datas, asegúrese de usar o intervalo de +-3 días. Escribín o código tendo en conta o que produce o sitio en resposta a tales solicitudes. Se, por exemplo, precisa buscar entradas só para datas especificadas, entón hai unha alta probabilidade de que teña que modificar o código do bot. Cando falo do código, dou as explicacións axeitadas, pero se te sentes confuso, avisame.

Agora fai clic no botón de procura e mira a ligazón na barra de enderezos. Debería ser semellante á ligazón que uso no seguinte exemplo onde se declara a variable kayak, que almacena o URL e úsase o método get controlador web. Despois de facer clic no botón de busca, os resultados deberían aparecer na páxina.

Python - un asistente para atopar billetes de avión económicos para os que aman viaxar
Cando usei o comando get máis de dúas ou tres veces en poucos minutos, pedíronme que completase a verificación mediante reCaptcha. Podes pasar esta comprobación manualmente e continuar experimentando ata que o sistema decida realizar unha nova comprobación. Cando probei o script, parecía que a primeira sesión de busca sempre se realizaba sen problemas, polo que se quería probar co código, só tería que comprobar periodicamente manualmente e deixar executar o código, utilizando intervalos longos entre sesións de busca. E, se o pensas niso, é improbable que unha persoa necesite información sobre os prezos dos billetes recibidos a intervalos de 10 minutos entre as operacións de busca.

Traballar cunha páxina usando XPath

Entón, abrimos unha fiestra e cargamos o sitio. Para obter prezos e outra información, necesitamos utilizar a tecnoloxía XPath ou os selectores CSS. Decidín seguir con XPath e non sentín a necesidade de usar selectores CSS, pero é moi posible que funcione así. Navegar por unha páxina usando XPath pode ser complicado, e aínda que uses as técnicas que describín isto artigo, que implicaba copiar os identificadores correspondentes do código da páxina, decateime de que esta, de feito, non é a forma óptima de acceder aos elementos necesarios. Por certo, en isto O libro ofrece unha excelente descrición dos conceptos básicos de traballar con páxinas usando os selectores XPath e CSS. Este é o aspecto do método de controlador web correspondente.

Python - un asistente para atopar billetes de avión económicos para os que aman viaxar
Entón, sigamos traballando no bot. Usemos as capacidades do programa para seleccionar os billetes máis baratos. Na seguinte imaxe, o código selector XPath está resaltado en vermello. Para ver o código, cómpre facer clic co botón dereito no elemento da páxina que che interesa e seleccionar o comando Inspeccionar no menú que aparece. Este comando pódese chamar para diferentes elementos da páxina, cuxo código se mostrará e destacará no visor de código.

Python - un asistente para atopar billetes de avión económicos para os que aman viaxar
Ver código da páxina

Para confirmar o meu razoamento sobre as desvantaxes de copiar selectores do código, preste atención ás seguintes características.

Isto é o que obtén ao copiar o código:

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

Para copiar algo así, cómpre facer clic co botón dereito na sección de código que che interesa e seleccionar o comando Copiar > Copiar XPath no menú que aparece.

Isto é o que usei para definir o botón Máis barato:

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

Python - un asistente para atopar billetes de avión económicos para os que aman viaxar
Comando de copia > Copiar XPath

É bastante obvio que a segunda opción parece moito máis sinxela. Cando se usa, busca un elemento a que teña o atributo data-codeigual a price. Cando se utiliza a primeira opción, búscase o elemento id que é igual a wtKI-price_aTab, e o camiño XPath ao elemento parece /div[1]/div/div/div[1]/div/span/span. Unha consulta XPath como esta a unha páxina fará o truco, pero só unha vez. Podo dicir agora que id cambiará a próxima vez que se cargue a páxina. Secuencia de caracteres wtKI cambia de forma dinámica cada vez que se carga a páxina, polo que o código que a utiliza será inútil despois da seguinte recarga da páxina. Así que tómase un tempo para entender XPath. Este coñecemento servirache ben.

Non obstante, hai que ter en conta que copiar os selectores XPath pode ser útil cando se traballa con sitios bastante sinxelos e, se estás cómodo con isto, non hai nada de malo.

Agora pensemos que facer se necesitas obter todos os resultados da busca en varias liñas, dentro dunha lista. Moi sinxelo. Cada resultado está dentro dun obxecto cunha clase resultWrapper. A carga de todos os resultados pódese facer nun bucle similar ao que se mostra a continuación.

Nótese que se entende o anterior, debería comprender facilmente a maior parte do código que analizaremos. A medida que se executa este código, accedemos ao que necesitamos (de feito, o elemento no que se envolve o resultado) mediante algún tipo de mecanismo de especificación de rutas (XPath). Isto faise co fin de obter o texto do elemento e colocalo nun obxecto do que se poidan ler os datos (utilizado primeiro flight_containers, entón - flights_list).

Python - un asistente para atopar billetes de avión económicos para os que aman viaxar
As tres primeiras liñas móstranse e podemos ver claramente todo o que necesitamos. Porén, temos formas máis interesantes de obter información. Necesitamos tomar os datos de cada elemento por separado.

Poñerse a traballar!

O xeito máis doado de escribir unha función é cargar resultados adicionais, polo que aí comezaremos. Gustaríame maximizar o número de voos dos que o programa recibe información, sen levantar sospeitas no servizo que leva a unha inspección, polo que premo no botón Cargar máis resultados unha vez cada vez que se mostra a páxina. Neste código, debes prestar atención ao bloque try, que engadín porque ás veces o botón non se carga correctamente. Se tamén atopas isto, comenta as chamadas a esta función no código da función start_kayak, que veremos a continuación.

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

Agora, despois dunha longa análise desta función (ás veces podo deixarme levar), estamos preparados para declarar unha función que raspará a páxina.

Xa recollín a maior parte do necesario na seguinte función chamada page_scrape. Ás veces, os datos do camiño devolto combínanse, polo que uso un método sinxelo para separalos. Por exemplo, cando uso variables por primeira vez section_a_list и section_b_list. A nosa función devolve un marco de datos flights_df, isto permítenos separar os resultados obtidos de diferentes métodos de ordenación de datos e combinalos posteriormente.

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

Tentei nomear as variables para que o código fose comprensible. Lembra que as variables comezan por a pertencen á primeira etapa do camiño, e b - ao segundo. Pasemos á seguinte función.

Mecanismos de apoio

Agora temos unha función que nos permite cargar resultados de busca adicionais e unha función para procesar eses resultados. Este artigo podería ter rematado aquí, xa que estas dúas funcións proporcionan todo o que precisa para raspar páxinas que pode abrir vostede mesmo. Pero aínda non consideramos algúns dos mecanismos auxiliares comentados anteriormente. Por exemplo, este é o código para enviar correos electrónicos e algunhas outras cousas. Todo isto pódese atopar na función start_kayak, que agora consideraremos.

Para que esta función funcione, necesitas información sobre cidades e datas. Usando esta información, forma unha ligazón nunha variable kayak, que se usa para levarche a unha páxina que conterá resultados de busca ordenados segundo a súa mellor coincidencia coa consulta. Despois da primeira sesión de raspado, traballaremos cos prezos da táboa na parte superior da páxina. É dicir, atoparemos o prezo mínimo da entrada e o prezo medio. Todo isto, xunto coa predición emitida polo sitio, enviarase por correo electrónico. Na páxina, a táboa correspondente debería estar na esquina superior esquerda. Traballar con esta táboa, por certo, pode provocar un erro ao buscar usando datas exactas, xa que neste caso a táboa non se mostra na páxina.

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

Probei este script usando unha conta de Outlook (hotmail.com). Non o probei para funcionar correctamente cunha conta de Gmail, este sistema de correo electrónico é bastante popular, pero hai moitas opcións posibles. Se usas unha conta de Hotmail, para que todo funcione, só tes que introducir os teus datos no código.

Se queres comprender o que se está a facer exactamente en seccións específicas do código desta función, podes copialas e experimentar con elas. Experimentando co código é o único xeito de entendelo verdadeiramente.

Sistema listo

Agora que fixemos todo o que falamos, podemos crear un bucle sinxelo que chame as nosas funcións. O script solicita ao usuario datos sobre cidades e datas. Ao probar con reinicio constante do script, é improbable que queira introducir estes datos manualmente cada vez, polo que as liñas correspondentes, para o momento da proba, poden ser comentadas descommentando as que están debaixo delas, nas que os datos necesarios polo o script está codificado.

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

Este é o aspecto dunha execución de proba do script.
Python - un asistente para atopar billetes de avión económicos para os que aman viaxar
Execución de proba do script

Resultados de

Se chegaches ata aquí, parabéns! Agora tes un raspador web funcionando, aínda que xa vexo moitas formas de melloralo. Por exemplo, pódese integrar con Twilio para que envíe mensaxes de texto en lugar de correos electrónicos. Podes usar unha VPN ou outra cousa para recibir simultáneamente resultados de varios servidores. Tamén hai un problema periódico ao comprobar o usuario do sitio para ver se é unha persoa, pero este problema tamén se pode solucionar. En todo caso, agora tes unha base que podes ampliar se o desexas. Por exemplo, asegúrese de que se envía un ficheiro de Excel ao usuario como anexo a un correo electrónico.

Python - un asistente para atopar billetes de avión económicos para os que aman viaxar

Só os usuarios rexistrados poden participar na enquisa. Rexístrate, por favor.

Usas tecnoloxías de rascado web?

  • Si

  • Non

Votaron 8 usuarios. 1 usuario abstívose.

Fonte: www.habr.com

Engadir un comentario