Como fazer raspagem de dados do Google Flights

Descubra como coletar dados do Google Flights usando Python para obter informações de viagem poderosas.
10 min read
How to Scrape Google Flights blog image

Google Flights é um serviço de reserva de voos amplamente usado que fornece uma grande variedade de dados, incluindo preços de voos, horários e detalhes da companhia aérea. Infelizmente, o Google não oferece uma API pública para acessar esses dados. No entanto, a raspagem de dados na web pode ser uma ótima alternativa para extrair esses dados.

Neste artigo, mostrarei como criar um raspador robusto do Google Flights usando Python. Analisaremos cada etapa para garantir que tudo esteja claro.

Por que fazer raspagem de dados no Google Flights?

A captura de voos do Google oferece várias vantagens, incluindo:

  • Rastreio de preços de voos ao longo do tempo
  • Análise de tendências de preços
  • Identificação dos melhores horários para reservar voos
  • Comparando preços em diferentes datas e companhias aéreas

Para viajantes, isso faz com que você encontre as melhores ofertas e economize dinheiro. Para empresas, ajuda na análise de mercado, na inteligência competitiva e no desenvolvimento de estratégias de preços eficazes.

Construindo o raspador de dados do Google Flights

O raspador que construímos permitirá que você insira detalhes como aeroporto de partida, destino, data da viagem e tipo de passagem (somente ida ou ida e volta). Se você estiver reservando uma viagem de ida e volta, também precisará fornecer uma data de retorno. O raspador de dados cuidará do resto: ele carrega todos os voos disponíveis, coleta os dados e salva os resultados em um arquivo JSON para análise posterior.

Se você é iniciante em raspagem de dados na web com Python, confira este tutorial para começar.

1. Quais dados você pode extrair do Google Flights?

O Google Flights fornece muitos dados, incluindo nomes de companhias aéreas, horários de partida e chegada, duração total, número de paradas, preços de passagens e dados de impacto ambiental (por exemplo, emissões de CO2).

scrape-google-flights-data-to-be-scraped

Aqui está um exemplo dos dados que você pode coletar:

{
  "airline": "Alaska",
  "departure_time": "5:22 PM",
  "arrival_time": "9:13 PM",
  "duration": "6 hr 51 min",
  "stops": "Nonstop",
  "price": "₹51,984",
  "co2_emissions": "282 kg CO2e",
  "emissions_variation": "-22% emissions"
}

2. Configurando o ambiente

Primeiro, vamos configurar o ambiente em seu sistema para executar o raspador.

# Create a virtual environment (optional)
python -m venv flight-scraper-env

# Activate the virtual environment
# On Windows:
.\flight-scraper-env\Scripts\activate
# On macOS/Linux:
source flight-scraper-env/bin/activate

# Install required packages
pip install playwright tenacity asyncio

# Install Playwright browsers
playwright install chromium

Playwright é ideal para automatizar navegadores e interagir com páginas dinâmicas da web, como o Google Flights. Usamos o Tenacity para implementar um mecanismo de repetição.

Se você é novo no Playwright, não deixe de conferir o guia sobre raspagem de dados na web com o Playwright.

3. Definindo classes de dados

Usando a classe de dados do Python, você pode estruturar perfeitamente os parâmetros de pesquisa e os dados de voo.

from dataclasses import dataclass
from typing import Optional

@dataclass
class SearchParameters:
    departure: str
    destination: str
    departure_date: str
    return_date: Optional[str] = None
    ticket_type: str = "One way"

@dataclass
class FlightData:
    airline: str
    departure_time: str
    arrival_time: str
    duration: str
    stops: str
    price: str
    co2_emissions: str
    emissions_variation: str

Aqui, a classe SearchParameters armazena detalhes da pesquisa de voos, como partida, destino, datas e tipo de passagem, enquanto a classe FlightData armazena dados sobre cada voo, incluindo companhia aérea, preço, emissões de CO2 e outros detalhes relevantes.

4. Lógica de raspagem de dados na classe FlightScraper

A lógica principal de raspagem está encapsulada na classe FlightScraper . Aqui está uma análise detalhada:

4.1 Definindo seletores CSS

Você precisa localizar elementos específicos na página do Google Flights para extrair dados. Isso é feito usando seletores CSS. Veja como os seletores são definidos na classe FlightScraper :

class FlightScraper:
    SELECTORS = {
        "airline": "div.sSHqwe.tPgKwe.ogfYpf",
        "departure_time": 'span[aria-label^="Departure time"]',
        "arrival_time": 'span[aria-label^="Arrival time"]',
        "duration": 'div[aria-label^="Total duration"]',
        "stops": "div.hF6lYb span.rGRiKd",
        "price": "div.FpEdX span",
        "co2_emissions": "div.O7CXue",
        "emissions_variation": "div.N6PNV",
    }

Esses seletores têm como alvo o nome da companhia aérea, os horários dos voos, a duração, as paradas, o preço e os dados de emissões.

Nome da companhia aérea:

scrape-google-flights-airline-name

Horário de partida:

scrape-google-flights-departure-time

Horário de chegada:

scrape-google-flights-arrival-time

Duração do voo:

scrape-google-flights-duration

Número de paradas:

scrape-google-flights-number-of-stops

Preço:

scrape-google-flights-price

CO2e:

scrape-google-flights-co2e

Variação das emissões de CO2:

scrape-google-flights-co2e

4.2 Preenchendo o formulário de pesquisa

O método _fill_search_form simula o preenchimento do formulário de pesquisa com detalhes de partida, destino e data:

async def _fill_search_form(self, page, params: SearchParameters) -> None:
    # First, let's pick our ticket type

    ticket_type_div = page.locator("div.VfPpkd-TkwUic[jsname='oYxtQd']").first
    await ticket_type_div.click()
    await page.wait_for_selector("ul[aria-label='Select your ticket type.']")
    await page.locator("li").filter(has_text=params.ticket_type).nth(0).click()

    # Now, let's fill in our departure and destination

    from_input = page.locator("input[aria-label='Where from?']")
    await from_input.click()
    await from_input.fill("")
    await page.keyboard.type(params.departure)
    # ... rest of the form filling code

4.3 Carregando todos os resultados

O Google Flights usa paginação para carregar voos. Você precisa clicar no botão “Mostrar mais voos” para carregar todos os voos disponíveis:

async def _load_all_flights(self, page) -> None:
    while True:
        try:
            more_button = await page.wait_for_selector(
                'button[aria-label*="more flights"]', timeout=5000
            )
            if more_button:
                await more_button.click()
                await page.wait_for_timeout(2000)
            else:
                break
        except:
            break

4.4 Extraindo dados de voo

Depois que os voos estiverem carregados, você poderá fazer a raspagem de dados dos detalhes de voos:

async def _extract_flight_data(self, page) -> List[FlightData]:
    await page.wait_for_selector("li.pIav2d", timeout=30000)
    await self._load_all_flights(page)

    flights = await page.query_selector_all("li.pIav2d")
    flights_data = []

    for flight in flights:
        flight_info = {}
        for key, selector in self.SELECTORS.items():
            element = await flight.query_selector(selector)
            flight_info[key] = await self._extract_text(element)
        flights_data.append(FlightData(**flight_info))
    return flights_data

5. Adicionando um mecanismo para tentar novamente

Para tornar nosso raspador mais confiável, adicione a lógica para tentar novamente usando a biblioteca tenacity :

@retry(stop=stop_after_attempt(3), wait=wait_fixed(5))
async def search_flights(self, params: SearchParameters) -> List[FlightData]:
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=False)
        context = await browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."
        )
        # ... rest of the search implementation

6. Salvando resultados extraídos

Salve os dados de voo extraídos em um arquivo JSON para análise futura.

def save_results(self, flights: List[FlightData], params: SearchParameters) -> str:
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = (
        f"flight_results_{params.departure}_{params.destination}_{timestamp}.json"
    )

    output_data = {
        "search_parameters": {
            "departure": params.departure,
            "destination": params.destination,
            "departure_date": params.departure_date,
            "return_date": params.return_date,
            "search_timestamp": timestamp,
        },
        "flights": [vars(flight) for flight in flights],
    }

    filepath = os.path.join(self.results_dir, filename)
    with open(filepath, "w", encoding="utf-8") as f:
        json.dump(output_data, f, indent=2, ensure_ascii=False)
    return filepath

7. Executando o raspador

Veja como executar o raspador do Google Flights:

async def main():
    scraper = FlightScraper()
    params = SearchParameters(
        departure="MIA",
        destination="SEA",
        departure_date="2024-12-01",
        # return_date="2024-12-30",
        ticket_type="One way",
    )

    try:
        flights = await scraper.search_flights(params)
        print(f"Successfully found {len(flights)} flights")
    except Exception as e:
        print(f"Error during flight search: {str(e)}")

if __name__ == "__main__":
    asyncio.run(main())

Resultados finais

Depois de executar o raspador, seus dados de voo serão salvos em um arquivo JSON da seguinte forma:

{
  "search_parameters": {
    "departure": "MIA",
    "destination": "SEA",
    "departure_date": "2024-12-01",
    "return_date": null,
    "search_timestamp": "20241027_172017"
  },
  "flights": [
    {
      "airline": "American",
      "departure_time": "7:45 PM",
      "arrival_time": "11:38 PM",
      "duration": "6 hr 53 min",
      "stops": "Nonstop",
      "price": "₹50,755",
      "co2_emissions": "303 kg CO2e",
      "emissions_variation": "-16% emissions"
    },
    {
      "airline": "Alaska",
      "departure_time": "5:22 PM",
      "arrival_time": "9:13 PM",
      "duration": "6 hr 51 min",
      "stops": "Nonstop",
      "price": "₹51,984",
      "co2_emissions": "282 kg CO2e",
      "emissions_variation": "-22% emissions"
    },
    {
      "airline": "Alaska",
      "departure_time": "9:00 AM",
      "arrival_time": "12:40 PM",
      "duration": "6 hr 40 min",
      "stops": "Nonstop",
      "price": "₹62,917",
      "co2_emissions": "325 kg CO2e",
      "emissions_variation": "-10% emissions"
    }
  ]
}

Você pode encontrar o código completo no meu GitHub Gist.

Desafios comuns para escalar a raspagem de dados do Google Flights

Ao escalar a raspagem de dados do Google Flights, desafios como bloqueio de IP e CAPTCHAs são comuns. Por exemplo, se você enviar muitas solicitações em pouco tempo usando um raspador, os sites podem bloquear seu endereço IP. Para evitar isso, você pode usar a rotação manual de IP ou optar por um dos principais serviços de proxy. Se você não tiver certeza sobre qual tipo de proxy é melhor para o seu tipo de uso, confira nosso guia sobre os melhores proxies para raspagem de dados na web.

Outro desafio é lidar com CAPTCHAs. Os sites costumam usá-los quando suspeitam do tráfego de bots, bloqueando seu scraper até que o CAPTCHA seja resolvido. Lidar com isso manualmente é demorado e complexo.

Então, qual é a solução? Vamos falar sobre isso a seguir!

A solução: ferramentas de raspagem na web da Bright Data

A Bright Data oferece uma variedade de soluções projetadas para simplificar e escalar seus esforços de raspagem de dados na web de forma eficiente. Vamos explorar como a Bright Data pode ajudar você a superar esses desafios comuns.

1. Proxies Residenciais

Os proxies residenciais da Bright Data oferecem a capacidade de acessar e rastrear sites de destino sofisticados. Proxies residenciais permitem que você roteie solicitações de raspagem de dados na web através de conexões residenciais legítimas. Suas solicitações aparecerão nos sites de destino como provenientes de usuários genuínos em uma região ou área específica. Como resultado, eles são uma solução eficaz para acessar páginas protegidas por medidas contra raspagem de dados baseadas em IP.

2. Web Unlocker

O Web Unlocker da Bright Data é perfeito para criar projetos que enfrentam CAPTCHAs ou restrições. Em vez de lidar manualmente com esses problemas, o Web Unlocker os trata automaticamente, adaptando-se às mudanças nos blocos do site com uma alta taxa de sucesso (normalmente 100%). Você simplesmente envia uma solicitação e o Web Unlocker cuida do resto.

3. Scraping Browser

O Scraping Browser da Bright Data é outra ferramenta poderosa para desenvolvedores que usam navegadores headless, como  Puppeteer ou Playwright. Ao contrário dos navegadores headless tradicionais, o Scraping Browser lida com a resolução de CAPTCHA, a impressão digital do navegador, novas tentativas e muito mais — tudo automaticamente — para que você possa se concentrar na coleta de dados sem se preocupar com as restrições do site.

Conclusão

Este artigo discutiu como coletar dados do Google Flights usando Python e Playwright. Embora a raspagem de dados manual possa ser eficaz, ela geralmente traz desafios como banimentos de IP e a necessidade de manutenção contínua de scripts. Para simplificar e aprimorar seus esforços de coleta de dados, considere aproveitar as soluções da Bright Data, como proxies residenciais, Web Unlocker e Scraping Browser.

Inscreva-se para um teste gratuito com a Bright Data hoje mesmo!

Além disso, explore nossos guias sobre como coletar outros serviços do Google, como Dados de resultados de pesquisa do GoogleGoogle TrendsGoogle ScholarGoogle Maps.

Não é necessário cartão de crédito