149 lines
5.5 KiB
Python
149 lines
5.5 KiB
Python
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']}") |