""" Intégrateurs de données externes pour AfriDataHub Created by Marino ATOHOUN - AfriDataHub Platform """ import requests import json import logging from datetime import datetime, timedelta from django.conf import settings from django.utils import timezone from datasets.models import Dataset, DataPoint, Alert logger = logging.getLogger('afridatahub') AFRICAN_COUNTRIES = [ 'DZ', 'AO', 'BJ', 'BW', 'BF', 'BI', 'CV', 'CM', 'CF', 'TD', 'KM', 'CG', 'CD', 'DJ', 'EG', 'GQ', 'ER', 'SZ', 'ET', 'GA', 'GM', 'GH', 'GN', 'GW', 'CI', 'KE', 'LS', 'LR', 'LY', 'MG', 'MW', 'ML', 'MR', 'MU', 'MA', 'MZ', 'NA', 'NE', 'NG', 'RW', 'ST', 'SN', 'SC', 'SL', 'SO', 'ZA', 'SS', 'SD', 'TZ', 'TG', 'TN', 'UG', 'ZM', 'ZW' ] class BaseDataIntegrator: """Classe de base pour les intégrateurs de données""" def __init__(self): self.session = requests.Session() self.session.headers.update({ 'User-Agent': 'AfriDataHub/1.0 (https://afridatahub.com)' }) def create_or_update_dataset(self, title, description, domain, source_name, source_url): """Crée ou met à jour un dataset""" dataset, created = Dataset.objects.get_or_create( title=title, defaults={ 'description': description, 'domain': domain, 'source_name': source_name, 'source_url': source_url, 'status': 'active' } ) if not created: dataset.last_updated = timezone.now() dataset.save() return dataset def save_data_point(self, dataset, country, value, date, unit='', extra_info=None): """Sauvegarde un point de données""" if extra_info is None: extra_info = {} data_point, created = DataPoint.objects.update_or_create( dataset=dataset, country=country, date=date, defaults={ 'value': value, 'unit': unit, 'extra_info': extra_info } ) return data_point, created class FAODataIntegrator(BaseDataIntegrator): """Intégrateur pour les données FAO (agriculture)""" def __init__(self): super().__init__() self.base_url = "http://www.fao.org/faostat/api/v1" self.api_key = settings.FAO_API_KEY def fetch_crop_production_data(self): """Récupère les données de production agricole""" try: # Créer le dataset dataset = self.create_or_update_dataset( title="Production agricole africaine (FAO)", description="Données de production des principales cultures en Afrique", domain="agriculture", source_name="FAO", source_url="http://www.fao.org/faostat/" ) # Données d'exemple (en attendant l'API réelle) import random sample_data = [] crops = ['Maïs', 'Blé', 'Cacao', 'Café', 'Riz', 'Manioc'] for country in AFRICAN_COUNTRIES: crop = random.choice(crops) sample_data.append({ 'country': country, 'crop': crop, 'production': random.randint(10000, 5000000), 'date': '2023-01-01' }) created_count = 0 for item in sample_data: date = datetime.strptime(item['date'], '%Y-%m-%d').date() data_point, created = self.save_data_point( dataset=dataset, country=item['country'], value=item['production'], date=date, unit='tonnes', extra_info={'crop': item['crop']} ) if created: created_count += 1 logger.info(f"FAO: {created_count} nouveaux points de données créés") return created_count except Exception as e: logger.error(f"Erreur lors de l'intégration FAO: {str(e)}") return 0 class WorldBankDataIntegrator(BaseDataIntegrator): """Intégrateur pour les données de la Banque Mondiale""" def __init__(self): super().__init__() self.base_url = "https://api.worldbank.org/v2" def fetch_economic_indicators(self): """Récupère les indicateurs économiques""" try: # Dataset PIB gdp_dataset = self.create_or_update_dataset( title="PIB par habitant (Banque Mondiale)", description="Produit Intérieur Brut par habitant des pays africains", domain="economy", source_name="Banque Mondiale", source_url="https://data.worldbank.org/" ) # Dataset Énergie energy_dataset = self.create_or_update_dataset( title="Accès à l'électricité (Banque Mondiale)", description="Pourcentage de la population ayant accès à l'électricité", domain="energy", source_name="Banque Mondiale", source_url="https://data.worldbank.org/" ) # Données d'exemple import random gdp_data = [] energy_data = [] for country in AFRICAN_COUNTRIES: gdp_data.append({ 'country': country, 'gdp_per_capita': random.randint(500, 15000), 'date': '2023-01-01' }) energy_data.append({ 'country': country, 'electricity_access': random.randint(10, 100), 'date': '2023-01-01' }) created_count = 0 # Sauvegarder les données PIB for item in gdp_data: date = datetime.strptime(item['date'], '%Y-%m-%d').date() data_point, created = self.save_data_point( dataset=gdp_dataset, country=item['country'], value=item['gdp_per_capita'], date=date, unit='USD' ) if created: created_count += 1 # Sauvegarder les données d'énergie for item in energy_data: date = datetime.strptime(item['date'], '%Y-%m-%d').date() data_point, created = self.save_data_point( dataset=energy_dataset, country=item['country'], value=item['electricity_access'], date=date, unit='%' ) if created: created_count += 1 logger.info(f"World Bank: {created_count} nouveaux points de données créés") return created_count except Exception as e: logger.error(f"Erreur lors de l'intégration World Bank: {str(e)}") return 0 class WHODataIntegrator(BaseDataIntegrator): """Intégrateur pour les données OMS (santé)""" def __init__(self): super().__init__() self.base_url = "https://ghoapi.azureedge.net/api" def fetch_health_indicators(self): """Récupère les indicateurs de santé""" try: # Dataset Espérance de vie life_expectancy_dataset = self.create_or_update_dataset( title="Espérance de vie (OMS)", description="Espérance de vie à la naissance dans les pays africains", domain="health", source_name="OMS", source_url="https://www.who.int/" ) # Dataset Mortalité infantile infant_mortality_dataset = self.create_or_update_dataset( title="Mortalité infantile (OMS)", description="Taux de mortalité infantile pour 1000 naissances vivantes", domain="health", source_name="OMS", source_url="https://www.who.int/" ) # Données d'exemple import random life_expectancy_data = [] infant_mortality_data = [] for country in AFRICAN_COUNTRIES: life_expectancy_data.append({ 'country': country, 'life_expectancy': round(random.uniform(50, 80), 1), 'date': '2023-01-01' }) infant_mortality_data.append({ 'country': country, 'infant_mortality': random.randint(10, 100), 'date': '2023-01-01' }) created_count = 0 # Sauvegarder les données d'espérance de vie for item in life_expectancy_data: date = datetime.strptime(item['date'], '%Y-%m-%d').date() data_point, created = self.save_data_point( dataset=life_expectancy_dataset, country=item['country'], value=item['life_expectancy'], date=date, unit='années' ) if created: created_count += 1 # Sauvegarder les données de mortalité infantile for item in infant_mortality_data: date = datetime.strptime(item['date'], '%Y-%m-%d').date() data_point, created = self.save_data_point( dataset=infant_mortality_dataset, country=item['country'], value=item['infant_mortality'], date=date, unit='pour 1000' ) if created: created_count += 1 logger.info(f"WHO: {created_count} nouveaux points de données créés") return created_count except Exception as e: logger.error(f"Erreur lors de l'intégration WHO: {str(e)}") return 0 class WeatherDataIntegrator(BaseDataIntegrator): """Intégrateur pour les données météorologiques""" def __init__(self): super().__init__() self.api_key = settings.OPENWEATHER_API_KEY self.base_url = "https://api.openweathermap.org/data/2.5" def fetch_weather_data(self): """Récupère les données météorologiques actuelles""" try: # Dataset Température temperature_dataset = self.create_or_update_dataset( title="Température moyenne (OpenWeatherMap)", description="Température moyenne quotidienne dans les capitales africaines", domain="weather", source_name="OpenWeatherMap", source_url="https://openweathermap.org/" ) # Dataset Précipitations rainfall_dataset = self.create_or_update_dataset( title="Précipitations (OpenWeatherMap)", description="Précipitations quotidiennes dans les capitales africaines", domain="weather", source_name="OpenWeatherMap", source_url="https://openweathermap.org/" ) # Données d'exemple (simulation météo) import random created_count = 0 today = timezone.now().date() for country in AFRICAN_COUNTRIES: # Température simulée temp = random.uniform(15, 35) # Entre 15 et 35°C data_point, created = self.save_data_point( dataset=temperature_dataset, country=country, value=round(temp, 1), date=today, unit='°C' ) if created: created_count += 1 # Précipitations simulées rainfall = random.uniform(0, 20) # Entre 0 et 20mm data_point, created = self.save_data_point( dataset=rainfall_dataset, country=country, value=round(rainfall, 1), date=today, unit='mm' ) if created: created_count += 1 logger.info(f"Weather: {created_count} nouveaux points de données créés") return created_count except Exception as e: logger.error(f"Erreur lors de l'intégration Weather: {str(e)}") return 0 def run_all_integrators(): """Exécute tous les intégrateurs de données""" total_created = 0 integrators = [ FAODataIntegrator(), WorldBankDataIntegrator(), WHODataIntegrator(), WeatherDataIntegrator(), ] for integrator in integrators: try: if hasattr(integrator, 'fetch_crop_production_data'): total_created += integrator.fetch_crop_production_data() elif hasattr(integrator, 'fetch_economic_indicators'): total_created += integrator.fetch_economic_indicators() elif hasattr(integrator, 'fetch_health_indicators'): total_created += integrator.fetch_health_indicators() elif hasattr(integrator, 'fetch_weather_data'): total_created += integrator.fetch_weather_data() except Exception as e: logger.error(f"Erreur avec l'intégrateur {integrator.__class__.__name__}: {str(e)}") logger.info(f"Total: {total_created} nouveaux points de données créés") return total_created