Google Flights est un service de réservation de vols très répandu qui fournit une multitude de données telles que le prix des billets d’avion, les horaires de départ et d’arrivée, et des informations détaillées sur les compagnies aériennes. Malheureusement, Google ne propose pas d’API publique pour accéder à ces données. Cependant, le web scraping peut être une excellente alternative pour extraire ces données.
Dans cet article, je vais vous montrer comment vous pouvez construire un scraper Google Flights robuste en utilisant Python. Nous allons passer en revue chaque étape pour vous familiariser avec la procédure.
Pourquoi extraire les données Google Flights ?
L’extraction des données Google Flights présente de nombreux avantages et vous aide notamment :
- À suivre l’évolution du prix des billets d’avion
- À analyser l’évolution des prix
- À Identifier les meilleurs moments pour réserver des vols
- À comparer les prix en fonction des dates et des compagnies aériennes
Cela permet aux voyageurs de trouver les meilleures offres et d’économiser de l’argent et aide les entreprises à analyser le marché, à exercer une veille concurrentielle et à élaborer des stratégies de tarification efficaces.
Construire le scraper Google Flights
Le scraper que nous allons créer permet d’extraire des informations telles que l’aéroport de départ, la destination, la date de départ et le type de billet (aller simple ou aller-retour). Si vous réservez un vol aller-retour, vous devrez également indiquer la date de retour. Le scraper s’occupe du reste : il charge tous les vols disponibles, récupère les données et enregistre les résultats dans un fichier JSON afin que vous puissiez les analyser ultérieurement.
Si vous êtes novice en matière de web scraping avec Python, consultez ce tutoriel pour commencer.
1. Quelles données pouvez-vous extraire de Google Flights ?
Google Flights fournit de nombreuses données, notamment les noms des compagnies aériennes, les heures de départ et d’arrivée, la durée totale du vol, le nombre d’escales, le prix des billets et les données relatives à l’impact sur l’environnement (par exemple, les émissions de CO2).
Voici un exemple des données que vous pouvez extraire :
{
"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. Configuration de l’environnement
Tout d’abord, configurons l’environnement de votre système pour exécuter le scraper.
# 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 est la solution idéale pour automatiser les navigateurs et interagir avec les pages web dynamiques, telles que Google Flights. Nous utilisons Tenacity pour mettre en œuvre un mécanisme de relance.
Si vous n’êtes pas familier avec Playwright, n’oubliez pas de consulter le guide sur le « Web scraping avec Playwright ».
3. Définir les classes de données
En utilisant la classe de données
de Python, vous pouvez structurer proprement les paramètres de recherche et les données de vol.
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
Ici, la classe « SearchParameters
» stocke les critères de recherche de vols tels que le départ, la destination, les dates et le type de billet, tandis que la classe « FlightDataclass
» stocke les données relatives à chaque vol, notamment la compagnie aérienne, le prix, les émissions de CO2 et autres détails pertinents.
4. Logique du scraper dans la classe FlightScraper
La logique principale de la tâche de scraping est encapsulée dans la classe « FlightDataclass
». Voici une analyse détaillée :
4.1 Définir les sélecteurs CSS
Vous devez localiser des éléments spécifiques sur la page Google Flights pour extraire des données. Cela se fait à l’aide de sélecteurs CSS. Voici comment les sélecteurs sont définis dans la classe « FlightDataclass
» :
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",
}
Ces sélecteurs ciblent le nom de la compagnie aérienne, les horaires de vol, la durée, les escales, le prix et les données relatives aux émissions de CO2.
Nom de la compagnie aérienne :
Heure de départ :
Heure d’arrivée :
Durée du vol :
Nombre d’escales :
Prix :
Émissions de CO2 :
Variation des émissions de CO2 :
4.2 Remplir le formulaire de recherche
La méthode « _fill_search_form
» simule le remplissage du formulaire de recherche avec la date de départ, la destination et la date d’arrivée :
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 Chargement de tous les résultats
Google Flights utilise la pagination pour charger les vols. Vous devez cliquer sur le bouton « Afficher plus de vols » pour charger tous les vols disponibles :
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 Extraction des données de vol
Une fois les vols chargés, vous pouvez en extraire les détails :
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. Ajouter un mécanisme de relance
Pour rendre le scraper plus fiable, ajoutez une logique de relance en utilisant la bibliothèque « 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. Enregistrer les résultats du scraping
Enregistrez les données de vol que vous avez récupérées dans un fichier JSON pour les analyser ultérieurement.
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. Lancer le scraper
Voici comment lancer le scraper 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())
Résultats finaux
Après le lancement du scraper, vos données de vol seront sauvegardées dans un fichier JSON comme celui-ci :
{
"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"
}
]
}
Vous pouvez trouver le code complet dans ma GitHub Gist.
Défis communs lors de la mise à l’échelle des opérations d’extraction de données Google Flights
Lors de la mise à l’échelle des opérations d’extraction de données Google Flights, vous pouvez être confrontés à des défis de taille tels que le blocage des adresses IP et les CAPTCHA. Par exemple, si vous envoyez trop de requêtes en peu de temps à l’aide d’un scraper, les sites web peuvent bloquer votre adresse IP. Pour éviter cela, vous pouvez utiliser la rotation manuelle des adresses IP ou opter pour un service proxy de qualité. Si vous ne savez pas quel type de proxy convient le mieux à votre cas d’utilisation, consultez notre guide sur les meilleurs proxys pour le web scraping.
Un autre défi consiste à résoudre les CAPTCHA. Les sites web utilisent souvent des CAPTCHA pour vérifier que l’utilisateur n’est pas un robot. Les scrapers se retrouvent ainsi bloqués du site jusqu’à ce que le CAPTCHA soit résolu. La résolution manuelle des CAPTCHA prend du temps et peut vous compliquer la tâche.
Quelle est donc la solution ? C’est ce que nous allons voir maintenant !
La solution : les outils de Wew scraping de Bright Data
Bright Data propose une large gamme de solutions qui ont été spécialement conçues pour simplifier et rationaliser les opérations de web scraping. Voyons comment Bright Data peut vous aider à surmonter ces défis.
1. Proxys résidentielles
Les proxys résidentiels de Bright Data vous permettent d’accéder à des sites web sophistiqués et d’en extraire les données. Les proxys résidentiels vous permettent d’acheminer les demandes de web scraping via des connexions résidentielles légitimes. Vos requêtes apparaîtront sur les sites web ciblés comme provenant d’utilisateurs authentiques résidants dans une région ou une zone spécifique. Ils constituent donc une solution efficace pour accéder aux pages protégées par des mesures anti-scraping qui filtrent les adresses IP.
2. Web Unlocker
Le Web Unlocker de Bright Data aide à contourner les mesures anti-scraping comme les CAPTCHA et le blocage géographique qui restreint l’accès aux contenus web. Web Unlocker s’adapte et contourne automatiquement les mesures anti-scraping avec un taux de réussite élevé (généralement 100 %). Il suffit d’envoyer une demande et Web Unlocker s’occupe du reste.
3. Scraping Browser
Le Scraping Browser de Bright Data est un autre outil puissant pour les développeurs qui utilisent des navigateurs headless comme Puppeteer et Playwright. Contrairement aux navigateurs headless traditionnels, Scraping Browser gère la résolution des CAPTCHA, l’empreinte du navigateur, les nouvelles tentatives et bien d’autres choses encore, le tout de manière automatique, afin que vous puissiez vous concentrer sur la collecte des données sans vous soucier des restrictions imposées par les sites.
Conclusion
Cet article explique comment vous pouvez extraire les données de Google Flights en utilisant Python et Playwright. Si le scraping manuel peut être efficace, il s’accompagne souvent de difficultés telles que le blocage des adresses IP et la nécessité d’une maintenance permanente des scripts. Pour simplifier et rationaliser vos opérations d’extraction de données, envisagez de tirer parti des solutions de Bright Data, telles que les proxys résidentiels, le Web Unlocker et le Scraping Browser.
Inscrivez-vous pour profiter dès aujourd’hui d’un essai gratuit !
Nous vous invitons également à consulter nos guides sur le scraping d’autres services Google tels que « Google Search Result Data », « Google Trends », « Google Scholar » et « Google Maps ».
Aucune carte de crédit requise