import requests import json from geopy.geocoders import Nominatim import time def get_weather_by_location(city, state, country="USA"): """ Get weather information from weather.gov based on city, state, and country. Args: city (str): City name state (str): State name or abbreviation country (str): Country name (defaults to "USA" as weather.gov is for US locations) Returns: dict: Weather forecast information """ # Step 1: Get coordinates for the location using geocoding location = f"{city}, {state}, {country}" coordinates = get_coordinates(location) if not coordinates: return {"error": f"Could not find coordinates for {location}"} # Step 2: Get the forecast grid endpoint for the coordinates grid_endpoint = get_grid_endpoint(coordinates) if not grid_endpoint: return {"error": f"Could not find weather grid for coordinates {coordinates}"} # Step 3: Get the forecast data from the grid endpoint forecast = get_forecast(grid_endpoint) return forecast def get_coordinates(location): """Convert a location string to latitude and longitude using Nominatim geocoder.""" try: # Create a geocoder with a meaningful user agent geolocator = Nominatim(user_agent="weather_app_example") # Get the location location_data = geolocator.geocode(location) if location_data: return { "latitude": location_data.latitude, "longitude": location_data.longitude } else: print(f"Location not found: {location}") return None except Exception as e: print(f"Error getting coordinates: {e}") return None def get_grid_endpoint(coordinates): """Get the grid endpoint from weather.gov based on coordinates.""" try: lat = coordinates["latitude"] lon = coordinates["longitude"] # Define headers for the API request headers = { "User-Agent": "WeatherAppExample/1.0 (your_email@example.com)", "Accept": "application/geo+json" } # Make the request to get the grid endpoint url = f"https://api.weather.gov/points/{lat},{lon}" response = requests.get(url, headers=headers) if response.status_code == 200: data = response.json() return data["properties"]["forecast"] else: print(f"Error getting grid: {response.status_code} - {response.text}") return None except Exception as e: print(f"Error in get_grid_endpoint: {e}") return None def get_forecast(grid_endpoint): """Get the forecast data from the grid endpoint.""" try: # Define headers for the API request headers = { "User-Agent": "WeatherAppExample/1.0 (your_email@example.com)", "Accept": "application/geo+json" } # Make the request to get the forecast response = requests.get(grid_endpoint, headers=headers) if response.status_code == 200: data = response.json() # Extract the relevant forecast information periods = data["properties"]["periods"] # Process the forecast data into a simpler format forecast = { "location": data["properties"].get("relativeLocation", {}).get("properties", {}), "updated": data["properties"].get("updated", ""), "periods": [] } for period in periods: forecast["periods"].append({ "name": period.get("name", ""), "temperature": period.get("temperature", ""), "temperatureUnit": period.get("temperatureUnit", ""), "windSpeed": period.get("windSpeed", ""), "windDirection": period.get("windDirection", ""), "shortForecast": period.get("shortForecast", ""), "detailedForecast": period.get("detailedForecast", "") }) return forecast else: print(f"Error getting forecast: {response.status_code} - {response.text}") return {"error": f"API Error: {response.status_code}"} except Exception as e: print(f"Error in get_forecast: {e}") return {"error": f"Exception: {str(e)}"} # Example usage if __name__ == "__main__": city = input("Enter city: ") state = input("Enter state: ") country = input("Enter country (default USA): ") or "USA" print(f"Getting weather for {city}, {state}, {country}...") weather_data = get_weather_by_location(city, state, country) if "error" in weather_data: print(f"Error: {weather_data['error']}") else: print("\nWeather Forecast:") print(f"Location: {weather_data.get('location', {}).get('city', city)}, {weather_data.get('location', {}).get('state', state)}") print(f"Last Updated: {weather_data.get('updated', 'N/A')}") print("\nForecast Periods:") for period in weather_data.get("periods", []): print(f"\n{period['name']}:") print(f" Temperature: {period['temperature']}{period['temperatureUnit']}") print(f" Wind: {period['windSpeed']} {period['windDirection']}") print(f" Forecast: {period['shortForecast']}") print(f" Details: {period['detailedForecast']}")