No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

No se trata de lo que quieres comprar, sino de quién quieres ser. Aprovecha el precio especial.

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

15 Días
11 Hrs
7 Min
18 Seg

Scrapeando escalas y tarifas

15/30
Recursos

Aportes 80

Preguntas 9

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Todos los nombres de las clases y en parte la estructura del webpage ha cambiado, pero me parece que eso ha sido en cierto punto positivo porque te obliga a pensar y buscar nuevas soluciones, ya no hacemos el ejercicio al pie de la letra sino que nos toca investigar. Hay que verle el lado positivo a todo!

Hola profe la pagina se actualizó y ahora no están esas clases, ahora aparece así:

<div class="sc-hORach jTGprl">
	<span class="sc-iQKALj bbrNfR">
		<div class="sc-bwCtUz bFAUiy">
			<div class="sc-ibxdXY ewiNkH">
				<time datetime="18:00" aria-hidden="true" class="sc-kIPQKe buAkkh">18:00</time>
				<abbr aria-hidden="true" title="EZE" class="sc-RefOD gTgkxI">EZE</abbr>
				<span class="sr-only">Salida a las 18 horas 00 Minutos, de Ezeiza Intl.</span>
			</div>
		</div>
		<span class="sc-hrWEMg dzhwmm">Ezeiza Intl.</span>
	</span>
</div>

para poder acceder al nombre del aeropuerto es necesario utilizar lo siguiente:

segmento.find_element_by_xpath('//div[@class="sc-ibxdXY ewiNkH"]/abbr').get_attribute('title')

Me costo bastante llegar la query pero se los comparto para que puedan seguir avanzando

Voy a dejar mi aporte como comentarios a este comentario para no hacer span, ya que el codigo es demasiado largo y al dia de hoy el nombre de muchas clases cambiaron, espero que ayude a aquellos que esten trabados.

Les recomiendo leer la documentación:

https://selenium-python.readthedocs.io/

Además desde el inspector de código, si el dan click derecho en la clase o parte del código puden copiar el Xpath, identificador o selector CSS y pueden ser usados en selenuim.

Hay varios metodos que se pueden usar para encontrar los elementos, por el nombre , por la clase, por favor revisen al documentación.

Con selenium pueden hacer loggin en páginas

En el minuto 7:10 corregir la producción, sale 3,2,1 (en audio) explicación de ubicación de tarifas en el foot. Salu2.

Reto 1 (Extraer información de escalas):

for segmento in segmentos:
    # Flight data
    # departure as de and arrival as ar
    city = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')
    de_city = city[0].text
    ar_city = city[1].text
    schedule = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')
    de_schedule = schedule[0].get_attribute('datetime')
    ar_schedule = schedule[1].get_attribute('datetime')
    airport = segmento.find_elements_by_xpath('.//span[@class="sc-hXRMBi gVvErD"]')
    de_airport = airport[0].text
    ar_airport = airport[1].text

    # flight elements as fi
    fi_duration = segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')
    fi_number = segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text
    fi_airplane = segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]').text
    fi_airline = (segmento.find_element_by_xpath('.//span[@class="sc-kfGgVZ lccoDs"]').text).replace('Operado por ', '')

    # flight Scale as fs
    modal_window = vuelo.find_element_by_xpath('//div[@class="sc-hZSUBg gfeULV"]/div[@class="sc-cLQEGU dnKRNG"]')
    fs_duration = modal_window.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')

Close modal window:

close_modal = vuelo.find_element_by_xpath('//div[@class="modal-header sc-dnqmqq cGfTsx"]/button').click()
close_modal

Reto2 (precio de vuelos):

tarifas = vuelo.find_elements_by_xpath('.//div[@class="fares-table-container"]//tfoot//td[contains(@class, "fare-")]')
tarifa_light = tarifas[0]
tarifa_pluss = tarifas[1]
tarifa_top = tarifas[2]

# find price
currency = tarifa_light.find_element_by_xpath('.//span[@class="price"]/span[@class="currency-symbol"]').text
light_cost = tarifa_light.find_element_by_xpath('.//span[@class="price"]/span[@class="value"]').text
pluss_cost = tarifa_pluss.find_element_by_xpath('.//span[@class="price"]/span[@class="value"]').text
top_cost = tarifa_top.find_element_by_xpath('.//span[@class="price"]/span[@class="value"]').text

light_price = (f'{currency} {light_cost}')
pluss_price = (f'{currency} {pluss_cost}')
top_price = (f'{currency} {top_cost}')

Todos los segmentos del pop-up comparten EXACTAMENTE los mismos nombres, ¿Cómo podemos acceder a cada una de las horas y destinos? Yo solo puedo acceder al primero 😦

Tags actualizados:

segmento.find_element_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr[@class="sc-hrWEMg hlCkST"]').text
segmento.find_element_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time').get_attribute('datetime')

Hola, aquí está parte del primer reto:

Y el segundo reto:

Tuve que importar time porque en aeroméxico tarda un momento en cerrar y abrir el menú y si no esperas se rompe.

from selenium import webdriver
import time

driver = webdriver.Firefox()
URL = 'https://aeromexico.com/es-mx/reserva/opciones?itinerary=MEX_JFK_2020-06-26&leg=1&travelers=A1_C0_I0_PH0_PC0'

driver.get(URL)
flights = driver.find_elements_by_xpath('//table[@class="FlightOptionsGrid-table"]/tbody/tr')


for i, flight in enumerate(flights):
    departure_and_arrival = flight.find_elements_by_xpath('.//div[@class="FlightOptionsTimeline-time"]')
    departure = departure_and_arrival[0].text
    arrival = departure_and_arrival[1].text
    flight_duration = flight.find_element_by_xpath('.//p[@class="FlightOptionsFlightInfoSummary-summary"][1]/span[last()]')
    
    button_details = flight.find_element_by_xpath('.//button[@class="FlightOptionsFlightInfo-btnWrapper"]')
    button_details.click()
    time.sleep(1)
    segments = button_details.find_elements_by_xpath('//div[@class="FlightDetailsSegment"]')
    button_close = button_details.find_element_by_xpath('//button[contains(@class, "Modal-close")]')
    
    segments_with_downtime = segments[:-1]
    last_segment = segments[-1]
    
    print(f'Viaje {i+1}:') 
    for segment in segments_with_downtime:
        segment_departure_and_arrival_destinations = segment.find_elements_by_xpath('.//div[@class="FlightDetailsSegment-cityPair"]/div/div[@class="FlightDetailsSegment-flightCity"]')
        segment_departure_destination = segment_departure_and_arrival_destinations[0].get_attribute('textContent')
        segment_arrival_destination = segment_departure_and_arrival_destinations[1].get_attribute('textContent')
        
        segment_departure_and_arrival = segment.find_elements_by_xpath('.//div[@class="FlightDetailsSegment-cityPair"]/div/div[@class="FlightDetailsSegment-flightTime"]')
        segment_departure = segment_departure_and_arrival[0].get_attribute('textContent')
        segment_arrival = segment_departure_and_arrival[1].get_attribute('textContent')
        
        downtime = segment.find_element_by_xpath('.//div[@class="FlightDetailsSegment-layover"]/span/div/span')
        print(f'Lugar de partida: {segment_departure_destination}')
        print(f'Lugar de destino: {segment_arrival_destination}')
        print(f'Hora de salida: {segment_departure}')
        print(f'Hora de llegada: {segment_arrival}')
        print(f'--- --- ---{downtime.get_attribute("textContent")} --- --- ---')
        print()
        
    last_departure_both = last_segment.find_elements_by_xpath('.//div[@class="FlightDetailsSegment-cityPair"]/div/div[@class="FlightDetailsSegment-flightCity"]')
    last_departure = last_departure_both[0]
    last_destination = last_departure_both[1]
    print(f'Lugar de partida: {last_departure.text}')
    print(f'Lugar de destino: {last_destination.text}')
    print(f'Hora de salida: {departure}')
    print(f'Hora de llegada: {arrival}')
    print(f'El vuelo dura: {flight_duration.text}')
    print()
    print()
    button_close.click()
    time.sleep(1)

Va mi aporte válido para mayo 2022. Obtengo 3 tablas (vuelos, tarifas y segmentos) que luego puedo vincular en una base de datos con el id del vuelo, para hacer el análisis:

flights_data = []
tariffs_data = []
segments_data = []

flights = driver.find_elements(By.XPATH, '//ol[@aria-label="Vuelos disponibles."]//div[contains(@id, "WrapperCardFlight")]')
for idf, flight in enumerate(flights):
    
    # Get flights data
    print(f'Getting flight {idf} data...')
    departure_time = flight.find_element(By.XPATH, './/div[contains(@class, "flight-information")][1]/span').text
    flight_duration = flight.find_element(By.XPATH, './/div[contains(@class, "flight-duration")]/span[2]').text
    arrival_time_el = flight.find_element(By.XPATH, './/div[contains(@class, "flight-information")][2]/span')
    arrival_time_child = arrival_time_el.find_element(By.XPATH, './*').text
    arrival_time = arrival_time_el.text.replace(arrival_time_child, '').strip()

    flights_data.append({
        'flight_id': idf,
        'departure_time' : departure_time,
        'flight_duration' : flight_duration,
        'arrival_time' : arrival_time
        })
    print(f'Flight {idf} data appended\n')


    # Get tariffs:
    print(f'Flight {idf} - Getting tariffs...')
    flight.click()
    tariffs = flight.find_elements(By.XPATH, '//ol[@aria-label="Tarifas disponibles."]/li[contains(@id, "WrapperBundleCardbundle-detail")]')
    for idt, tariff in enumerate(tariffs):
        tariff_name = tariff.find_elements(By.XPATH, './/div[@aria-hidden="true"]//span')[0].text.replace('\n', '')
        tariff_price = tariff.find_element(By.XPATH, './/span[contains(@class, "displayAmount")]').text
        tariffs_data.append({
            'flight_id': idf,
            'tariff_id': idt,
            'tariff_name': tariff_name,
            'tariff_price' : tariff_price
        })
    print(f'Flight {idf} - Tariff {tariff_name} data appended\n')
    
    # Hide tariffs
    tariffs_close_btn = flight.find_element(By.XPATH, './/button[contains(@class, "MuiButtonBase-root")]')
    tariffs_close_btn.click()

    # Get segments:
    print(f'Getting segments...')
    segments_open_btn = flight.find_element(By.XPATH, './/a[contains(@id, "itinerary-modal")]')
    segments_open_btn.click()
    sleep(2)
    segments = flight.find_elements(By.XPATH, '//section[contains(@data-test, "section-info-leg")]')
    for ids, segment in enumerate(segments):
        print(f'Flight {idf} - Getting segment {ids} data...')
        flight_number = segment.find_element(By.XPATH, './/div[contains(@class, "airline-wrapper")]').text.replace('*', '')
        airplane_code = segment.find_element(By.XPATH, './/span[@class="airplane-code"]').text
        origin_airport = segment.find_element(By.XPATH, './/span[contains(@class, "pathInfo-origin")]/following-sibling::div[contains(@class, "iataCode")]/span[not(@class="time")]').text
        origin_time = segment.find_element(By.XPATH, './/span[contains(@class, "pathInfo-origin")]/following-sibling::div[contains(@class, "iataCode")]/span[@class="time"]').text
        segment_duration = segment.find_element(By.XPATH, './/span[contains(@class, "pathInfo-duration")]/following-sibling::span[@class="time"]').text
        destination_airport = segment.find_element(By.XPATH, './/span[contains(@class, "pathInfo-destination")]/following-sibling::div[contains(@class, "iataCode")]/span[not(@class="time")]').text
        destination_time = segment.find_element(By.XPATH, './/span[contains(@class, "pathInfo-destination")]/following-sibling::div[contains(@class, "iataCode")]/span[@class="time"]').text
        connections = segment.find_elements(By.XPATH, './following-sibling::section[contains(@data-test, "section-info-connection")]')
        if connections:
            connection_city = connections[0].find_element(By.XPATH, './/span[@class="connection-text"]').text.replace('Conexión ', '')
            connection_duration = connections[0].find_element(By.XPATH, './/span[@class="time"]').text
        else:
            connection_city = ''
            connection_duration = ''

        segments_data.append({
            'flight_id': idf,
            'segment_id' : ids,
            'flight_number' : flight_number,
            'airplane_code' : airplane_code,
            'origin_airport' : origin_airport,
            'origin_time' : origin_time,
            'segment_duration' : segment_duration,
            'destination_airport' : destination_airport,
            'destination_time' : destination_time,
            'connection_city' : connection_city,
            'connection_duration' : connection_duration
        })
        print(f'Flight {idf} - Segment {ids} data appended\n')

    # Hide segments
    segments_close_btn = driver.find_element(By.XPATH, '//div[contains(@class, "MuiDialog-container")]//button[contains(@class, "MuiButtonBase-root")]')
    segments_close_btn.click()
import pandas as pd

df_flights = pd.json_normalize(flights_data)
df_flights.to_csv('flights.csv', sep=';')

df_tariffs = pd.json_normalize(tariffs_data)
df_tariffs.to_csv('tariffs.csv', sep=';')

df_segments = pd.json_normalize(segments_data)
df_segments.to_csv('segments.csv', sep=';')

Fue dificil pero se puede jeje 😄 Por cierto cuando hay más de un elemento que hace match cuando realizas un querie con XPATH , este solo te traera el primer elemento.

  • Segmento 1:
a=segmento.find_elements_by_xpath('.//span[@class="sc-hXRMBi gVvErD"]')
a_1= a[0].text
a_2= a[1].text
print(a_1)
print(a_2)

# Obtener Hora de salida y la hora de llegada del primer y segundo aeropueto
tiempo = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')
ida = tiempo[0].get_attribute('datetime')
llegada = tiempo[1].get_attribute('datetime')
print(ida)
print(llegada)

# Tiempo estimado de vuelo
segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')

# Siglas del aeropuerto de llegada
siglas = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')
print(f'{siglas[1].get_attribute("title")} y {siglas[0].get_attribute("title")}')

#Modelo del avion
segmento.find_element_by_xpath('.//span[@class="sc-gzOgki uTyOl"]').text

Segmento intermedio:

#Segundo segmento: Trasbordo
segmento_1= segmentos[1]

#Tiempo de espera del trasbordo
segmento_1.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')

Tercer segmento:

#Tercer segmento: llegada.
segmento2= segmentos[2]

b = segmento2.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')
b1=b[0].get_attribute('title')
b2=b[1].get_attribute('title')
print(b1)
print(b2)

# Hora de llegada f
tiempo2 = segmento2.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')
ida1=tiempo2[0].get_attribute('datetime')
llegada2=tiempo2[1].get_attribute('datetime')
print(ida1)
print(llegada2)

#Aeropuertos
aero = segmento2.find_elements_by_xpath('.//span[@class="sc-hXRMBi gVvErD"]')
aero_1= aero[0].text
aero_2= aero[1].text
print(aero_1)
print(aero_2)

#Tiempo de viaje
segmento2.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')

reto, con este codigo no importa si son 1 o 2 escalas

segmentos= vuelo.find_element_by_xpath('//article[@class="itinerarystyle__Wrapper-sc__sc-1n97ky6-0 hfhDJj" ]')
F=segmentos.find_elements_by_xpath('.//section[@data-test="section-info-leg" ]')
S=segmentos.find_elements_by_xpath('.//section[@data-test="section-info-connection" ]')
F,S,len(F),len(S)
if len(F)==2 :
    v1=F[0]
    v2=F[1]
    e1=S
    print('1 escala ',v1,v2,e1)
else:
    v1=F[0]
    v2=F[1]
    v3=F[2]
    e1=S[0]
    e2=S[1]
    print("2 escalas",v1,v2,v3,e1,e2)

a_orig_v1= v1.find_element_by_xpath('.//div[@class="path-infostyle__Top-sc__sc-xj1cll-2 eZnnpl"]//span[@class="airport-name"]').text
t_orig_v1=v1.find_element_by_xpath('.//div[@class="path-infostyle__Top-sc__sc-xj1cll-2 eZnnpl"]//span[@class="time"]').text
d_v1=v1.find_element_by_xpath('.//div[@class="path-infostyle__Middle-sc__sc-xj1cll-3 ksaVIu"]//span[@class="time"]').text #flight 1 duration
a_esc_v1= v1.find_element_by_xpath('.//div[@class="path-infostyle__Bottom-sc__sc-xj1cll-4 jMpZeH"]//span[@class="airport-name"]').text #escale airport name
t_a_esc_v1= v1.find_element_by_xpath('.//div[@class="path-infostyle__Bottom-sc__sc-xj1cll-4 jMpZeH"]//span[@class="time"]').text #arrive time in escale airport
p_v1=v1.find_element_by_xpath('.//div[@class="plane-infostyle__Wrapper-sc__sc-7wc798-1 cUCTjf plane-info"]//span[@class="airplane-code"]').text#fligth plane
a_orig_v1,t_orig_v1,d_v1, a_esc_v1,t_a_esc_v1, p_v1

('Cancun',
 '12:25 a. m.',
 '5 h 10 min',
 'J Chavez Intl.',
 '5:35 a. m.',
 'Airbus A320')
#scale time (waiting) 
esc_time1=e1.find_element_by_xpath('.//div[@class="connection-infostyle__ConnectionInformation-sc__sc-1qity98-2 bOpeBi"]//span[@class="time"]').text
esc_time1
'4 h 10 min'

#fligth 2
a_orig_v2= v2.find_element_by_xpath('.//div[@class="path-infostyle__Top-sc__sc-xj1cll-2 eZnnpl"]//span[@class="airport-name"]').text
t_orig_v2=v2.find_element_by_xpath('.//div[@class="path-infostyle__Top-sc__sc-xj1cll-2 eZnnpl"]//span[@class="time"]').text
d_v2=v2.find_element_by_xpath('.//div[@class="path-infostyle__Middle-sc__sc-xj1cll-3 ksaVIu"]//span[@class="time"]').text #flight 1 duration
a_esc_v2= v2.find_element_by_xpath('.//div[@class="path-infostyle__Bottom-sc__sc-xj1cll-4 jMpZeH"]//span[@class="airport-name"]').text #escale airport name
t_a_esc_v2= v2.find_element_by_xpath('.//div[@class="path-infostyle__Bottom-sc__sc-xj1cll-4 jMpZeH"]//span[@class="time"]').text #arrive time in escale airport
p_v2=v2.find_element_by_xpath('.//div[@class="plane-infostyle__Wrapper-sc__sc-7wc798-1 cUCTjf plane-info"]//span[@class="airplane-code"]').text#fligth plane
a_orig_v2,t_orig_v2,d_v2, a_esc_v2,t_a_esc_v2, p_v2

('J Chavez Intl.',
 '9:45 a. m.',
 '3 h 30 min',
 'A. Merino Benitez Intl.',
 '3:15 p. m.',
 'Boeing B787-9')

#scale time 2
if len(F)==3 :
    esc_time2=e2.find_element_by_xpath('.//div[@class="connection-infostyle__ConnectionInformation-sc__sc-1qity98-2 bOpeBi"]//span[@class="time"]').text
    print(esc_time2)
2 h 21 min

#flight 3
if len(F)==3 :
    a_orig_v3= v3.find_element_by_xpath('.//div[@class="path-infostyle__Top-sc__sc-xj1cll-2 eZnnpl"]//span[@class="airport-name"]').text
    t_orig_v3=v3.find_element_by_xpath('.//div[@class="path-infostyle__Top-sc__sc-xj1cll-2 eZnnpl"]//span[@class="time"]').text
    d_v3=v3.find_element_by_xpath('.//div[@class="path-infostyle__Middle-sc__sc-xj1cll-3 ksaVIu"]//span[@class="time"]').text #flight 1 duration
    a_esc_v3= v3.find_element_by_xpath('.//div[@class="path-infostyle__Bottom-sc__sc-xj1cll-4 jMpZeH"]//span[@class="airport-name"]').text #escale airport name
    t_a_esc_v3= v3.find_element_by_xpath('.//div[@class="path-infostyle__Bottom-sc__sc-xj1cll-4 jMpZeH"]//span[@class="time"]').text #arrive time in escale airport
    p_v3=v3.find_element_by_xpath('.//div[@class="plane-infostyle__Wrapper-sc__sc-7wc798-1 cUCTjf plane-info"]//span[@class="airplane-code"]').text#fligth plane

    
    print( a_orig_v3,t_orig_v3,d_v3, a_esc_v3,t_a_esc_v3, p_v3)
A. Merino Benitez Intl. 5:36 p. m. 1 h 57 min Ezeiza Intl. 7:33 p. m. Airbus A320

Hoy, tres anhos despues de que se lanzara este curso la pagina de Latam cambio. Esta es mi solucion para obtener las distintas tarifas:

diferencias = vuelo_1.find_elements(by=By.XPATH, value=’.//div[@class=“differentialPricestyle__DescriptionContainer-sc__sc-1wmoeew-1 cNHngn”]//span[@class=“display-currencystyle__CurrencyAmount-sc__sc-19mlo29-2 fMjBKP”]’)

print(‘Tarifa base: ‘, diferencias[0].text +’\n’, ‘TarifaPlus: ‘, diferencias[0].text +"+" +diferencias[1].text+’\n’, ‘TarifaTop: ‘, diferencias[0].text+"+"+diferencias[2].text+’\n’, 'TarifaPremium: ',diferencias[0].text+"+"+diferencias[3].text)

Les comparto mi enfoque actualizado

for segmento in segmentos:
    #verifico si lo que tengo es una conexión
    try:
        conexion = segmento.find_element(By.XPATH,'.//section[@class="page-contentstyle-sc__sc-1p15pyh-0 flight-connectionstyle__Wrapper-sc__sc-1kwznnj-0 eDxtzn hKcJOb connectionInfo"]')
        conex = True
    except:
        conex = False
        
    if conex:
        print("CONEXION")
        print("\n")
        #tenemos una conexion
        elementos = conexion.find_element(By.XPATH,'.//div[@class="connection-infostyle__ConnectionInformation-sc__sc-1qity98-2 bOpeBi"]')
        nombre_conexion = elementos.find_element(By.XPATH,'.//div/span').text
        duracion = elementos.find_element(By.XPATH,'.//span[@class="time"]').text
                                          
        print(nombre_conexion+" - "+duracion)
        print("\n")
        
    else:
        print("TRAYECTO")
        print("\n")
        #tenemos un trayecto
        elementos = segmento.find_elements(By.XPATH,'.//div[@class="path-infostyle__InfoContainer-sc__sc-xj1cll-1 YPtZn"]/div')
        #Defino las variables
        datos_salida = []
        datos_llegada = []
        duracion = ""
        for i in range(len(elementos)):
            if i==1:
                #Duracion
                duracion = elementos[i].find_element(By.XPATH,'.//span[@class="time"]').text
            else: #Es certeza que es salida o llegada
                
                #ciudad salida y hora
                detalles = elementos[i].find_elements(By.XPATH,'.//div/span')
                ciudad_salida = detalles[0].text
                hora=detalles[1].text
                
                #Punto y nombre del aeropuerto
                informacion = elementos[i].find_elements(By.XPATH,'.//span')
                punto = informacion[0].text
                nombre_aeropuerto = informacion[1].text
                
                if punto=="Salida":
                    datos_salida = [ciudad_salida,hora,nombre_aeropuerto]
                elif punto=="Llegada":
                    datos_llegada = [ciudad_salida,hora,nombre_aeropuerto]
        
        #Datos del modelo del avion y numero de vuelo
        vuelo = segmento.find_element(By.XPATH,'.//div[@class="plane-infostyle__TopContainer-sc__sc-7wc798-3 ftrPQD"]')
        
        #Numero de vuelo
        numero_vuelo = vuelo.find_element(By.XPATH,'.//div[@class="plane-infostyle__AirlineWrapper-sc__sc-7wc798-0 cHGYdi airline-wrapper"]').text
        
        #Modelo del avion
        modelo_avion = vuelo.find_element(By.XPATH,'.//span').text
        
        
        #En este punto ya tengo todos los datos relacionados al trayecto y a los datos del avión, ahora vamos a imprimirlo
        print(numero_vuelo+" en "+modelo_avion+" Desde "+datos_salida[2]+", "+datos_salida[0]+" -- "+datos_salida[1]+" hasta "+datos_llegada[2]+", "+datos_llegada[0]+" -- "+datos_llegada[1]+" con duracion de "+duracion+" ")
        print("\n")

solución al segundo reto de la clase al día de hoy

nombre_tarifas= vuelo.find_elements(By.XPATH, 
'//ol[@aria-label ="Tarifas disponibles."]//span[@class= "columnBrandstyle__BrandName-sc__sc-1e0tr9m-4 eCbTSs"]')

tarifas = vuelo.find_elements(By.XPATH, 
'//ol[@aria-label ="Tarifas disponibles."]//span[@class= "display-currencystyle__CurrencyAmount-sc__sc-19mlo29-2 fMjBKP"]')
dic_tarifas={} 
categorias = []
precios=[]
for i,tarifa in enumerate(tarifas): 
    precio = int(tarifa.text[:-3].replace('.',''))   #formateamos la tarifa para que sea de tipo entero
    
    if i == 0:                                       #definimos la tarifa básica a la que se sumaran los inbrementos
        tarifa_basica = precio
        precios.append(tarifa_basica)
    if tarifa_basica != precio:
        precio_tarifa = tarifa_basica + precio
        precios.append(precio_tarifa)
for categoria in nombre_tarifas:
    categorias.append(categoria.text)

tarifas_dic = dict(zip(categorias, precios))

resultado un diccionario con la información solicitada

{'basic': 140570, 'light': 217920, 'plus': 265520, 'top': 283370}

mi solución al reto:

def info_escala(numero, segmento):
    dic_escala={}
    try:
        ae_salida, ae_llegada = segmento.find_elements(By.XPATH, 
    './/div[@class ="path-infostyle__InfoContainer-sc__sc-xj1cll-1 YPtZn"]//span[@class= "airport-name"]')
        hora_llegada= segmento.find_element(By.XPATH, 
                    './/div[@class = "path-infostyle__Bottom-sc__sc-xj1cll-4 jMpZeH"]//span[@class="time"]')
        duracion_vuelo = segmento.find_element(By.XPATH,
                './/div[@class = "path-infostyle__Middle-sc__sc-xj1cll-3 ksaVIu"]/span[@class = "time"]')
       
        
        dic_escala["Salida"]= ae_salida.text
        dic_escala['Destino']= ae_llegada.text
        dic_escala['Hora de llegada'] = hora_llegada.text
        dic_escala['Duración vuelo'] = duracion_vuelo.text
        try:
            duraciones_escalas = segmento.find_elements(By.XPATH,
                '//div[@class="connection-infostyle__ConnectionInformation-sc__sc-1qity98-2 bOpeBi"]/span')
            duracion_escala= duraciones_escalas[numero]
            dic_escala["duración de escala"] = duracion_escala.text
        except:
            print(numero)
            dic_escala["duración de escala"] = None
        num_vuelo =segmento.find_element(By.XPATH, 
                    './/div[@class= "plane-infostyle__AirlineWrapper-sc__sc-7wc798-0 cHGYdi airline-wrapper"]')
        dic_escala['numero vuelo']= num_vuelo.text
        modelo_avion = segmento.find_element(By.XPATH, 
                './/div[@class = "plane-infostyle__TopContainer-sc__sc-7wc798-3 ivuGVj"]//span[@class= "airplane-code"]')
        dic_escala['Modelo avión']= modelo_avion.text
        
        
        return(dic_escala)
        
    except:
        print("error obteniendo segmento")

def info_escalas (vuelo):
    dic_escalas= {}
    try:
        boton_escalas = vuelo.find_element(By.XPATH, 
'.//div[@class= "card-flightstyle__FooterCard-sc__sc-16r5pdw-22 fUfLuR"]/div/a/span' )
        boton_escalas.click()
        sleep(1)
        escalas = vuelo.find_elements(By.XPATH, '//article[@class = "itinerarystyle__Wrapper-sc__sc-1n97ky6-0 hfhDJj"]/div/section[@class = "itinerarystyle__Section-sc__sc-1n97ky6-1 ddwMLI"]')
        numero_escalas = len(escalas)
        
        
        segmentos= vuelo.find_elements(By.XPATH, 
            '//article[@class = "itinerarystyle__Wrapper-sc__sc-1n97ky6-0 hfhDJj"]/div/section[@class = "itinerarystyle__Section-sc__sc-1n97ky6-1 ddwMQK"]')
        for i, segmento in enumerate(segmentos):
            dic_escalas[f'Escala {i+1}'] = info_escala(i,segmento)
        sleep(1)
        boton_cerrar = vuelo.find_element(By.XPATH,
                    '//span[@class= "MuiButton-label"]/i[@class= "sc-fnykZs dXtIeu"]')
        boton_cerrar.click()
        return(dic_escalas)
    except:
        print('Error obteniendo escalas')

Resultado:

{'Escala 1': {'Salida': 'Jose Maria Cordova', 'Destino': 'J Chavez Intl.', 'Hora de llegada': '9:25 p. m.', 'Duración vuelo': '3 h', 'duración de escala': '2 h 55 min', 'numero vuelo': 'LA2393', 'Modelo avión': 'Airbus A320'}, 'Escala 2': {'Salida': 'J Chavez Intl.', 'Destino': 'Benito Juarez Intl.', 'Hora de llegada': '5:25 a. m.', 'Duración vuelo': '6 h 5 min', 'duración de escala': '3 h 5 min', 'numero vuelo': 'LA2486', 'Modelo avión': 'Boeing B767-300'}, 'Escala 3': {'Salida': 'Benito Juarez Intl.', 'Destino': 'Aguascalientes', 'Hora de llegada': '9:53 a. m.', 'Duración vuelo': '1 h 23 min', 'duración de escala': None, 'numero vuelo': 'LA7521', 'Modelo avión': 'Embraer E190'}}

este es mi reto

list(map(
    lambda x:x.find_element(By.XPATH,'.//span[@class="display-currencystyle__TextAmount-sc__sc-19mlo29-3 fhURPH displayAmount" and contains(@aria-label,"Precio")]').get_attribute('aria-label'),
    tarifas
))

lo interesante es que hay un atributo que tiene escrito en texto plano toda la info que se pedia

out:

['Precio de la tarifa LIGHT 9067780 Pesos colombianos por pasajero',
 'Precio de la tarifa PLUS 9067780 Pesos colombianos más 940744 Pesos colombianos adicionales por pasajero',
 'Precio de la tarifa TOP 9067780 Pesos colombianos más 1485374 Pesos colombianos adicionales por pasajero',
 'Precio de la tarifa PLUS 9067780 Pesos colombianos más -2029902 Pesos colombianos adicionales por pasajero']

Mi solucion actualizada al dia de hoy para el reto 😄

vuelos = driver.find_elements(by=By.XPATH, value='//li[@class="sc-fQfKYo hqsges"]')
vuelo = vuelos[0]
segmentos = vuelo.find_elements(by=By.XPATH, value='//section[@class="sc-fZFPbK dYZPay"]')
scales = vuelo.find_elements(by=By.XPATH, value='//section[@class="sc-fZFPbK hQaHnY"]')
n = 0
segments_info = []

for segmento in segmentos: 
    arrive_hour = segmento.find_elements(by=By.XPATH, value='.//div[@class="iataCode"]/span[@class="time"]')[-1].text
    flight_duration = segmento.find_element(by=By.XPATH, value='.//div[@class="sc-byuwlG flXYkA"]/span[@class="time"]').text
    flight_number = segmento.find_element(by=By.XPATH, value='.//div[@class="sc-cCzqYu duzMGK airline-wrapper"]').text
    plain_model = segmento.find_element(by=By.XPATH, value='.//div[@class="sc-bveJEc bpOmrh"]/span[@class="airplane-code"]').text
    if segmento != segmentos[-1]:
        scale = scales[n]
        scale_destiny = scale.find_element(by=By.XPATH, value='.//div[@class="sc-fVSCDV dRtGEn"]//span[@class="connection-text"]').text
        scale_duration = scale.find_element(by=By.XPATH, value='.//div[@class="sc-fVSCDV dRtGEn"]/span[@class="time"]').text
    else:
        scale_destiny = None
        scale_duration = None
        
    segment_info = {
        'arrive_hour': arrive_hour,
        'flight_duration': flight_duration,
        'flight_number': flight_number,
        'plain_model': plain_model,
        'scale_destiny': scale_destiny,
        'scale_duration': scale_duration
    }
    
    segments_info.append(segment_info)
    n+= 1

Anotaciones y Ejercicios Curso de Web Scraping - Modulo I
Desafíos resuelto y mas, te dejo esta y todas las anotaciones del curso actualizados al 2023, tome nota de los comentarios y ejercicios resueltos de cada sección. Lleve en cuenta las explicaciones del docente! Espero les sirva. 👌
(si quieres apoyar deja una estrella a la repo ✌⭐)

Para la obtención de las tarifas por separado:

val_tarifas = [tarifa.find_element(by = By.XPATH, value = ‘.//div[@class = “sc-cLmFfZ cBdkUC”]//span[@class = “sc-ihiiSJ AoaXI”]’).text for tarifa in tarifas]
val_tarifas

Reto (16 Nov 2022)

import requests
from bs4 import BeautifulSoup

url = 'https://www.latamairlines.com/us/es/ofertas-vuelos?origin=BUE&inbound=null&outbound=2022-11-30T16%3A00%3A00.000Z&destination=MAD&adt=1&chd=0&inf=0&trip=OW&cabin=Economy&redemption=false&sort=RECOMMENDED'

soup = BeautifulSoup(req.text, 'lxml')

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from time import sleep

options = webdriver.ChromeOptions()
options.add_argument('--incognito')
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
driver.maximize_window()
driver.implicitly_wait(20)
driver.get(url)

def close_dialog():
    dialogs = driver.find_elements(By.XPATH, '//div[contains(@class,"MuiDialog-container")]')
    if len(dialogs):
        dialogs[0].find_element(By.XPATH, './/button[contains(@class,"Dialog__CloseButton")]').click()

close_dialog()

vuelos = driver.find_elements(By.XPATH, '//div[@id="WrapperBodyFlights"]/ol/li')
# Mostrando el ultimo vuelo ya que tiene 3 escalas
vuelo = vuelos[-1]

print('- Escalas -\n')

salida = vuelo.find_element(By.XPATH, './/div[contains(@class,"flight-information")][1]/span[1]').text
duracion = vuelo.find_element(By.XPATH, './/div[contains(@class,"flight-duration")]/span[2]').text
llegada = vuelo.find_element(By.XPATH, './/div[contains(@class,"flight-information")][2]/span[1]').text
print('Salida  :', salida)
print('Duración:', duracion)
print('Llegada :', llegada.split('\n')[0])
footer_card = vuelo.find_element(By.XPATH, './/div[contains(@id, "ContainerFooterCard")]')
btn_escalas = footer_card.find_element(By.PARTIAL_LINK_TEXT, 'parada')
btn_escalas.click()
sleep(2)
sections_container = driver.find_element(By.XPATH, '//div[contains(@class,"MuiDialogContent-root")]/article')
sections = sections_container.find_elements(By.XPATH, './div/section')
escalas = sections_container.find_elements(By.XPATH, './div/section[@data-test="section-info-leg"]')
print('Escalas :', len(escalas)-1)
print('\n- Itinerario de vuelo -')

for i, escala in enumerate(sections):
    if escala.get_attribute('data-test') != 'section-info-leg':
        conn_duration = escala.find_element(By.XPATH, './/span[@class="time"]').text
        print(f'\nDemora  : {conn_duration}')
        continue
    airport_names = escala.find_elements(By.XPATH, './/span[@class="ariport-name"]')
    departure_times = escala.find_elements(By.XPATH, './/div[@class="iataCode"]//span[@class="time"]')
    duration = escala.find_element(By.XPATH, './/span[@class="pathInfo-duration"]/following-sibling::span[@class="time"]').text
    plane_info = flight_number = escala.find_element(By.XPATH, './/div[contains(@class,"plane-info")]')
    flight_number = plane_info.find_element(By.XPATH, './/div[@class="incoming-outcoming-title"]//div[contains(@class,"airline-wrapper")]').text
    airplane_code = plane_info.find_element(By.XPATH, './/span[@class="airplane-code"]').text
    print(f'\nVuelo   : {flight_number}')
    print(f'Avión   : {airplane_code}')    
    print(f'Salida  :' if i ==0 else f'Escala {int(i/2)}:', f'{airport_names[0].text} | {departure_times[0].text}')
    print(f'Duración: {duration}')
    print(f'Llegada : {airport_names[1].text} | {departure_times[1].text}')

close_dialog()

vuelo.click()
print('- Tarifas -\n')

tarifas = vuelo.find_elements(By.XPATH, './/ol/li//span[contains(@class,"displayAmount")]')
tarifa_light = tarifas[0].text
tarifa_plus = tarifas[1].text
tarifa_top = tarifas[2].text
print('Light:', tarifa_light.replace('\n', ' '))
print('Plus :', tarifa_plus.replace('\n', ' '))
print('Top  :', tarifa_top.replace('\n', ' '))

Obtener los precios de cada plan en una list comprehension.

Se puede aplicar otro for para eliminar los saltos “\n” con repalce()

# almacenar los planes
planes = driver.find_elements_by_xpath('//li[@class="sc-bEeSwp jaaNgz"]')
# extraer cada precio
precio = [ plan.find_element_by_xpath('.//span[@class="sc-bvCTgw fnzFob displayAmount"]').text for plan in planes
]
# imprimir la lista de precios
print(precio)

Una forma fácil de visualizar qué es lo que estamos extrayendo en el mismo notebook es:

from IPython.display import HTML, display_html
display_html(HTML(segment.get_attribute('innerHTML')))

donde segment es un objeto de clase
selenium.webdriver, dependera de que clase de driver utilicen.

El output no es el más estético de todos pero nos puede servir para entender qué estamos extrayendo.

Mi función retorna tarifas:

def get_prices(list_vuelos, num_vuelo):
    vuelo = list_vuelos[num_vuelo-1]
    vuelo.find_elements(By.XPATH, './/div [@role="button"]')[0].click()
    #Busca dentro de los tags de mi vuelo todos los tags span que contengan en su clase la palabra clave "sc-jSsgRB" 
    tarifas_vuelo = vuelo.find_elements(By.XPATH, './/span [contains(@class,"sc-jSsgRB")]')
    tarifas_vuelo = [tarifas_vuelo[i].text for i in range(len(tarifas_vuelo))]
    return tarifas_vuelo

No sirve cuando llega a la parte de hacer click me da este mensaje ElementNotInteractableException: Message: element not interactable (que el elemento no es interactivo)
y probe con otro boton en la pagina y me dice que en ese punto el boton no se puede clickear en ese punto: **ElementClickInterceptedException: Message: element click intercepted: Element <a id=“itinerary-modal-0-dialog-open” data-testid=“itinerary-modal-0-dialog-open-link” target="_self" rel=“noopener noreferrer” href="#flight-0-itinerary-detail" data-reference=“modal-air-offers” class=“sc-fMiknA haupI” aria-label=“Conocer el detalle completo del itinerario de vuelo. “>…</a> is not clickable at point (57, 483). Other element would receive the click: <div class=“MuiDialog-container MuiDialog-scrollPaper” role=“presentation” type=“center” tabindex=”-1” style=“opacity: 1; transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;”>…</div> **

Reto solucionado:

def obtener_tax_por_vuelo(vuelo):
    
    try:
        tax_vuelo_close_button = vuelo.find_element_by_xpath('//div[@role="dialog"]/button')
        tax_vuelo_close_button.click()
    except:
        pass
    
    time.sleep(0.05)
    
    # Se expande la ventana con las tarifas
    tax_vuelo_open_button = vuelo.find_element_by_xpath('.//div[@role="button"]')
    tax_vuelo_open_button.click()
    
    time.sleep(0.5)
    
    # Extraer los tipos de tarifas
    tipos_tax = vuelo.find_elements_by_xpath('//ul[contains(@class, "iqUDOc")]/li')
    
    # Extraer la moneda y cantidad de la tarifa
    taxes = ([tipo_tax.find_element_by_xpath('.//span[contains(@class, "gHfEat")]').text 
                for tipo_tax in tipos_tax])
    
    prices = ([tipo_tax.find_element_by_xpath('.//span[contains(@class, "displayAmount")]').get_attribute('aria-label')
              for tipo_tax in tipos_tax])
    
    time.sleep(0.05)
    
    # Se cierra el cuadro de dialogo 
    tax_vuelo_close_button = vuelo.find_element_by_xpath('//div[@role="dialog"]/button')
    tax_vuelo_close_button.click()
        
    return zip(taxes, prices)

Reto

def itinerario_vuelo(vuelo):
    
    ret_dict = dict()    
    try:
        # Se cierra la ventana emergente
        boton_escalas_close = vuelo.find_element_by_xpath('//div[@role="dialog"]/button')
        boton_escalas_close.click()
    except:
        pass

    time.sleep(0.05)
    
    # Se da click sobre el enlace de escalas
    boton_escalas = vuelo.find_element_by_xpath('.//div[contains(@class,"eMunVf")]/a')
    boton_escalas.click()
    
    time.sleep(0.5)
    
    # Aqui esta lo bueno del codigo:
    
    secciones = vuelo.find_elements_by_xpath('//section[@data-test="section-info-leg"]')
    
    # Extrayendo las referencias de las escalas
    refs = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//div[contains(@class, "airline-wrapper")]'))
                ))
    ret_dict['refs'] = refs
    
    # Extrayendo las referencias de los aviones
    avion_tipo = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//span[@class="airplane-code"]'))
                ))
    ret_dict['avion_codigo'] = avion_tipo
    
    # Extrayendo las horas de las salidas
    h_salida = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//div[contains(@class, "lgsqwh")]/div[@class="iataCode"]/span[@class="time"]'))
                ))
    ret_dict['horas_salida'] = h_salida
    
    # Extrayendo las horas de las llegadas
    h_llegada = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//div[contains(@class, "cfJviT")]/div[@class="iataCode"]/span[@class="time"]'))
                ))
    ret_dict['horas_llegada'] = h_llegada
    
    # Extrayendo los lugares de origen
    origenes = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//div[contains(@class, "lgsqwh")]/div[@class="iataCode"]/span[not(@class)]'))
                ))
    ret_dict['lugares_origen'] = origenes
    
    # Extrayendo los lugares de destino
    destino = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//div[contains(@class, "cfJviT")]/div[@class="iataCode"]/span[not(@class)]'))
                ))
    ret_dict['lugares_destino'] = destino
    
    # Extrayendo la duracion de cada escala
    duracion_escala = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//div[contains(@class, "hdcwMr")]/span[@class="time"]'))
                ))
    ret_dict['duracion_escala'] = duracion_escala
    
    # Extrayendo los aeropuertos de origen
    aeropuertos_origen = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//div[contains(@class, "lgsqwh")]/span[@class="ariport-name"]'))
                ))
    ret_dict['aeropuertos_origen'] = aeropuertos_origen
    
    # Extrayendo los aeropuertos de destino
    aeropuertos_destino = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//div[contains(@class, "cfJviT")]/span[@class="ariport-name"]'))
                ))
    ret_dict['aeropuertos_destino'] = aeropuertos_destino
    
    # Extrayendo los tiempos de cambio de avion
    cambios_avion = (list(
                map(lambda x: x.text, secciones[0].find_elements_by_xpath('//div[contains(@class, "gGkiSV")]/span[@class="time"]'))
                ))
    ret_dict['cambios_avion'] = '0 min' if len(cambios_avion) == 0 else cambios_avion
    
    # Se cierra la ventana emergente
    boton_escalas_close = vuelo.find_element_by_xpath('//div[@role="dialog"]/button')
    boton_escalas_close.click()
    
    time.sleep(0.05)
    
    return ret_dict

Solución del reto a Julio de 2021

# obtener todas las escalas
stops = driver.find_elements_by_xpath('//section[@class="sc-jWxkHr fPpyxb"]')

# iterar sobre las escalas y extraer la información
for s, stop in enumerate(stops):
    dep = stop.find_element_by_xpath('.//div[@class="sc-geAPOV biWURZ"]')
    dep_city = dep.find_element_by_xpath('.//div[@class="iataCode"]//span').text
    dep_time = dep.find_element_by_xpath('.//div[@class="iataCode"]//span[@class="time"]').text
    dep_aport =  dep.find_element_by_xpath('.//span[@class="ariport-name"]').text
    
    flight_time = stop.find_element_by_xpath('.//div[@class="sc-bJTOcE iJlaOT"]//span[@class="time"]').text
    airplane = stop.find_element_by_xpath('.//span[@class="airplane-code"]').text
    
    arr = stop.find_element_by_xpath('.//div[@class="sc-PLyBE iVAtbp"]')
    arr_city = arr.find_element_by_xpath('.//div[@class="iataCode"]//span').text
    arr_time = arr.find_element_by_xpath('.//div[@class="iataCode"]//span[@class="time"]').text
    arr_aport =  arr.find_element_by_xpath('.//span[@class="ariport-name"]').text
    

imprimiendo se obtiene algo como:
Stop 1
Airplane: Airbus A321
Departure: BOG(El Dorado Intl.) 13:00
Flight time: 6 h 10 min
Arrival: GRU(Guarulhos Intl.) 21:10
Stop 2
Airplane: Boeing B787-9
Departure: GRU(Guarulhos Intl.) 23:10
Flight time: 9 h 45 min
Arrival: MAD(Barajas Intl.) 13:55

Para los que no les funcione el cerrar el boton de las escalas, capaz que les sucede como a mi que les aparece una ventana con promociones.

Me aparecía el siguiente error: Message: element click intercepted: Element <button class=“close” aria-label="">…</button> is not clickable at point (807, 62). Other element would receive the click: <div id=“onesignal-slidedown-container” class=“onesignal-slidedown-container onesignal-reset slide-down”>…</div>

Deben cerrar primero esta ventana, y luego si pueden cerrar el boton de las escalas

button_promocion = driver.find_element_by_xpath('//div[@class="slidedown-footer"]//button[@class="align-right secondary slidedown-button"]').click()

button_close = driver.find_element_by_xpath('//button[@class="close"]').click()

Al día de hoy la tarifa y su moneda se encuentran en una misma etiqueta span:

# Para obtener las tarifas del vuelo
tarifas = vuelo.find_elements_by_xpath('.//ol[@class="sc-clWJBl jMzfXj"]//span[contains(@class, "sc-ileJJU bxvQhO displayAmount")]')
tarifas

Mi aporte al 11/05/2021 :

segmentos = vuelo.find_elements_by_xpath('//div[@class="sc-hZSUBg gfeULV"]/div[@class="sc-cLQEGU hyoued"]')

segmento = segmentos[0]

for i, segmento in enumerate(segmentos):
    print(f'{i}) Salida:' , segmento.find_element_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr[@class="sc-hrWEMg hlCkST"]').text,
         '/Hora_salida:', segmento.find_element_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time[@class="sc-RefOD libzvk"]').get_attribute('datetime'),
         '/Duración:',segmento.find_element_by_xpath('.//div[@class="sc-eXEjpC fqUnRK"]/span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime'),
         '/Destino:',segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr[@class="sc-hrWEMg hlCkST"]')[1].text,
         '/Hora_llegada:',segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time[@class="sc-RefOD libzvk"]')[1].get_attribute('datetime'),
         '/Avión:',segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]').text,
         '/N° Vuelo:',segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text)

Me gusta que haya cambiado la estructura de la pagina de LATAM, creo que me motiva a hacer los ejercicios y así entiendo mejor!

for p in rate:
    name = p.find_element_by_xpath('..//div[@class="type"]').text
    price = p.find_element_by_xpath('.//div[@class="price bold"]').text
    if name.find('check')==0:
        name = name.replace('check\nAdded','')
    else:
        name = name.replace('Select','')
    
    dict_rate = {name: price}
    print(dict_rate)

interesante

Reto 2

i=int(input('Selecciona que tipo de tarifa quiere obtener: 0 para Basic, 1 para Ligth, 2 para Plus, 3 para Top'))
currency=tarifas[i].find_element_by_xpath('.//span[@class="currency-symbol"]').text
value=tarifas[i].find_element_by_xpath('.//span[@class="price"]//span[@class="value"]').text
print(f'El valor para la tarifa seleccionada es: {currency} {value}')```

Reto 1 de la clase

#Tomo el codigo fuente del primer trayecto, y hago una lista de las clases, esta lista tiene 4 elementos
first_traject=segmento.find_elements_by_xpath('//div[@class="sc-bwCtUz iybVbT"]')
#Comienzo a tener los datos de los recorridos

#Recorrido 1
departure_a=first_traject[0].find_element_by_xpath('.//time[@class="sc-RefOD libzvk"]').get_attribute('datetime')
point_a=first_traject[0].find_element_by_xpath('.//abbr[@class="sc-hrWEMg hlCkST"]').get_attribute('title')
arrival_a=first_traject[1].find_element_by_xpath('.//time[@class="sc-RefOD libzvk"]').get_attribute('datetime')
point_b=first_traject[1].find_element_by_xpath('.//abbr[@class="sc-hrWEMg hlCkST"]').get_attribute('title')

#Recorrido 2
departure_b=first_traject[2].find_element_by_xpath('.//time[@class="sc-RefOD libzvk"]').get_attribute('datetime')
point_b=first_traject[2].find_element_by_xpath('.//abbr[@class="sc-hrWEMg hlCkST"]').get_attribute('title')
arrival_b=first_traject[3].find_element_by_xpath('.//time[@class="sc-RefOD libzvk"]').get_attribute('datetime')
point_c=first_traject[3].find_element_by_xpath('.//abbr[@class="sc-hrWEMg hlCkST"]').get_attribute('title')

#Tiempos de vuelo y conexion
time=segmento.find_elements_by_xpath('//div[@class="sc-eXEjpC fqUnRK"]')
travel_time_a=time[0].text
conexion_time=time[1].text
travel_time_b=time[2].text

#Detalles de vuelo
details=segmento.find_elements_by_xpath('//div[@class="airline-flight-details"]')
flight_details_a=details[0].text
details=segmento.find_elements_by_xpath('//div[@class="airline-flight-details"]')
flight_details_b=details[1].text

#Quien Opera el vuelo
operator=segmento.find_elements_by_xpath('//span[@class="sc-kfGgVZ lccoDs"]')
operator_a=operator[0].text
operator_b=operator[1].text

print(f'Salida a las: {departure_a} desde: {point_a}\n llegando a las :{arrival_a} a: {point_b}\n timepo de vuelo: {travel_time_a}\n Detalles del vuelo: {flight_details_a}, {operator_a}')
print(f'Tiempo de conexion {conexion_time}')
print(f'Salida a las: {departure_b} desde: {point_b}\n llegando a las :{arrival_b} a: {point_c}\n timepo de vuelo: {travel_time_b}\n Detalles del vuelo: {flight_details_b}, {operator_b}')
# Vamos a ver el origen de cada escala
# Reto! El destino de cada escala, la hora de llegada de cada escala, la duracion de cada vuelo, la duracion de la escala, el numero de vuelo, y el modelo del avion.

for segmento in segmentos:

    city = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')
    de_city = city[0].text
    ar_city = city[1].text

    schedule = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')
    de_schedule = schedule[0].get_attribute('datetime')
    ar_schedule = schedule[1].get_attribute('datetime')

    duration = segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')

    flight_no = segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text
    airplane = segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]').text

    print(de_city, de_schedule, ar_city, ar_schedule, f'Duracion del vuelo {duration}', flight_no, airplane)

duration_scale = vuelo.find_element_by_xpath('//div[@class="sc-cLQEGU dnKRNG"]//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')
print(f'Con escala de {duration_scale}')
# Informacion de las tarifas
# Lo primero es cerrar la ventana a la que se le habia dado click
driver.find_element_by_xpath('//div[@class="modal-header sc-dnqmqq cGfTsx"]/button').click()
# Ahora hay que click sobre el vuelo
vuelo.find_element_by_xpath('.//div[@class="flight-container"]/button').click()
# Encontrar la moneda y el valor del vuelo

fare_type = vuelo.find_elements_by_xpath('.//table[@class="fare-options-table"]//thead//th[contains(@class, "fare")]//span')
currency = vuelo.find_elements_by_xpath('.//table[@class="fare-options-table"]//tfoot//td[contains(@class, "fare")]//span[@class="currency-symbol"]')
tarifas = vuelo.find_elements_by_xpath('.//table[@class="fare-options-table"]//tfoot//td[contains(@class, "fare")]//span[@class="value"]')

for i in range(len(tarifas)):
    print(fare_type[i].text, currency[i].text, tarifas[i].text)

Solución al reto2, código y Output (Solo era necesario recorrer la lista e imprimirla ya que los valores los entregaba con el Símbolo de la divisa y el valor):

Como puedo escribir en un input que se encuentra dentro de un iframe que se crea al abrir el modal utilizando selenium web driver en ? , Como scrapear el iframe ?,

Mi solución del segundo reto 😄

for i, tarifa in enumerate(tarifas):
    span_price = tarifa.find_element_by_xpath('.//span[@class="price"]')
    currency_symbol = span_price.find_element_by_xpath('./span[@class="currency-symbol"]').text
    value = span_price.find_element_by_xpath('./span[@class="value"]').text
    print("Símbolo Tarifa {}: {}".format(i+1, currency_symbol))
    print('Valor Tarifa {}: {}'.format(i+1, value))
    print('_______________________________')

Solución primer reto:

departure_name = segmento.find_element_by_xpath('.//div[@class="departure"]//span[@class="ground-point-name"]').text
departure_name

departure_time = segmento.find_element_by_xpath('.//div[@class="departure"]//time').get_attribute('datetime')
departure_time

arrival_name = segmento.find_element_by_xpath('.//div[@class="arrival"]//span[@class="ground-point-name"]').text
arrival_name

arrival_time = segmento.find_element_by_xpath('.//div[@class="arrival"]//time').get_attribute('datetime')
arrival_time

flight_duration = segmento.find_element_by_xpath('.//div[@class="flight-schedule"]//span[@class="duration flight-schedule-duration"]/time').get_attribute('datetime')
flight_duration

flight_duration = segmento.find_element_by_xpath('.//div[@class="flight-schedule"]//span[@class="duration flight-schedule-duration"]/time').get_attribute('datetime')
flight_duration

airplane = segmento.find_element_by_xpath('.//span[@class="equipment-airline-material"]').text
airplane

scale_duration = segmento.find_element_by_xpath('.//span[@class="duration"]/time').get_attribute('datetime')
scale_duration

Resolución del reto de la clase:

# Hora de llegada de cada escala
checkin_1 = segments[0].find_element_by_xpath('.//div[@class="arrival"]//time').get_attribute('datetime')
checkin_2 = segments[1].find_element_by_xpath('.//div[@class="arrival"]//time').get_attribute('datetime')

print('Check In 1:', checkin_1)
print('Check In 2:', checkin_2)

# Destino de cada escala
destination_1 = segments[0].find_element_by_xpath('.//div[@class="arrival"]//span[@class="ground-point-name"]//abbr').get_attribute('title')
destination_2 = segments[1].find_element_by_xpath('.//div[@class="arrival"]//span[@class="ground-point-name"]//abbr').get_attribute('title')

print('Destination 1:', destination_1)
print('Destination 2:', destination_2)

# Duración de cada vuelo
duration_1 = segments[0].find_element_by_xpath('.//span[@class="duration flight-schedule-duration"]//time').get_attribute('datetime')
duration_2 = segments[1].find_element_by_xpath('.//span[@class="duration flight-schedule-duration"]//time').get_attribute('datetime')

print('Duration 1:', duration_1)
print('Duration 2:', duration_2)

# Demora de cada escala
delay = segments[0].find_element_by_xpath('.//p[@class="stop-wait-time"]//time').get_attribute('datetime')

print('Delay 1:', delay)

# Número de cada vuelo
number_1 = segments[0].find_element_by_xpath('.//span[@class="equipment-airline-number"]').text
number_2 = segments[1].find_element_by_xpath('.//span[@class="equipment-airline-number"]').text

print('Number 1:', number_1)
print('Number 2:', number_2)

# Modelo de cada vuelo
model_1 = segments[0].find_element_by_xpath('.//span[@class="equipment-airline-material"]').text
model_2 = segments[1].find_element_by_xpath('.//span[@class="equipment-airline-material"]').text

print('Model 1:', model_1)
print('Model 2:', model_2)

Resolución del segundo reto de la clase (precios):

tarifas = vuelo.find_elements_by_xpath('.//ul[@class="selection-tabs-fare-list"]//span[@class="price"]')

tarifas_price = [
    tarifa.find_element_by_xpath('./span[@class="currency-symbol"]').text + tarifa.find_element_by_xpath('./span[@class="value"]').text
    for tarifa in tarifas
]

print(tarifas_price)
#Out: ['US$1154,00', 'US$1207,50', 'US$1457,84']

Primer reto

for i, seg in enumerate(segmentos[0:-1]):
    print('Destino de escala', i+1,': ', seg.find_element_by_xpath('.//div[@class="arrival"]/span[@class="ground-point-name"]').text)
    print('Hora de llegada de escala', i+1,': ', seg.find_element_by_xpath('.//div[@class="arrival"]/time').get_attribute('datetime'))
    print('Duración de escala', i+1,': ', seg.find_element_by_xpath('.//div[@class="stop-content"]/p[@class="stop-wait-time"]/span[@class="duration"]/time').get_attribute('datetime').replace('PT', ''))

for i, seg in enumerate(segmentos):
    print('Número de vuelo en la escala', i,': ', seg.find_element_by_xpath('.//span[@class="equipment-airline-number"]').text)
    print('Modelo del avión en la escala', i,': ', seg.find_element_by_xpath('.//span[@class="equipment-airline-material"]').text)


Segundo reto

for i, tarifa in enumerate(tarifas):
    print('Tarifa ', i+1, ': ', tarifa.find_element_by_xpath('.//label').get_attribute('for'))
    print("Moneda: ", tarifa.find_element_by_xpath('.//span[@class="currency-symbol"]').text)
    print("Valor: ", tarifa.find_element_by_xpath('.//span[@class="value"]').text)

Una consulta, como hago para extraer, por ejemplo el horario de llegada a cada aeropuerto dentro de un mismo segmento, si estos estan compartiendo la misma clase y los mismos tags. No encuentro la forma. Siempre me trae el primero.
Gracias!

Tambien en el minuto 5:56 que pide que hagamos vuelo.click(), actualmente no va a servir debido a que la pagina cambio, para que te funcione debes de realizar la siguiente query:

vuelo.find_element_by_xpath('//button[@class="price-button"]').click()```

Con esto se te abrirara la ventana de tarifas

Solo les vengo a decir…QUE BRUTAL!!!, OSEAAAA, AMOOOO ESTE CURSO!!! YEAH!!!



url='https://www.latam.com/pt_br/apps/personas/booking?fecha1_dia=01&fecha1_anomes=2020-09&from_city1=GRU&to_city1=LIS&ida_vuelta=ida_vuelta&fecha2_dia=11&fecha2_anomes=2020-09&from_city2=LIS&to_city2=GRU&cabina=Y&nadults=1&nchildren=0&ninfants=0&app=deal-finder#/'


#origen
print('origen: ',segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')[0].text)
#duracion
print('Duración:',segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime'))
#destino
print('Destino:',segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')[1].text)
#Detalles avion
print('MOdelo Avion:',segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text)
#Detalles avion
print('VUelo:',segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]').text)

#pueden usar este enlace para practicas

url='https://www.latam.com/pt_br/apps/personas/booking?fecha1_dia=01&fecha1_anomes=2020-09&from_city1=GRU&to_city1=LIS&ida_vuelta=ida_vuelta&fecha2_dia=11&fecha2_anomes=2020-09&from_city2=LIS&to_city2=GRU&cabina=Y&nadults=1&nchildren=0&ninfants=0&app=deal-finder#/'

el reto final

tarifas=vuelo.find_elements_by_xpath('.//div[@class="fares-table-container"]//tfoot//td[contains(@class, "fare-")]')
tarifas
#out 
[<selenium.webdriver.remote.webelement.WebElement (session="2c4da4d36723a793f87f3629046da14e", element="7a0e2f38-b36a-4635-bc8a-59d94ed9dff3")>,
 <selenium.webdriver.remote.webelement.WebElement (session="2c4da4d36723a793f87f3629046da14e", element="594ef01a-8072-4728-9f6f-f09a5d446e3c")>,
 <selenium.webdriver.remote.webelement.WebElement (session="2c4da4d36723a793f87f3629046da14e", element="6fdae90a-91d8-4900-b620-71f1412d9844")>]


#in
for tarifa in tarifas:
    print(tarifa.text)
#out
R$1.231,14
R$1.494,00
R$5.699,84

Esta es mi solución al reto:

tarifas = vuelo.find_elements_by_xpath('.//div[@class="fares-table-container"]//tfoot//td[contains(@class, "fare-")]')

for tarifa in tarifas:
    sy_pre = tarifa.find_elements_by_xpath('.//span[@class="price"]/span')
    sy = sy_pre[0].text
    pre = sy_pre[1].text
    print(f'el precio es de {sy} {pre}')```

Aquí una solución simple para saber el nombre de la tarifa y el precio:

for tarifa in tarifas:
    print('{}: {}'.format(tarifa.find_element_by_xpath('.//label').get_attribute('for'),tarifa.text))

El resultado:
LIGHT: US$434
PLUS: US$488
TOP: US$1646

Primer reto:

segmento = segmentos[0]
segmento_salida = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr[@class="sc-hrWEMg hlCkST"]')[0].text
segmento_llegada = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr[@class="sc-hrWEMg hlCkST"]')[1].text
hora_salida = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')[0].get_attribute('datetime')
hora_llegada = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')[1].get_attribute('datetime')
duracion_segmento = segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')
numero_vuelo = segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text
modelo_avion = segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]').text
print(f'Salida de segmento: {segmento_salida}')
print(f'Hora de Salida: {hora_salida}')
print(f'Duracion Segmento: {duracion_segmento}')
print(f'Llegada de segmento: {segmento_llegada}')
print(f'Hora de Llegada: {hora_llegada}')
print(f'Numero de Vuelo: {numero_vuelo}')
print(f'Modelo Avion: {modelo_avion}')
#Destino de c/escala
segmento.find_element_by_xpath('.//span[@class="C"]//abbr[@class="sc-hrWEMg hlCkST"]').text
#Hora de llegada de la escala
segmento.find_element_by_xpath('.//span[@class="C"]//time').get_attribute('datetime')
#duración del vuelo
segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')
#Nº de vuelo
segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text
#Avión
segmento.find_element_by_xpath('.//span[@class="sc-gzOgki uTyOl"]').text
tarifas_extrapoladas = []
for i, tarifa in enumerate(tarifas):
    dict = {}
    precio = tarifa.find_element_by_xpath('.//div[@class="attribute-column-wrapper"]//span[@class="value"]').text
    dict["precio"] = precio
    moneda = tarifa.find_element_by_xpath('.//div[@class="attribute-column-wrapper"]//span[@class="currency-symbol"]').text
    dict["moneda"] = moneda
    
    tarifas_extrapoladas.append(dict)

print(tarifas_extrapoladas)```

tarifas = vuelo.find_elements_by_xpath(’.//div[@class=“fares-table-container”]//tfoot//td[contains(@class, “fare-”)]’)

for tarifa in tarifas:
print(tarifa.text)

Mi respuesta:

def find_tarifa(tarifa):
    currency = tarifa.find_element_by_xpath('.//span[@class="currency-symbol"]')
    precio = tarifa.find_element_by_xpath('.//span[@class="value"]')
    print(f"Precio: {precio.text}\nCurrency: {currency.text}")
    return precio.text, currency.text
find_tarifa(tarifas[0])
[find_tarifa(tarifa) for tarifa in tarifas]

Esta bueno saber usar x-path, aqui la documentacion para usar selenium,también podemos interactuar con los siguiente selectores.

Los primeros obtenermos la referencia al objeto como usar getElementById en JS

  • find_element_by_id
  • find_element_by_name
  • find_element_by_xpath
  • find_element_by_link_text
  • find_element_by_partial_link_text
  • find_element_by_tag_name
  • find_element_by_class_name
  • find_element_by_css_selector

Los selectores multiples retornan una lista:

  • find_element_by_id
  • find_element_by_name
  • find_element_by_xpath
  • find_element_by_link_text
  • find_element_by_partial_link_text
  • find_element_by_tag_name
  • find_element_by_class_name
  • find_element_by_css_selector

Super genial el reto, hubo ciertas consideraciones en cuanto a segmentos, Comparto codigo:
Vuelo La Paz-Lima-Cuzco con escala en Lima:
Resultados obtenidos:

LPB LIM 04:39 05:30
La duracion del vuelo es: 1:51
La escala de espera en aeropuerto es 1:35
LA2401 Airbus 320-200

LIM CUZ 07:05 08:27
La duracion del vuelo es: 1:22
LA2013 Airbus 320-200

Consideraciones de los segmentos ya que donde se encuentra la escala tiene otro nombre de clase asi que adicioné segmento3 guardandolo como uno array de un elemento

segmento=segmentos[0]
segmento2=segmentos[1]
segmento4=vuelo.find_elements_by_xpath('//div[@class="sc-hZSUBg gfeULV"]/div[@class="sc-cLQEGU dnKRNG"]')
segmento3=segmento4[0]
#Luego se procede con los codigos
#Primer segmento
#Hallando el origen de escala
salidas=segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')
salida=salidas[0].text
#Hallando el destino de escala
llegada=salidas[1].text
#Hallando la hora de salida de vuelo
hora=segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')
hora_partida=hora[0].text
#Hallando la hora de llegada de cada escala
hora_salida=hora[1].text
#Hallando la duracion de cada vuelo
duracion=segmento.find_elements_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time')
duracion1=duracion[0].get_attribute('datetime')
#Hallando la duración de la escala
escalad=segmento3.find_elements_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time')
escala=escalad[0].get_attribute('datetime')
#Hallando el número de vuelo
vuelo=segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]//b')
num_vuelo=vuelo.text
#Hallando el modelo del avion
avion=segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]')
modeloavion=avion.text
print(salida,llegada,hora_partida,hora_salida)
print(f'La duracion del vuelo es: {duracion1}')
print(f'La escala de espera en aeropuerto es {escala}')
print(num_vuelo,modeloavion)


#Segundo segmento
#Hallando el origen de escala
salidas=segmento2.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')
salida=salidas[0].text
#Hallando el destino de escala
llegada=salidas[1].text
#Hallando la hora de salida de vuelo
hora=segmento2.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')
hora_partida=hora[0].text
#Hallando la hora de llegada de cada escala
hora_salida=hora[1].text
#Hallando la duracion de cada vuelo
duracion=segmento2.find_elements_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time')
duracion1=duracion[0].get_attribute('datetime')
#Hallando el número de vuelo
vuelo=segmento2.find_element_by_xpath('.//div[@class="airline-flight-details"]//b')
num_vuelo=vuelo.text
#Hallando el modelo del avion
avion=segmento2.find_element_by_xpath('.//div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]')
modeloavion=avion.text
print(salida,llegada,hora_partida,hora_salida
print(f'La duracion del vuelo es: {duracion1}')
print(num_vuelo,modeloavion)


Moneda:

tarifa_moneda = tarifas[0].find_element_by_xpath('.//span[@class="currency-symbol"]').text

Precio:

tarifa_precio = tarifas[0].find_element_by_xpath('.//span[@class="value"]').text

Codigo para el reto:

escalas_tag = vuelo.find_elements_by_xpath('//div[@class="sc-cLQEGU dnKRNG"]//time')    
escalas = list(map(lambda escala : escala.get_attribute('datetime') , escalas_tag))

for i, segmento in enumerate(segmentos):
    global escalas
    aeropuertos_tag = segmento.find_elements_by_xpath('.//div[@class="sc-iujRgT jEtESl"]//abbr[@class="sc-hrWEMg hlCkST"]')
    aeropuertos = list(map(lambda aeropuerto : aeropuerto.get_attribute('title') , aeropuertos_tag))
    horas_tag = segmento.find_elements_by_xpath('.//div[@class="sc-iujRgT jEtESl"]//time')
    horas = list(map(lambda hora : hora.get_attribute('datetime') , horas_tag))
    duracion = segmento.find_element_by_xpath('.//div[@class="sc-bMVAic hShZwU"]//time').get_attribute('datetime')
    modelo = segmento.find_element_by_xpath('.//div[@class="sc-hMFtBS bGZqFm"]//span[@class="sc-gzOgki uTyOl"]').text
    vuelo = segmento.find_element_by_xpath('.//div[@class="sc-hMFtBS bGZqFm"]//b').text
    print(f'Tramo N# {i+1}: vuelo {vuelo}, nave {modelo}.')
    print(f'salida a las {horas[0]} desde el aeropuerto {aeropuertos[0]}, llegada a las {horas[1]} al aeropuerto {aeropuertos[1]}.')
    print(f'Duracion del tramo: {duracion}')
    if i < len(segmentos) - 1:
        print(f'Duracion de escala: {escalas[i]}')
    
#Output:
Tramo N# 1: vuelo LA8013, nave Airbus 320-200.
salida a las 18:00 desde el aeropuerto EZE, llegada a las 20:50 al aeropuerto GRU.
Duracion del tramo: 2:50
Duracion de escala: 1:50
Tramo N# 2: vuelo LA8064, nave Airbus 350-900.
salida a las 22:40 desde el aeropuerto GRU, llegada a las 13:35 al aeropuerto MAD.
Duracion del tramo: 9:55

Código para tarifas:

tarifas_tag = vuelo.find_elements_by_xpath('.//ul[@class="selection-tabs-fare-list"]//span[@class="price"]')
monedas = list(map(lambda tarifa : tarifa.find_element_by_xpath('./span[@class="currency-symbol"]').text , tarifas_tag))
valores = list(map(lambda tarifa : tarifa.find_element_by_xpath('./span[@class="value"]/span').text , tarifas_tag))
tarifas = list(map(lambda moneda, valor : f'{moneda} {valor}', monedas, valores))
categorias_tag = vuelo.find_elements_by_xpath('.//div[@class="selection-tabs"]//h4[@class="fare-category"]/span')
categorias = list(map(lambda categoria : categoria.text , categorias_tag)) 
tarifa_por_categoria = dict(zip(categorias, tarifas))
tarifa_por_categoria

**output:**

{'Light': 'ARS 51.069,80', 'Plus': 'ARS 56.173,00', 'Top': 'ARS 109.961,75'}

hice el reto de esta manera

import requests
from bs4 import BeautifulSoup
from selenium import webdriver
import time

url = "https://www.latam.com/es_mx/apps/personas/booking?fecha1_dia=10&fecha1_anomes=2020-11&auAvailability=1&ida_vuelta=ida&vuelos_origen=Ciudad%20de%20M%C3%A9xico&from_city1=MEX&vuelos_destino=Santiago%20de%20Chile&to_city1=SCL&flex=1&vuelos_fecha_salida_ddmmaaaa=10/11/2020&cabina=Y&nadults=1&nchildren=0&ninfants=0&cod_promo=&stopover_outbound_days=0&stopover_inbound_days=0#/"
r = requests.get(url)
print(r.status_code)

s = BeautifulSoup(r.text, 'lxml')

# print(s.prettify())

options = webdriver.ChromeOptions()
options.add_argument('--incognito')
driver = webdriver.Chrome(executable_path='./chromedriver', options=options)  # Inicia el navegador
driver.get(url)

time.sleep(15)

vuelos = driver.find_elements_by_xpath('//li[@class="flight"]')

print(vuelos)
vuelo = vuelos[1]
# vuelo
print(vuelo)

hora_salida = vuelo.find_element_by_xpath('.//div[@class="departure"]/time').get_attribute('datetime')
hora_llegada = vuelo.find_element_by_xpath('.//div[@class="arrival"]/time').get_attribute('datetime')
duracion_vuelo = vuelo.find_element_by_xpath('.//span[@class="duration"]/time').get_attribute('datetime')
duracion_formateada = duracion_vuelo.replace('PT', '')
print(hora_salida)
print(hora_llegada)
print(duracion_vuelo)
print(duracion_formateada)

boton_escalas = vuelo.find_element_by_xpath('.//div[@class="flight-summary-stops-description"]/button')

boton_escalas.click()
time.sleep(7)
interfaz = vuelo.find_element_by_xpath('//div[@class="sc-hZSUBg gfeULV"]')
segmentos = interfaz.find_elements_by_xpath('.//div[@class="sc-cLQEGU hyoued"]')
escalas = interfaz.find_elements_by_xpath('.//div[@class="sc-cLQEGU dnKRNG"]')
print(f'Numero de escalas {len(escalas)}')

# segmento = segmentos[0]
cont = len(escalas)
for segmento in segmentos:

    partida_s = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')[0].get_attribute('title')
    hora_partida_s = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')[0].get_attribute(
        'datetime')
    aeropuerto_partida = \
        segmento.find_elements_by_xpath('.//div[@class="sc-iujRgT jEtESl"]/span[@class="sc-eTuwsz eumCTU"]/span')[0].text
    llegada_s = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')[1].get_attribute('title')
    hora_llegada_s = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')[1].get_attribute(
        'datetime')
    aeropuerto_llegada = \
        segmento.find_elements_by_xpath('.//div[@class="sc-iujRgT jEtESl"]/span[@class="sc-eTuwsz eumCTU"]/span')[1].text
    avion = segmento.find_element_by_xpath(
        './/div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]').text
    duracion_vuelo_s = segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute(
        "datetime")
    numero_vuelo = segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text
    print("-" * 20)
    print(f'Partida de: {partida_s} del aeropuerto: {aeropuerto_partida}')
    print(f'Hora de partida {hora_partida_s}')
    print(f'llegada a: {llegada_s} al aeropuerto: {aeropuerto_llegada}')
    print(f'Hora de llegada {hora_llegada_s}')
    print(f"Modelo del avion: {avion}")
    print(f"Numero de vuelo: {numero_vuelo}")
    print(f"Duracion de vuelo: {duracion_vuelo_s}")
    print("-" * 20)
    if cont > 0:
        tiempo_escala = escalas[cont - 1].find_element_by_xpath(
            './/span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')
        print(f'Duracion de la escala: {tiempo_escala}')
        cont -= cont

driver.close()  # cierra el navegador```

Estos son los códigos del reto:
El de obtener los datos de escala y demas:

for segmento in segmentos:
    try:
        print('Salida:', segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')[0].text)
        print('Hora de salida:', segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')[0].get_attribute('datetime'))
        print('Duracion de vuelo:', segmento.find_element_by_xpath('.//div[@class="sc-eXEjpC fqUnRK"]/span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime'))
        print('Llegada:', segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')[1].text)
        print('Hora de llegada:', segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')[1].get_attribute('datetime'))
        print('Numero vuelo:', segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text)
        print('Modelo avion:', segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]').text)
        print('\n')
        if segmento != segmentos[-1] and escalas != 0 and segmento == segmentos[0]:
            print('Duracion escala:', segmento.find_elements_by_xpath('//div[@class="sc-cLQEGU dnKRNG"]//div[@class="sc-eXEjpC fqUnRK"]/span[@class="sc-esjQYD dMquDU"]/time')[0].get_attribute('datetime'))
        if segmento == segmentos[1] and escalas == 2:
            print('Duracion escala:', segmento.find_elements_by_xpath('//div[@class="sc-cLQEGU dnKRNG"]//div[@class="sc-eXEjpC fqUnRK"]/span[@class="sc-esjQYD dMquDU"]/time')[1].get_attribute('datetime'))
        print('\n')
    except:
        pass

Resultado:

Y el de las tarifas:

for tarifa in tarifas:
    moneda = tarifa.find_element_by_xpath('.//span[@class="price"]/span[@class="currency-symbol"]').text
    valor = tarifa.find_element_by_xpath('.//span[@class="price"]/span[@class="value"]/span').text
    clase = tarifa.find_element_by_xpath('.//label').get_attribute('for')

    print('Tarifa {}: {} {}'.format(clase, moneda, valor))

Resultado:
![](

Reto de las tarifas de vuelo:

mo = []
pre = []
for i in range(len(tarifas)):
    mo.append(tarifas[i].find_element_by_xpath(".//span[@class='currency-symbol']").text)
    pre.append(tarifas[i].find_element_by_xpath(".//span[@class='value']").text)
tarifas = list(map(lambda moneda, valor : f'{moneda} {valor}', mo, pre))
categorias = ['Ligth','Plus','Top']
diccionario = dict(zip(categorias,tarifas))
print(diccionario)
##### 1. se instancia un driver (chromedriver.exe debe estar en la misma carpeta 

options = webdriver.ChromeOptions()
options.add_argument('--incognito')
driver = webdriver.Chrome('chromedriver.exe')

##### 2. hacer que el navegador cargue la pagina

driver.get(url)

##### 3. extraer informacion de la pagia

vuelos = driver.find_elements_by_xpath('//li[@class="flight"]')
vuelos

vuelo = vuelos[0]
vuelo

vuelo.find_element_by_xpath('.//div[@class="departure"]/time').get_attribute('datetime')

vuelo.find_element_by_xpath('.//div[@class="arrival"]/time').get_attribute('datetime')

duracion = vuelo.find_element_by_xpath('.//span[@class="duration"]/time').get_attribute('datetime')
print(duracion.replace('PT', ' '))

##### para hacer click en un boton


boton_escalas = vuelo.find_element_by_xpath('.//div[@class="flight-summary-stops-description"]/button')

boton_escalas.click()

segmentos = vuelo.find_elements_by_xpath('//div[@class="sc-hZSUBg gfeULV"]/div[@class="sc-cLQEGU hyoued"]')

segmentos

cantidad_escalas = len(segmentos)-1
cantidad_escalas

segmento = segmentos[0]

segmento

#####  lugar y hora de salida

lugar = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')
lsalida = lugar[0]
lsalida.text

lsalida = lugar[1]
lsalida.text

#####  modelo del avion

avion = segmento.find_elements_by_xpath('.//div[@class="airline-flight-details"]/span')
navion = avion[1]
navion.text

tiempo = segmento.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')
salida = tiempo[0]
salida.text


llegada = tiempo[1]
llegada.text

#####  escala

escala = segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').text
s = escala.replace('\n', ' ')
s

##### trayecto 2

segmento2 = segmentos[-1]
lugar2 = segmento2.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/abbr')
lsalida2 = lugar2[0]
lsalida2.text

lsalida2 = lugar2[1]
lsalida2.text

avion2 = segmento2.find_elements_by_xpath('.//div[@class="airline-flight-details"]/span')
navion2 = avion2[1]
navion2.text

tiempo2 = segmento2.find_elements_by_xpath('.//div[@class="sc-bwCtUz iybVbT"]/time')
salida2 = tiempo2[0]
salida2.text

salida2 = tiempo2[1]
salida2.text

driver.find_element_by_xpath('.//div[@class="ReactModal__Content ReactModal__Content--after-open modal-dialog segments-modal sc-gZMcBi yRFTu"]//button[@class="close"]').click()

vuelo.click()

####Precio de cada una de las tarifas

tarifas = vuelo.find_elements_by_xpath('.//div[@class="fares-table-container"]//tfoot//td[contains(@class, "fare-")]//span[@class = "price"]/span[@class="value"]')

basic1 = tarifas[0]
basic2 = tarifas[1]
basic3 = tarifas[2]
basic4 = tarifas[3]
print(f'Basic {basic1.text} Light {basic2.text} Plus {basic3.text} Top {basic4.text}')

Dejo el codigo del primer reto

rutas = vuelo.find_elements_by_xpath('//div[@class = "sc-bwCtUz iybVbT"]/abbr')
horas = vuelo.find_elements_by_xpath('//div[@class = "sc-bwCtUz iybVbT"]/time')
duracion = vuelo.find_elements_by_xpath('//span[@class = "sc-esjQYD dMquDU"]/time')
airplane = vuelo.find_elements_by_xpath('//div[@class = "airline-flight-details"]/span[@class = "sc-gzOgki uTyOl"]')
num_flight = vuelo.find_elements_by_xpath('//div[@class = "airline-flight-details"]/b')
for j, i in enumerate(range(0,len(rutas),2)):
    print('De',rutas[i].text,'a las',horas[i].text, 'a' ,rutas[i+1].text,'a las', horas[i+1].text, 'Duracion',duracion[i].get_attribute('datetime'),'Numero de vuelo',num_flight[j].text,'Avion',airplane[j].text)
    if i+2 < len(rutas):
        print("Duracion escala:",duracion[i+1].get_attribute('datetime'),'H')

Resultado:

De BOG a las 21:05 a GRU a las 05:20+1 Duracion 6:15 Numero de vuelo LA8001 Avion Boeing 767-300
Duracion escala: 12:0 H
De GRU a las 17:20 a LIS a las 06:05+1 Duracion 9:45 Numero de vuelo LA8146 Avion Airbus 350-900
Duracion escala: 2:25 H
De LIS a las 08:30 a MAD a las 10:55 Duracion 1:25 Numero de vuelo IB3111 Avion Airbus 321

Y este es el codigo del segundo reto

tarifas = vuelo.find_elements_by_xpath('.//div[@class="fares-table-container"]//tfoot//td[contains(@class,"fare")]')
for tarifa in tarifas:
    print(tarifa.find_element_by_xpath('.//span[@class="currency-symbol"]').text,tarifa.find_element_by_xpath('.//span[@class="value"]').text)

Resultado:
$ 2.227.230
$ 2.486.050
$ 2.776.690

Solución del reto, Código:

Output:

i = 0
for segmento in segmentos:
    i+= 1
    origen,destino = segmento.find_elements_by_xpath('.//div[@class="sc-iujRgT jEtESl"]//abbr[@class="sc-hrWEMg hlCkST"]')
    hora_salida, hora_llegada = segmento.find_elements_by_xpath('.//div[@class="sc-iujRgT jEtESl"]//time')
    duracion_vuelo=segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')
    vuelo=segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text
    modelo = segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/span[@class="sc-gzOgki uTyOl"]').text
    print(f"""Escala {i}
Origen: {origen.text}
Hora Salida: {hora_salida.get_attribute('datetime')}
Destino: {destino.text}
Hora Llegada: {hora_llegada.get_attribute('datetime')}
Duracion vuelo: {duracion_vuelo}
Numero de Vuelo: {vuelo}
Modelo Avion: {modelo}
""")```


Out::

Escala 1
Origen: BOG
Hora Salida: 18:22
Destino: LIM
Hora Llegada: 21:25
Duracion vuelo: 3:3
Numero de Vuelo: LA2447
Modelo Avion: Airbus 320-200
.
Escala 2
Origen: LIM
Hora Salida: 00:15
Destino: MIA
Hora Llegada: 06:05
Duracion vuelo: 5:50
Numero de Vuelo: LA2460
Modelo Avion: Boeing 767-300
.
Escala 3
Origen: MIA
Hora Salida: 08:50
Destino: EWR
Hora Llegada: 11:48
Duracion vuelo: 2:58
Numero de Vuelo: UA1662
Modelo Avion: Airbus 320-200

A 17 de Septiembre de 2020 los valores de las clases siguen igual que hace 3 meses

    button = vuelos[6].find_element_by_xpath('.//div[@class="flight-summary-stops-description"]/button')
    button.click()
    segments = vuelos[6].find_elements_by_xpath('//div[@class="sc-hZSUBg gfeULV"]/div[@class="sc-cLQEGU hyoued"]')

    for idx, escala in enumerate(segments):
        print('Escala N°: {}'.format(idx + 1))
        escala = segments[idx].find_elements_by_xpath('.//span[@class="sc-bsbRJL bMMExG"]//abbr')
        escala_time = segments[idx].find_elements_by_xpath('.//span[@class="sc-bsbRJL bMMExG"]//time')
        # Origin
        print('Lugar de Origen: {} Hora: {}'.format(escala[0].text, escala_time[0].text))
        # Destiny
        print('Lugar de Destino: {} Hora: {}'.format(escala[1].text, escala_time[1].text))
        # duration
        duration = segments[idx].find_element_by_xpath('.//span[@class="sc-cmthru ipcOEH"]//time').get_attribute('datetime')
        print('Duracion: {}h'.format(duration))
        # Numero de vuelo y Avion
        numero = segments[idx].find_element_by_xpath('.//div[@class="airline-flight-details"]//b')
        avion = segments[idx].find_element_by_xpath('.//span[@class="sc-gzOgki uTyOl"]')
        print('Numero de vuelo: {} Avion: {}'.format(numero.text, avion.text))
        # Avion
        print('-' * 40)

    driver.find_element_by_xpath('//div[@class="modal-content sc-iwsKbI eHVGAN"]//button[@class="close"]').click()
    ############### TARIFAS ###################
    vuelos[6].click()
    #### Economy #####
    tarifas_basicas = vuelos[6].find_elements_by_xpath('.//div[@class="fares-table-container"]//tfoot//td[contains(@class, "fare-")]')
    print('Economy cabin')
    for tarifa in tarifas_basicas:
        label = tarifa.find_element_by_xpath('.//label').get_attribute('for')
        price = tarifa.find_element_by_xpath('.//span[@class="price"]/span[@class="value"]/span')
        currency = tarifa.find_element_by_xpath('.//span[@class="price"]/span[@class="currency-symbol"]')
        print('{}: {}{}'.format(label, currency.text, price.text))
    print('-' * 40)
    #### Premium #####
    button_premium = vuelos[6].find_element_by_xpath('.//li[@id="J"]')
    button_premium.click()
    tarifas_premium = vuelos[6].find_elements_by_xpath('.//div[@class="fares-table-container"]//tfoot//td[contains(@class, "fare-")]')
    print('Premium Bussines Cabin')
    for tarifa in tarifas_premium:
        label = tarifa.find_element_by_xpath('.//label').get_attribute('for')
        price = tarifa.find_element_by_xpath('.//span[@class="price"]/span[@class="value"]/span')
        currency = tarifa.find_element_by_xpath('.//span[@class="price"]/span[@class="currency-symbol"]')
        print('{}: {}{}'.format(label, currency.text, price.text))
    print('-' * 40)

extraccion de tarfias y todo lo que incluye:

trate de obtener ademas del precio, todo lo que incluye el vuel, alimento, equipaje, flexibilidad, etc…
esto fue lo que logre hacer:

-primero obtuve la lista de elementos de elementos correspondiente a cada tarifa, que a dia de hoy estan en tags li con un clase distinta

tarifas_disponibles=vuelo.find_elements_by_xpath('.//ol[@aria-label="Tarifas disponibles."]/li[@class="sc-lnrBVv cVmVy"]')
tarifas_disponibles

captura_notebook.

luego, para cada elemento de esta lista obtengo la informacion detallada, (lo mostrare por separado para que se entienda mejor)–

precios:

precios_tarifas=[tarifa.find_element_by_class_name('displayAmount').text for tarifa in tarifas_disponibles]
precios_tarifas

nombres_de_tarifa:

nombres_tarifas=[tarifa.find_element_by_xpath('.//span[@class="sc-cFlXAS lhMviV"]').text for tarifa in tarifas_disponibles]
nombres_tarifas

para obtener lo que incluye cada tarifa. tuve que extraer una lista de elementos por cada tag <li> de la lista inicial (tarifas_disponibles), ya que como se ve resaltado en la imagen, cada tarifa posee un listado de beneficios

para logra esto primero se extraen los elementos correspondientes al listado de beneficios de cada tarifa, lo hice con list_comprehensions

detalles_en_tarifas=[included.find_elements_by_xpath('.//ul[@class="sc-dKEPtC dxncdP"]//span') for included in tarifas_disponibles]

cada elemento de esta lista, es una lista de elementos en la cual estan los beneficios incluidos de la tarifa, estos elementos tiene la informacion del beneficio, en un atributo llamado ‘title’, lo cual extraje con otro for loop

incluido=[] #creo una lista vaci para guardar cada beneficio 
for lista in detalles_en_tarifas:
    incluido.append([element.get_attribute('title') for element in lista])

asi obtengo lo siguiente

por ultimo, condenso toda la informacion obtenida en un diccionario, en donde llaves seran el nombre de la tarifa, y los valores de estas llaves, seran tuplas, que contengan el precio y una lista de beneficios incluidos,

creo que seria una idea bastante util, lo hice con el objetivo de poner en practica las list comprehension y dict comprehensios, sin embargo creo que estoy utilizando demasiados for loops, aunque es no es que cause mucho problema por que son listas relativamente pequeñas, cuando empiece a unificar todo en módulos, quizá logre algo mas eficiente

cada vez es mas emocionante esto del WebScraping

Mi solución para extraer los datos de las escalas:

datos = []
for item in segmentos:
  salida = item.find_elements_by_xpath('.//div/div/div[@class="sc-TuwoP chNiww"]/div/span')
  datos.extend(salida)
  duracion = item.find_elements_by_xpath('.//div/div/div[@class="sc-fQkuQJ eyxjup"]/span')
  datos.extend(duracion)
  llegada = item.find_elements_by_xpath('.//div/div/div[@class="sc-epGmkI hynWkG"]/div/span')
  datos.extend(llegada)
datos_esc = []
for item in datos:
  dato = item.text
  datos_esc.append(dato)

Les dejo como me quedó en 2021, si quieren que ponga el código completo para ejecutar avisen 😊.

from selenium.common.exceptions import NoSuchElementException

def obtener_escala(segmento):
    escala = {}
    
    segmento_aeropuertos = segmento.find_elements_by_xpath('.//abbr')
          
    escala['origen'] = segmento_aeropuertos[0].text
    escala['destino'] = segmento_aeropuertos[-1].text    
    
    segmento_horarios = segmento.find_elements_by_xpath('.//time')    

    escala['hora_partida'] = segmento_horarios[0].get_attribute('datetime')    
    escala['duracion'] = segmento_horarios[1].get_attribute('datetime')
    escala['hora_llegada'] = segmento_horarios[-1].get_attribute('datetime')    
    
    try:    
        demora = segmento.find_element_by_xpath('./following-sibling::*//time')
        escala['demora'] = demora.get_attribute('datetime')
    except NoSuchElementException as e:
        escala['demora'] = '0:0'
        
    segmento_numero_vuelo = segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b')
    escala['numero'] = segmento_numero_vuelo.text
    
    segmento_modelo_avion = segmento.find_element_by_xpath('(.//div[@class="airline-flight-details"]/span)[last()]')    
    escala['modelo'] = segmento_modelo_avion.text
    
    return escala

for segmento in segmentos:
    print(obtener_escala(segmento))
    

En Enero 2021, El boton para cerrar la ventana no es visible, yo lo pude cerrar usando este secuencia de codigo:

<itinerario=vuelo.find_element_by_xpath('.//div[@id="ContainerFooterCard1"]/a/span[@aria-hidden="true"]')
itinerario.click()
segmentos= vuelo.find_elements_by_xpath('//div[@aria-hidden="true"]//section[@data-test="section-info-leg"]')
print("este vuelo tiene ",len(segmentos)," Escalas")
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//div[@class="MuiDialog-container MuiDialog-scrollPaper"]//button[@class="MuiButtonBase-root MuiIconButton-root sc-dNLxif cnFxBf"]'))).click()
vuelo.click()>

Ahora mismo el boton para cerrar la informacion de escalas no se puede acceder:

<boton=driver.find_element_by_xpath('//div[@class="MuiDialog-container MuiDialog-scrollPaper"]//button[@class="MuiButtonBase-root MuiIconButton-root sc-dNLxif cnFxBf"]')
print("Element is visible? " + str(boton.is_displayed()))>

Esto imprime falso
para cerrarlo use esta linea de codigo:

<WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, '//div[@class="MuiDialog-container MuiDialog-scrollPaper"]//button[@class="MuiButtonBase-root MuiIconButton-root sc-dNLxif cnFxBf"]'))).click()>

Así es como encontré el precio:

# Gettings the price objects
price = flight.find_elements_by_xpath('.//div[@class = "fares-table-container"]//tfoot//td[contains(@class, "fare-")]')
price

# Extracting the prices

price[0].find_element_by_xpath('.//span[@class = "price"]').text

# Output
'US$318'