Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar

El autor del artículo, cuya traducción publicamos hoy, dice que su objetivo es hablar sobre el desarrollo de un web scraper en Python utilizando Selenium, que busca precios de billetes de avión. A la hora de buscar billetes se utilizan fechas flexibles (+- 3 días con respecto a las fechas especificadas). El raspador guarda los resultados de la búsqueda en un archivo de Excel y envía a la persona que realizó la búsqueda un correo electrónico con un resumen de lo que encontró. El objetivo de este proyecto es ayudar a los viajeros a encontrar las mejores ofertas.

Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar

Si mientras comprendes el material te sientes perdido, echa un vistazo a este artículo

¿Qué estamos buscando?

Eres libre de utilizar el sistema descrito aquí como desees. Por ejemplo, lo usé para buscar tours de fin de semana y entradas para mi ciudad natal. Si realmente desea encontrar boletos rentables, puede ejecutar el script en el servidor (simple servidor, por 130 rublos al mes, es bastante adecuado para esto) y asegúrese de que funcione una o dos veces al día. Los resultados de la búsqueda se le enviarán por correo electrónico. Además, recomiendo configurar todo para que el script guarde un archivo de Excel con los resultados de la búsqueda en una carpeta de Dropbox, lo que le permitirá ver dichos archivos desde cualquier lugar y en cualquier momento.

Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar
Aún no he encontrado tarifas con errores, pero creo que es posible.

Al realizar la búsqueda, como ya se mencionó, se utiliza la “fecha flexible”, el script encuentra ofertas que se encuentran dentro de los tres días posteriores a las fechas indicadas. Aunque al ejecutar el script busca ofertas en una sola dirección, es fácil modificarlo para que pueda recopilar datos en varias direcciones de vuelo. Con su ayuda, incluso puedes buscar tarifas erróneas; estos hallazgos pueden ser muy interesantes.

¿Por qué necesitas otro raspador web?

Cuando comencé con el web scraping, sinceramente, no estaba particularmente interesado en ello. Quería hacer más proyectos en el campo del modelado predictivo, análisis financiero y, posiblemente, en el campo del análisis del color emocional de los textos. Pero resultó que era muy interesante descubrir cómo crear un programa que recopile datos de sitios web. Mientras profundizaba en este tema, me di cuenta de que el web scraping es el "motor" de Internet.

Quizás pienses que esta es una afirmación demasiado atrevida. Pero considere que Google comenzó con un raspador web que Larry Page creó usando Java y Python. Los robots de Google han estado explorando Internet, intentando ofrecer a sus usuarios las mejores respuestas a sus preguntas. El web scraping tiene infinitos usos, e incluso si está interesado en algo más en ciencia de datos, necesitará algunas habilidades de scraping para obtener los datos que necesita analizar.

Encontré algunas de las técnicas utilizadas aquí en un maravilloso un libro sobre web scraping, que adquirí recientemente. Contiene muchos ejemplos sencillos e ideas para la aplicación práctica de lo aprendido. Además, hay un capítulo muy interesante sobre cómo evitar las comprobaciones de reCaptcha. Esto fue una novedad para mí, ya que ni siquiera sabía que existían herramientas especiales e incluso servicios completos para resolver este tipo de problemas.

¡¿Te gusta viajar?!

A la pregunta simple y bastante inofensiva planteada en el título de esta sección, a menudo se puede escuchar una respuesta positiva, acompañada de un par de historias de los viajes de la persona a quien se le hizo la pregunta. La mayoría de nosotros estaríamos de acuerdo en que viajar es una excelente manera de sumergirse en nuevos entornos culturales y ampliar nuestros horizontes. Sin embargo, si le preguntas a alguien si le gusta buscar billetes de avión, estoy seguro de que la respuesta no será tan positiva. De hecho, Python viene en nuestra ayuda aquí.

La primera tarea que debemos resolver en el camino hacia la creación de un sistema de búsqueda de información sobre billetes de avión será seleccionar una plataforma adecuada de la que tomaremos la información. Resolver este problema no fue fácil para mí, pero al final elegí el servicio de Kayak. Probé los servicios de Momondo, Skyscanner, Expedia y algunos otros, pero los mecanismos de protección de los robots en estos recursos eran impenetrables. Después de varios intentos, durante los cuales tuve que lidiar con semáforos, pasos de peatones y bicicletas, tratando de convencer a los sistemas de que era humano, decidí que Kayak era el más adecuado para mí, a pesar de que incluso si hay demasiadas páginas cargadas. en poco tiempo y también comienzan los controles. Logré que el bot enviara solicitudes al sitio en intervalos de 4 a 6 horas y todo funcionó bien. De vez en cuando, surgen dificultades al trabajar con Kayak, pero si comienzan a molestarlo con comprobaciones, entonces debe solucionarlos manualmente y luego iniciar el bot, o esperar unas horas y las comprobaciones deberían detenerse. Si es necesario, puedes adaptar fácilmente el código para otra plataforma y, si lo haces, puedes informarlo en los comentarios.

Si recién está comenzando con el web scraping y no sabe por qué algunos sitios web tienen problemas, entonces, antes de comenzar su primer proyecto en esta área, hágase un favor y haga una búsqueda en Google con las palabras "etiqueta del web scraping". . Sus experimentos pueden terminar antes de lo que cree si realiza web scraping de manera imprudente.

Primeros pasos

Aquí hay una descripción general de lo que sucederá en nuestro código de raspador web:

  • Importe las bibliotecas necesarias.
  • Abrir una pestaña de Google Chrome.
  • Llame a una función que inicia el bot, pasándole las ciudades y fechas que se utilizarán al buscar boletos.
  • Esta función toma los primeros resultados de búsqueda, los ordena por mejores y hace clic en un botón para cargar más resultados.
  • Otra función recopila datos de toda la página y devuelve un marco de datos.
  • Los dos pasos anteriores se realizan utilizando tipos de clasificación por precio del billete (barato) y por velocidad del vuelo (más rápido).
  • Al usuario del script se le envía un correo electrónico que contiene un resumen de los precios de los boletos (boletos más baratos y precio promedio), y se guarda como un archivo Excel un marco de datos con información ordenada por los tres indicadores mencionados anteriormente.
  • Todas las acciones anteriores se realizan en un ciclo después de un período de tiempo específico.

Cabe señalar que cada proyecto de Selenium comienza con un controlador web. yo suelo controlador de cromo, Trabajo con Google Chrome, pero hay otras opciones. PhantomJS y Firefox también son populares. Después de descargar el controlador, debe colocarlo en la carpeta correspondiente y esto completa la preparación para su uso. Las primeras líneas de nuestro script abren una nueva pestaña de Chrome.

Tenga en cuenta que en mi historia no intento abrir nuevos horizontes para encontrar grandes ofertas en boletos aéreos. Existen métodos mucho más avanzados para buscar este tipo de ofertas. Sólo quiero ofrecer a los lectores de este material una forma sencilla pero práctica de resolver este problema.

Aquí está el código del que hablamos 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)

Al comienzo del código puede ver los comandos de importación de paquetes que se utilizan en todo nuestro proyecto. Entonces, randint se utiliza para hacer que el robot "se quede dormido" durante una cantidad aleatoria de segundos antes de comenzar una nueva operación de búsqueda. Por lo general, ningún robot puede prescindir de esto. Si ejecuta el código anterior, se abrirá una ventana de Chrome, que el bot utilizará para trabajar con los sitios.

Hagamos un pequeño experimento y abramos el sitio web kayak.com en una ventana separada. Seleccionaremos la ciudad desde la que vamos a volar, y la ciudad a la que queremos llegar, así como las fechas de vuelo. Al elegir las fechas, asegúrese de utilizar el rango de +-3 días. Escribí el código teniendo en cuenta lo que produce el sitio en respuesta a dichas solicitudes. Si, por ejemplo, necesita buscar entradas solo para fechas específicas, existe una alta probabilidad de que tenga que modificar el código del bot. Cuando hablo del código, doy las explicaciones adecuadas, pero si te sientes confundido, házmelo saber.

Ahora haga clic en el botón de búsqueda y mire el enlace en la barra de direcciones. Debería ser similar al enlace que uso en el siguiente ejemplo donde se declara la variable. kayak, que almacena la URL y se utiliza el método get controlador web. Después de hacer clic en el botón de búsqueda, los resultados deberían aparecer en la página.

Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar
Cuando usé el comando get Más de dos o tres veces en unos pocos minutos, me pidieron que completara la verificación usando reCaptcha. Puede pasar esta verificación manualmente y continuar experimentando hasta que el sistema decida ejecutar una nueva verificación. Cuando probé el script, parecía que la primera sesión de búsqueda siempre transcurría sin problemas, por lo que si deseaba experimentar con el código, solo tenía que verificar periódicamente manualmente y dejar que el código se ejecutara, utilizando largos intervalos entre las sesiones de búsqueda. Y, si lo piensa bien, es poco probable que una persona necesite información sobre los precios de los billetes recibidos en intervalos de 10 minutos entre las operaciones de búsqueda.

Trabajar con una página usando XPath

Entonces, abrimos una ventana y cargamos el sitio. Para obtener precios y otra información, necesitamos utilizar tecnología XPath o selectores CSS. Decidí seguir con XPath y no sentí la necesidad de usar selectores de CSS, pero es muy posible trabajar de esa manera. Navegar por una página usando XPath puede ser complicado, e incluso si usas las técnicas que describí en este artículo, que implicaba copiar los identificadores correspondientes del código de la página, me di cuenta de que, de hecho, esta no es la forma óptima de acceder a los elementos necesarios. Por cierto, en este El libro proporciona una excelente descripción de los conceptos básicos del trabajo con páginas utilizando selectores XPath y CSS. Así es como se ve el método del controlador web correspondiente.

Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar
Entonces, sigamos trabajando en el bot. Utilicemos las capacidades del programa para seleccionar los boletos más baratos. En la siguiente imagen, el código del selector XPath está resaltado en rojo. Para ver el código, debe hacer clic derecho en el elemento de la página que le interesa y seleccionar el comando Inspeccionar en el menú que aparece. Este comando se puede llamar para diferentes elementos de la página, cuyo código se mostrará y resaltará en el visor de código.

Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar
Ver código de página

Para encontrar confirmación de mi razonamiento sobre las desventajas de copiar selectores del código, preste atención a las siguientes características.

Esto es lo que obtienes cuando copias el código:

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

Para copiar algo como esto, debe hacer clic derecho en la sección de código que le interesa y seleccionar el comando Copiar > Copiar XPath en el menú que aparece.

Esto es lo que usé para definir el botón Más barato:

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

Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar
Comando Copiar > Copiar XPath

Es bastante obvio que la segunda opción parece mucho más sencilla. Cuando se utiliza, busca un elemento a que tenga el atributo data-codeigual a price. Al utilizar la primera opción se busca el elemento id que es igual a wtKI-price_aTaby la ruta XPath al elemento se ve así /div[1]/div/div/div[1]/div/span/span. Una consulta XPath como esta a una página funcionará, pero sólo una vez. Puedo decir ahora mismo que id cambiará la próxima vez que se cargue la página. Secuencia de caracteres wtKI cambia dinámicamente cada vez que se carga la página, por lo que el código que lo utiliza será inútil después de la siguiente recarga de la página. Así que tómate un tiempo para comprender XPath. Este conocimiento le será de gran utilidad.

Sin embargo, cabe señalar que copiar selectores XPath puede resultar útil cuando se trabaja con sitios bastante simples y, si se siente cómodo con esto, no tiene nada de malo.

Ahora pensemos en qué hacer si necesita obtener todos los resultados de la búsqueda en varias líneas, dentro de una lista. Muy simple. Cada resultado está dentro de un objeto con una clase. resultWrapper. La carga de todos los resultados se puede realizar en un bucle similar al que se muestra a continuación.

Cabe señalar que si comprende lo anterior, comprenderá fácilmente la mayor parte del código que analizaremos. A medida que se ejecuta este código, accedemos a lo que necesitamos (de hecho, el elemento en el que está envuelto el resultado) utilizando algún tipo de mecanismo de especificación de ruta (XPath). Esto se hace para obtener el texto del elemento y colocarlo en un objeto desde el cual se puedan leer los datos (usado por primera vez flight_containers, entonces - flights_list).

Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar
Se muestran las tres primeras líneas y podemos ver claramente todo lo que necesitamos. Sin embargo, disponemos de formas más interesantes de obtener información. Necesitamos tomar datos de cada elemento por separado.

A trabajar!

La forma más sencilla de escribir una función es cargar resultados adicionales, así que ahí es donde comenzaremos. Me gustaría maximizar la cantidad de vuelos sobre los que el programa recibe información, sin levantar sospechas en el servicio que lleva a una inspección, por eso hago clic en el botón Cargar más resultados una vez cada vez que se muestra la página. En este código, debes prestar atención al bloque. try, que agregué porque a veces el botón no se carga correctamente. Si también encuentra esto, comente las llamadas a esta función en el código de 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

Ahora, después de un largo análisis de esta función (a veces puedo dejarme llevar), estamos listos para declarar una función que eliminará la página.

Ya he recopilado la mayor parte de lo que se necesita en la siguiente función llamada page_scrape. A veces, los datos de la ruta devuelta se combinan, por lo que utilizo un método simple para separarlos. Por ejemplo, cuando uso variables por primera vez section_a_list и section_b_list. Nuestra función devuelve un marco de datos. flights_df, esto nos permite separar los resultados obtenidos de diferentes métodos de clasificación de datos y posteriormente combinarlos.

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

Intenté nombrar las variables para que el código fuera comprensible. Recuerde que las variables que comienzan con a pertenecen a la primera etapa del camino, y b - al segundo. Pasemos a la siguiente función.

Mecanismos de apoyo

Ahora tenemos una función que nos permite cargar resultados de búsqueda adicionales y una función para procesar esos resultados. Este artículo podría haber terminado aquí, ya que estas dos funciones proporcionan todo lo que necesita para extraer páginas que puede abrir usted mismo. Pero todavía no hemos considerado algunos de los mecanismos auxiliares discutidos anteriormente. Por ejemplo, este es el código para enviar correos electrónicos y algunas cosas más. Todo esto se puede encontrar en la función. start_kayak, que ahora consideraremos.

Esta función requiere información sobre ciudades y fechas. Usando esta información, forma un enlace en una variable. kayak, que se utiliza para llevarlo a una página que contendrá resultados de búsqueda ordenados según su mejor coincidencia con la consulta. Después de la primera sesión de scraping, trabajaremos con los precios de la tabla en la parte superior de la página. Es decir, encontraremos el precio mínimo del billete y el precio medio. Todo esto, junto con la predicción emitida por el sitio, se enviará por correo electrónico. En la página, la tabla correspondiente debe estar en la esquina superior izquierda. Por cierto, trabajar con esta tabla puede provocar un error al buscar por fechas exactas, ya que en este caso la tabla no se muestra en la página.

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

Probé este script usando una cuenta de Outlook (hotmail.com). No lo he probado para que funcione correctamente con una cuenta de Gmail, este sistema de correo electrónico es bastante popular, pero hay muchas opciones posibles. Si usa una cuenta de Hotmail, para que todo funcione, solo necesita ingresar sus datos en el código.

Si desea comprender qué se hace exactamente en secciones específicas del código para esta función, puede copiarlas y experimentar con ellas. Experimentar con el código es la única manera de comprenderlo verdaderamente.

Sistema listo

Ahora que hemos hecho todo lo que hablamos, podemos crear un bucle simple que llame a nuestras funciones. El script solicita datos al usuario sobre ciudades y fechas. Al realizar pruebas con reinicio constante del script, es poco probable que desee ingresar estos datos manualmente cada vez, por lo que las líneas correspondientes, durante el momento de la prueba, se pueden comentar descomentando las que se encuentran debajo de ellas, en las que se muestran los datos que necesita el script. El 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.....')

Así es como se ve una ejecución de prueba del script.
Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar
Ejecución de prueba del script

resultados

Si has llegado hasta aquí, ¡enhorabuena! Ahora tienes un web scraper funcional, aunque ya puedo ver muchas formas de mejorarlo. Por ejemplo, se puede integrar con Twilio para que envíe mensajes de texto en lugar de correos electrónicos. Puedes usar una VPN u otra cosa para recibir resultados simultáneamente de varios servidores. También surge periódicamente el problema de comprobar si el usuario del sitio es una persona, pero este problema también se puede solucionar. En cualquier caso, ahora tienes una base que puedes ampliar si lo deseas. Por ejemplo, asegúrese de enviar un archivo de Excel al usuario como archivo adjunto a un correo electrónico.

Python: un asistente para encontrar billetes de avión económicos para los amantes de viajar

Solo los usuarios registrados pueden participar en la encuesta. Registrarsepor favor

¿Utiliza tecnologías de web scraping?

  • No

8 usuarios votaron. 1 usuario se abstuvo.

Fuente: habr.com

Añadir un comentario