Volver al curso

Python Desde Cero

leccion
20 / 21
beginner
20 horas
Python para el Mundo Real

Introduccion a las APIs: Consume Datos del Mundo Real

Lectura
25 min~5 min lectura

Introduccion a las APIs: Consume Datos del Mundo Real

Las APIs (Application Programming Interfaces) son la forma en que las aplicaciones modernas se comunican entre si. Aprender a consumir APIs te abre un universo de datos y funcionalidades: clima, mapas, pagos, redes sociales, inteligencia artificial y mucho mas.

Que es una API REST

Una API REST (Representational State Transfer) es un servicio web que expone datos y funcionalidades a traves de URLs. Las interacciones usan metodos HTTP:

  • GET: Obtener datos
  • POST: Crear datos
  • PUT/PATCH: Actualizar datos
  • DELETE: Eliminar datos

Las respuestas generalmente son en formato JSON.

La libreria requests

Python usa la libreria requests para hacer peticiones HTTP:

# pip install requests
import requests

# Peticion GET simple
respuesta = requests.get('https://api.github.com/users/python')
print(respuesta.status_code)  # 200 = OK
print(respuesta.headers['Content-Type'])  # application/json

datos = respuesta.json()
print(f"Usuario: {datos['login']}")
print(f"Nombre: {datos['name']}")
print(f"Repositorios: {datos['public_repos']}")
Codigos de estado HTTP
Codigo Significado
200 OK
201 Creado
400 Bad Request
401 No autorizado
403 Prohibido
404 No encontrado
429 Demasiadas peticiones
500 Error del servidor
API publica: OpenWeather

Vamos a consumir la API de clima (necesitas registrarte gratis en openweathermap.org):

import requests

API_KEY = 'tu_api_key_aqui'
BASE_URL = 'https://api.openweathermap.org/data/2.5'

def obtener_clima(ciudad, pais='AR'):
    url = f'{BASE_URL}/weather'
    params = {
        'q': f'{ciudad},{pais}',
        'appid': API_KEY,
        'units': 'metric',
        'lang': 'es'
    }
    
    respuesta = requests.get(url, params=params)
    
    if respuesta.status_code == 200:
        datos = respuesta.json()
        return {
            'ciudad': datos['name'],
            'temperatura': datos['main']['temp'],
            'sensacion': datos['main']['feels_like'],
            'descripcion': datos['weather'][0]['description'],
            'humedad': datos['main']['humidity'],
            'viento': datos['wind']['speed']
        }
    elif respuesta.status_code == 404:
        print(f'Ciudad {ciudad} no encontrada')
        return None
    else:
        print(f'Error: {respuesta.status_code}')
        return None

clima = obtener_clima('Buenos Aires')
if clima:
    print(f"Ciudad: {clima['ciudad']}")
    print(f"Temperatura: {clima['temperatura']}C (sensacion {clima['sensacion']}C)")
    print(f"Descripcion: {clima['descripcion']}")
    print(f"Humedad: {clima['humedad']}%")
    print(f"Viento: {clima['viento']} m/s")
Manejo correcto de errores en APIs
def peticion_segura(url, params=None, headers=None):
    try:
        respuesta = requests.get(
            url,
            params=params,
            headers=headers,
            timeout=10  # Timeout de 10 segundos
        )
        respuesta.raise_for_status()  # Lanza excepcion si hay error HTTP
        return respuesta.json()
    
    except requests.exceptions.Timeout:
        print('Tiempo de espera agotado')
    except requests.exceptions.ConnectionError:
        print('Error de conexion')
    except requests.exceptions.HTTPError as e:
        print(f'Error HTTP {e.response.status_code}: {e}')
    except requests.exceptions.JSONDecodeError:
        print('Error al parsear la respuesta JSON')
    
    return None

datos = peticion_segura('https://api.github.com/repos/python/cpython')
if datos:
    print(f"Repositorio: {datos['full_name']}")
    print(f"Stars: {datos['stargazers_count']}")
Autenticacion con APIs

La mayoria de las APIs requieren autenticacion:

# API Key en headers
API_KEY = 'mi_api_key'
headers = {'Authorization': f'Bearer {API_KEY}'}
respuesta = requests.get('https://api.ejemplo.com/datos', headers=headers)

# API Key en parametros URL
respuesta = requests.get(
    'https://api.ejemplo.com/datos',
    params={'api_key': API_KEY}
)

# Autenticacion basica
respuesta = requests.get(
    'https://api.ejemplo.com/datos',
    auth=('usuario', 'contrasenia')
)
Peticiones POST: Enviar datos a una API
def crear_usuario(nombre, email, plan):
    url = 'https://api.ejemplo.com/usuarios'
    headers = {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer mi_token'
    }
    datos = {
        'nombre': nombre,
        'email': email,
        'plan': plan
    }
    
    respuesta = requests.post(url, json=datos, headers=headers)
    
    if respuesta.status_code == 201:
        nuevo_usuario = respuesta.json()
        print(f"Usuario creado con ID: {nuevo_usuario['id']}")
        return nuevo_usuario
    else:
        print(f"Error: {respuesta.status_code} - {respuesta.text}")
        return None

nuevo = crear_usuario('Ana Garcia', '[email protected]', 'premium')
API de JSONPlaceholder (perfecta para practicar)

JSONPlaceholder es una API gratuita y falsa para practicar:

BASE_URL = 'https://jsonplaceholder.typicode.com'

# Obtener posts
def obtener_posts(limite=5):
    params = {'_limit': limite}
    datos = peticion_segura(f'{BASE_URL}/posts', params=params)
    return datos or []

# Obtener usuario
def obtener_usuario(user_id):
    return peticion_segura(f'{BASE_URL}/users/{user_id}')

# Crear post
def crear_post(titulo, cuerpo, user_id):
    url = f'{BASE_URL}/posts'
    datos = {'title': titulo, 'body': cuerpo, 'userId': user_id}
    respuesta = requests.post(url, json=datos)
    return respuesta.json() if respuesta.status_code == 201 else None

# Usar la API
posts = obtener_posts(3)
for post in posts:
    print(f"[{post['id']}] {post['title'][:50]}")

usuario = obtener_usuario(1)
if usuario:
    print(f"Usuario: {usuario['name']} ({usuario['email']})")

nuevo = crear_post('Mi primer post', 'Contenido del post', 1)
if nuevo:
    print(f"Post creado con ID: {nuevo['id']}")
Caso real: Dashboard de datos
import requests
import json
from datetime import datetime

def obtener_tipo_cambio(moneda_origen='USD', moneda_destino='ARS'):
    url = f'https://open.er-api.com/v6/latest/{moneda_origen}'
    datos = peticion_segura(url)
    if datos and datos.get('result') == 'success':
        return datos['rates'].get(moneda_destino)
    return None

def generar_dashboard():
    print('=== DASHBOARD ===', datetime.now().strftime('%Y-%m-%d %H:%M'))
    
    tasa = obtener_tipo_cambio('USD', 'ARS')
    if tasa:
        print(f'USD/ARS: {tasa:.2f}')
    
    clima = obtener_clima('Buenos Aires') if 'obtener_clima' in dir() else None
    if clima:
        print(f"Clima: {clima['temperatura']}C - {clima['descripcion']}")
    
    posts = obtener_posts(3)
    print(f'Ultimos posts: {len(posts)} obtenidos')
    
    print('================')

generar_dashboard()
Guardar respuestas de API en JSON
import json
import requests
from datetime import datetime

def cache_api_response(url, archivo_cache, max_age_horas=1):
    from pathlib import Path
    
    cache = Path(archivo_cache)
    
    if cache.exists():
        datos_cache = json.loads(cache.read_text())
        timestamp = datetime.fromisoformat(datos_cache['timestamp'])
        edad_horas = (datetime.now() - timestamp).total_seconds() / 3600
        
        if edad_horas < max_age_horas:
            print(f'Usando cache (edad: {edad_horas:.1f}h)')
            return datos_cache['datos']
    
    respuesta = requests.get(url)
    datos = respuesta.json()
    
    cache_data = {
        'timestamp': datetime.now().isoformat(),
        'datos': datos
    }
    cache.write_text(json.dumps(cache_data, indent=2))
    print('Datos frescos obtenidos y cacheados')
    return datos

datos = cache_api_response(
    'https://jsonplaceholder.typicode.com/users',
    'usuarios_cache.json',
    max_age_horas=24
)
print(f'Usuarios obtenidos: {len(datos)}')
💡 Concepto Clave

Revisemos los puntos más importantes de esta lección antes de continuar.

Resumen

  • requests.get() para obtener datos de una API
  • requests.post() para enviar datos
  • Usa timeout para evitar que tu programa se quede esperando
  • raise_for_status() para detectar errores HTTP
  • La autenticacion puede ser por Bearer token, API key o Basic auth
  • Guarda respuestas en JSON para evitar llamadas innecesarias

En la proxima y ultima leccion construiremos un proyecto final que integra todo lo aprendido.

🧠 Pon a prueba tu conocimiento
¿Cuál es el aspecto más importante que aprendiste en esta lección?
  • Comprendo el concepto principal y puedo explicarlo con mis palabras
  • Entiendo cómo aplicarlo en mi situación específica
  • Necesito repasar algunas partes antes de continuar
  • Quiero ver más ejemplos prácticos del tema
✅ ¡Excelente! Continúa con la siguiente lección para profundizar más.