Scraping the Weather: Build a Python CLI for Real-Time Forecasts

Scraping the Weather: Build a Python CLI for Real-Time Forecasts

Scraping the Weather: Build a Python CLI for Real-Time Forecasts

 

As developers, we often need quick access to live data—like weather—without opening a browser. In this guide, we’ll build a command-line interface (CLI) using Python that fetches real-time weather forecasts using the OpenWeatherMap API. This tool is ideal for terminal users, automation scripts, or for integrating small utilities into larger projects.

1. Setting Up the Environment and OpenWeatherMap API Key

To begin, you’ll need:

  • Python 3 installed
  • An API key from OpenWeatherMap (free tier available)
  • The requests library for making HTTP requests

First, install the required library:

pip install requests

Next, store your API key in an environment variable so you don’t hard-code it:

# Bash example:
export OPENWEATHER_API_KEY="your_api_key_here"

2. Creating the Basic CLI with argparse

We’ll use Python’s built-in argparse to accept city names as CLI arguments. This makes the tool flexible to user input and scriptable.

import argparse

def parse_args():
    parser = argparse.ArgumentParser(description="Get current weather information for a city.")
    parser.add_argument("city", help="City name (e.g., London, Tokyo, New York)")
    return parser.parse_args()

With this setup, we can now run:

python weather_cli.py Paris

3. Fetching Real-Time Data from OpenWeatherMap API

Now, let’s integrate the API. The OpenWeatherMap current weather endpoint is:

https://api.openweathermap.org/data/2.5/weather?q={city}&appid={API_key}&units=metric

Here’s how we make the request and handle basic errors:

import os
import requests

def get_weather(city):
    api_key = os.getenv("OPENWEATHER_API_KEY")
    if not api_key:
        raise EnvironmentError("OPENWEATHER_API_KEY not set.")

    url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
    resp = requests.get(url)

    if resp.status_code != 200:
        raise Exception(f"API request failed: {resp.status_code} - {resp.json().get('message')}")

    return resp.json()

This function returns a parsed JSON object containing temperature, conditions, wind speed, and more.

4. Presenting Weather Data Nicely in the Terminal

Let’s extract and format the relevant information for user-friendly terminal output:

def display_weather(data):
    city = data["name"]
    country = data["sys"]["country"]
    weather = data["weather"][0]["description"].capitalize()
    temp = data["main"]["temp"]
    humidity = data["main"]["humidity"]
    wind_speed = data["wind"]["speed"]

    print(f"\nWeather in {city}, {country}:")
    print(f"  Condition: {weather}")
    print(f"  Temperature: {temp}°C")
    print(f"  Humidity: {humidity}%")
    print(f"  Wind Speed: {wind_speed} m/s\n")

This makes reading the output easier, especially when integrated into scripts or pipelines.

5. Wrapping It All Together

Putting the modules together, here’s a complete runnable script:

import argparse
import requests
import os

def parse_args():
    parser = argparse.ArgumentParser(description="Get current weather info for a city.")
    parser.add_argument("city", help="City name (e.g., Helsinki, Tokyo)")
    return parser.parse_args()

def get_weather(city):
    api_key = os.getenv("OPENWEATHER_API_KEY")
    if not api_key:
        raise EnvironmentError("OPENWEATHER_API_KEY not set.")

    url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}&units=metric"
    resp = requests.get(url)
    if resp.status_code != 200:
        raise Exception(f"API Error: {resp.status_code} - {resp.json().get('message')}")
    return resp.json()

def display_weather(data):
    city = data["name"]
    country = data["sys"]["country"]
    weather = data["weather"][0]["description"].capitalize()
    temp = data["main"]["temp"]
    humidity = data["main"]["humidity"]
    wind_speed = data["wind"]["speed"]

    print(f"\nWeather in {city}, {country}:")
    print(f"  Condition: {weather}")
    print(f"  Temperature: {temp}°C")
    print(f"  Humidity: {humidity}%")
    print(f"  Wind Speed: {wind_speed} m/s\n")

def main():
    args = parse_args()
    data = get_weather(args.city)
    display_weather(data)

if __name__ == '__main__':
    main()

6. Bonus: Tips and Considerations

  • Rate limits: Free API plans limit requests per minute. Avoid spamming the API.
  • Error handling: Consider catching specific errors (e.g., connection errors).
  • Caching: For frequent lookups, consider using a 10-minute cache to reduce API use.
  • Extendability: This CLI can be expanded with forecasts, multiple locations, or background weather logging.

Now you have a lightweight Python CLI that brings weather data directly into your terminal, boosting productivity and demonstrating API integration skills.

Happy hacking!

 

Useful links: