A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Scrapeando escalas y tarifas

15/30
Recursos

Aportes 66

Preguntas 8

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

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

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

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=鈥渋tinerary-modal-0-dialog-open鈥 data-testid=鈥渋tinerary-modal-0-dialog-open-link鈥 target="_self" rel=鈥渘oopener noreferrer鈥 href="#flight-0-itinerary-detail" data-reference=鈥渕odal-air-offers鈥 class=鈥渟c-fMiknA haupI鈥 aria-label=鈥淐onocer el detalle completo del itinerario de vuelo. 鈥>鈥</a> is not clickable at point (57, 483). Other element would receive the click: <div class=鈥淢uiDialog-container MuiDialog-scrollPaper鈥 role=鈥減resentation鈥 type=鈥渃enter鈥 tabindex=鈥-1鈥 style=鈥渙pacity: 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=鈥渃lose鈥 aria-label="">鈥</button> is not clickable at point (807, 62). Other element would receive the click: <div id=鈥渙nesignal-slidedown-container鈥 class=鈥渙nesignal-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鈥UE 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')
#duracin del vuelo
segmento.find_element_by_xpath('.//span[@class="sc-esjQYD dMquDU"]/time').get_attribute('datetime')
#Nde vuelo
segmento.find_element_by_xpath('.//div[@class="airline-flight-details"]/b').text
#Avin
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=鈥渇ares-table-container鈥漖//tfoot//td[contains(@class, 鈥渇are-鈥)]鈥)

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

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)

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 鈥榯itle鈥, 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'