Guía para el scraping de datos de Google Flights con Python

Comentarios: 0

Cuando se trata de la planificación de viajes, análisis de la competencia o con fines de investigación, el raspado de la información relacionada con los vuelos de Google Flights podría producir información significativa. Aquí tienes un tutorial paso a paso sobre cómo scrapear información de vuelos utilizando las librerías Python, Playwright y lxml.

Cómo configurar el entorno

Antes de sumergirte en el proceso de scraping, asegúrate de tener instaladas las librerías Python necesarias:

pip install playwright
Pip install lxml

Para utilizar Playwright, también es necesario instalar los binarios del navegador:

playwright install chromium

Proceso de scraping paso a paso

Nos centraremos en extraer datos de vuelos de la página de resultados de búsqueda de Google Flights.

Paso 1. Entender la estructura de la página web

Para raspar datos de Google Flights de forma efectiva, debes familiarizarte con la estructura HTML del sitio web. A continuación, te explicamos cómo puedes utilizar Chrome DevTools para inspeccionar elementos y recuperar las expresiones XPath necesarias para el scraping:

  1. Abre Chrome DevTools haciendo clic con el botón derecho en la página de Google Flights y seleccionando "Inspeccionar", o utiliza el método abreviado Ctrl+Mayús+I (Windows/Linux) o Cmd+Opción+I (Mac).
  2. Inspeccione los elementos pasando el ratón por encima de diferentes partes de la página. Esto resaltará la estructura HTML en las DevTools. Haga clic en los elementos específicos para ver sus atributos, que son cruciales para crear expresiones XPath precisas.
  3. Recupere las expresiones XPath haciendo clic con el botón derecho en el elemento deseado en el panel Elementos, seleccionando "Copiar" y, a continuación, "Copiar XPath". Esto copia la expresión XPath directamente a su portapapeles, listo para usar en su script de raspado.

Lista de expresiones XPath utilizadas:

From Location: //input[@aria-label="Where from?"]/@value
To Location: //input[@aria-label="Where to?"]/@value
Departure Date: //input[@placeholder="Departure"]/@value
Return Date: //input[@placeholder="Return"]/@value

Nota: Este XPath devuelve múltiples elementos, cada uno correspondiente a un vuelo individual.

Flight Elements: //li[@class="pIav2d"]
Airway: .//div[@class="sSHqwe tPgKwe ogfYpf"]/span/text()
Details: .//span[@class="mv1WYe"]/@aria-label
Departure Time: .//span[@aria-describedby="gEvJbfc1583"]/span/text()
Arrival Time: .//span[@aria-describedby="gEvJbfc1584"]/span/text()
Travel Time: .//div[@class="gvkrdb AdWm1c tPgKwe ogfYpf"]/text()
Price: .//div[@class="YMlIz FpEdX"]/span/text()

Paso 2. Envío de peticiones HTTP y extracción del contenido de la página con Playwright

Utilizamos Playwright para interactuar con la página web y extraer su contenido. Este enfoque ayuda a manejar el contenido dinámico que JavaScript podría cargar.

El uso de Playwright ayuda a gestionar el contenido dinámico cargado por JavaScript. Lanza un navegador sin cabeza, navega a la URL y extrae el contenido de la página.

from playwright.sync_api import sync_playwright

# URL de la página de búsqueda de Google Flights
url = "https link"

def get_page_content(url):
    """Obtiene el contenido HTML de la URL dada utilizando Playwright."""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)  # Iniciar el navegador en modo headless
        context = browser.new_context()  # Crear un nuevo contexto de navegación
        page = context.new_page()  # Abrir una nueva página
        page.goto(url)  # Navegar a la URL especificada
        content = page.content()  # Obtener el contenido de la página
        browser.close()  # Cerrar el navegador
    return content

# Obtener el contenido de la página
page_content = get_page_content(url)

Paso 3. Extracción de detalles comunes mediante XPath

A continuación, analizamos el contenido HTML de la respuesta utilizando lxml para extraer detalles comunes del vuelo, como las fechas de salida y regreso.

from lxml import html

# Creación del analizador sintáctico
tree = html.fromstring(page_content)

# Extracción de datos comunes de vuelos mediante XPath
from_location = tree.xpath('//input[@aria-label="Where from?"]/@value')[0]  # Obtener la ubicación "desde
to_location = tree.xpath('//input[@aria-label="Where to?"]/@value')[0]  # Obtener el lugar de destino
departure_date = tree.xpath('//input[@placeholder="Departure"]/@value')[0]  # Obtener la fecha de salida
return_date = tree.xpath('//input[@placeholder="Return"]/@value')[0]  # Obtener la fecha de devolución

Paso 4. Extracción de datos de vuelo específicos mediante lxml

A continuación, analizamos el contenido HTML para extraer información específica del vuelo en función de las expresiones XPath identificadas.

# Inicializar una lista vacía para almacenar los detalles del vuelo
flights = []

# Extraer elementos de vuelo del HTML analizado mediante XPath
flight_elements = tree.xpath('//li[@class="pIav2d"]')

# Recorrer cada elemento de vuelo y extraer los detalles
for flight in flight_elements:
    # Extraer el nombre de la compañía aérea
    airway = flight.xpath('.//div[@class="sSHqwe tPgKwe ogfYpf"]/span/text()')[0].strip()
    
    # Extraer detalles del vuelo, como las escalas
    details = flight.xpath('.//span[@class="mv1WYe"]/@aria-label')[0]
    
    # Extraer la hora de salida
    departure = flight.xpath('.//span[@jscontroller="cNtv4b"]/span/text()')[0].strip()
    
    # Extraer la hora de llegada
    arrival = flight.xpath('.//span[@jscontroller="cNtv4b"]/span/text()')[1].strip()
    
    # Extraer el tiempo total de viaje
    travel_time = flight.xpath('.//div[@class="gvkrdb AdWm1c tPgKwe ogfYpf"]/text()')[0].strip()
    
    # Extraer el precio del vuelo
    price = flight.xpath('.//div[@class="U3gSDe"]/div/div[2]/span/text()')[0].strip()

    # Añade los detalles extraídos a la lista de vuelos como diccionario
    flights.append({
        'Airway': airway,
        'Details': details,
        'Departure': departure,
        'Arrival': arrival,
        'Travel Time': travel_time,
        'Price': price,
        'From': from_location,
        'To': to_location,
        'Departure Date': departure_date,
        'Return Date': return_date
    })

Paso 5. Guardar los datos en CSV

Por último, utilizamos el módulo CSV incorporado en Python para guardar los datos extraídos en un archivo CSV para su posterior análisis.

import csv

# Definir la ruta del archivo CSV
csv_file = 'google_flights.csv'

# Definir nombres de campo CSV
fieldnames = ['Airway', 'Details', 'Departure', 'Arrival', 'Travel Time', 'Price', 'From', 'To', 'Departure Date', 'Return Date']

# Escritura de datos en un archivo CSV
with open(csv_file, mode='w', newline='', encoding='utf-8') as file:
    writer = csv.DictWriter(file, fieldnames=fieldnames)
    writer.writeheader()
    for flight in flights:
        writer.writerow(flight)

print(f"Data saved to {csv_file}")

Poniéndolo todo junto

from playwright.sync_api import sync_playwright
from lxml import html
import csv

# URL de la página de búsqueda de Google Flights
url = "https link"

def get_page_content(url):
    """Obtiene el contenido HTML de la URL dada utilizando Playwright."""
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=False)  # Iniciar el navegador en modo cabeza llena
        context = browser.new_context()  # Crear un nuevo contexto de navegación
        page = context.new_page()  # Abrir una nueva página
        page.goto(url)  # Navegar a la URL especificada
        page.wait_for_timeout(10000)  # Espere 10 segundos para asegurarse de que la página se carga completamente.
        content = page.content()  # Obtener el contenido de la página
        browser.close()  # Cerrar el navegador
    return content

# Obtener el contenido de la página
page_content = get_page_content(url)

# Analiza el contenido HTML con lxml
tree = html.fromstring(page_content)

# Extracción de datos de búsqueda de vuelos
from_location = tree.xpath('//input[@aria-label="Where from?"]/@value')[0]
to_location = tree.xpath('//input[@aria-label="Where to?"]/@value')[0]
departure_date = tree.xpath('//input[@placeholder="Departure"]/@value')[0]
return_date = tree.xpath('//input[@placeholder="Return"]/@value')[0]

# Inicializar una lista para almacenar los detalles del vuelo
flights = []

# Extraer elementos de vuelo del HTML analizado
flight_elements = tree.xpath('//li[@class="pIav2d"]')
for flight in flight_elements:
    airway = flight.xpath('.//div[@class="sSHqwe tPgKwe ogfYpf"]/span/text()')[0].strip()
    details = flight.xpath('.//span[@class="mv1WYe"]/@aria-label')[0]
    departure = flight.xpath('.//span[@jscontroller="cNtv4b"]/span/text()')[0].strip()
    arrival = flight.xpath('.//span[@jscontroller="cNtv4b"]/span/text()')[1].strip()
    travel_time = flight.xpath('.//div[@class="gvkrdb AdWm1c tPgKwe ogfYpf"]/text()')[0].strip()
    price = flight.xpath('.//div[@class="U3gSDe"]/div/div[2]/span/text()')[0].strip()

    # Añadir los detalles del vuelo a la lista
    flights.append({
        'Airway': airway,
        'Details': details,
        'Departure': departure,
        'Arrival': arrival,
        'Travel Time': travel_time,
        'Price': price,
        'From': from_location,
        'To': to_location,
        'Departure Date': departure_date,
        'Return Date': return_date
    })

# Definir la ruta del archivo CSV
csv_file = 'google_flights.csv'

# Definir nombres de campo CSV
fieldnames = ['Airway', 'Details', 'Departure', 'Arrival', 'Travel Time', 'Price', 'From', 'To', 'Departure Date', 'Return Date']

# Escritura de los detalles de vuelo extraídos en un archivo CSV
with open(csv_file, mode='w', newline='', encoding='utf-8') as file:
    writer = csv.DictWriter(file, fieldnames=fieldnames)
    writer.writeheader()  # Escribir la línea de cabecera
    for flight in flights:
        writer.writerow(flight)  # Escribe los detalles de cada vuelo

print(f"Data saved to {csv_file}")

Para reducir el riesgo de detección durante el scraping de datos, es aconsejable incorporar retardos entre las solicitudes y utilizar proxies. La implementación de retardos ayuda a imitar la interacción humana, lo que dificulta a los sitios web la detección de actividades de scraping automatizadas. Para la selección de proxies, se recomiendan los proxies dinámicos residenciales porque ofrecen un alto nivel de confianza y es menos probable que se bloqueen debido a su naturaleza dinámica. Como alternativa, puede utilizar un grupo de proxies estáticos ISP, que proporcionan una conexión estable y rápida, mejorando la fiabilidad de su proceso de extracción de datos. Estas estrategias ayudan a eludir las medidas de protección que los sitios web utilizan para identificar y bloquear los robots de scraping.

Comentarios:

0 Comentarios