Python es el lenguaje perfecto para automatizar esas tareas repetitivas que te roban horas cada semana: renombrar archivos, extraer datos de sitios web, enviar correos masivos, interactuar con APIs, generar reportes. En esta guía práctica vas a aprender a automatizar tareas reales con scripts que puedes usar desde hoy mismo.
Trabajo con Python para automatización desde hace años, tanto para proyectos personales como empresariales, y puedo decirte que cada script que escribes te ahorra tiempo exponencialmente. Vamos a construir varios scripts útiles paso a paso.
Requisitos previos
Necesitas Python 3.10+ instalado. Verifica con:
python --version # o python3 --version
pip --version # o pip3 --version
Crea un entorno virtual para mantener las dependencias aisladas (buena práctica que muchos tutoriales ignoran):
# Crear entorno virtual
python -m venv mi_entorno
# Activar (Windows)
mi_entorno\Scripts\activate
# Activar (macOS/Linux)
source mi_entorno/bin/activate
# Instalar las librerías que usaremos
pip install requests beautifulsoup4 openpyxl python-dotenv schedule
1. Automatizar operaciones con archivos
Una de las automatizaciones más útiles es organizar archivos automáticamente. Este script clasifica los archivos de una carpeta por tipo:
import os
import shutil
from pathlib import Path
def organizar_descargas(carpeta_origen):
"""Organiza archivos de una carpeta por tipo/extensión."""
# Mapa de categorías
categorias = {
'Imagenes': ['.jpg', '.jpeg', '.png', '.gif', '.svg', '.webp'],
'Documentos': ['.pdf', '.doc', '.docx', '.txt', '.xlsx', '.csv'],
'Videos': ['.mp4', '.avi', '.mkv', '.mov'],
'Audio': ['.mp3', '.wav', '.flac', '.aac'],
'Codigo': ['.py', '.js', '.html', '.css', '.json', '.sql'],
'Comprimidos': ['.zip', '.rar', '.7z', '.tar', '.gz'],
}
carpeta = Path(carpeta_origen)
archivos_movidos = 0
for archivo in carpeta.iterdir():
# Saltar directorios
if archivo.is_dir():
continue
# Encontrar la categoría correcta
extension = archivo.suffix.lower()
destino = 'Otros'
for categoria, extensiones in categorias.items():
if extension in extensiones:
destino = categoria
break
# Crear carpeta destino si no existe
carpeta_destino = carpeta / destino
carpeta_destino.mkdir(exist_ok=True)
# Mover archivo
shutil.move(str(archivo), str(carpeta_destino / archivo.name))
archivos_movidos += 1
print(f" {archivo.name} -> {destino}/")
print(f"\nTotal: {archivos_movidos} archivos organizados")
# Uso
organizar_descargas(os.path.expanduser("~/Downloads"))
Renombrar archivos en masa
from pathlib import Path
import re
def renombrar_fotos(carpeta, prefijo="foto"):
"""Renombra archivos secuencialmente: foto_001.jpg, foto_002.jpg..."""
carpeta = Path(carpeta)
imagenes = sorted(
[f for f in carpeta.iterdir()
if f.suffix.lower() in ('.jpg', '.jpeg', '.png')],
key=lambda x: x.stat().st_mtime # Ordenar por fecha de modificación
)
for i, imagen in enumerate(imagenes, start=1):
nuevo_nombre = f"{prefijo}_{i:03d}{imagen.suffix.lower()}"
imagen.rename(carpeta / nuevo_nombre)
print(f" {imagen.name} -> {nuevo_nombre}")
print(f"\n{len(imagenes)} archivos renombrados")
renombrar_fotos("./mis_fotos", prefijo="vacaciones_2026")
2. Web Scraping con BeautifulSoup
El web scraping te permite extraer datos de sitios web automáticamente. Usamos BeautifulSoup por su simplicidad:
import requests
from bs4 import BeautifulSoup
import csv
from datetime import datetime
def scrape_noticias_hackernews():
"""Extrae los títulos y enlaces de Hacker News."""
url = "https://news.ycombinator.com/"
headers = {
'User-Agent': 'Mozilla/5.0 (compatible; MiBot/1.0)'
}
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status() # Lanza error si la petición falla
soup = BeautifulSoup(response.text, 'html.parser')
# Encontrar todos los títulos
noticias = []
for item in soup.select('.titleline > a'):
noticias.append({
'titulo': item.text,
'url': item.get('href', ''),
'fecha_extraccion': datetime.now().isoformat()
})
# Guardar en CSV
archivo_csv = f"hackernews_{datetime.now().strftime('%Y%m%d')}.csv"
with open(archivo_csv, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=['titulo', 'url', 'fecha_extraccion'])
writer.writeheader()
writer.writerows(noticias)
print(f"Se extrajeron {len(noticias)} noticias -> {archivo_csv}")
return noticias
scrape_noticias_hackernews()
Importante: Siempre respeta el archivo robots.txt del sitio y no hagas peticiones excesivas. Agrega delays entre requests con time.sleep(1) para no sobrecargar el servidor. Lee más sobre robots.txt y Python.
3. Interactuar con APIs REST
Las APIs son la forma más limpia y legal de obtener datos. Aquí un ejemplo práctico con la API del clima:
import requests
import json
import os
from dotenv import load_dotenv
load_dotenv() # Carga variables de .env
def obtener_clima(ciudad):
"""Obtiene el clima actual de una ciudad usando OpenWeatherMap."""
api_key = os.getenv('OPENWEATHER_API_KEY')
if not api_key:
print("Error: Define OPENWEATHER_API_KEY en tu archivo .env")
return None
url = "https://api.openweathermap.org/data/2.5/weather"
params = {
'q': ciudad,
'appid': api_key,
'units': 'metric',
'lang': 'es'
}
try:
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
datos = response.json()
clima = {
'ciudad': datos['name'],
'temperatura': datos['main']['temp'],
'sensacion': datos['main']['feels_like'],
'humedad': datos['main']['humidity'],
'descripcion': datos['weather'][0]['description'],
'viento': datos['wind']['speed'],
}
print(f"\nClima en {clima['ciudad']}:")
print(f" Temperatura: {clima['temperatura']}°C")
print(f" Sensación térmica: {clima['sensacion']}°C")
print(f" Humedad: {clima['humedad']}%")
print(f" Condición: {clima['descripcion']}")
print(f" Viento: {clima['viento']} m/s")
return clima
except requests.exceptions.HTTPError as e:
print(f"Error HTTP: {e}")
except requests.exceptions.ConnectionError:
print("Error: No hay conexión a internet")
except requests.exceptions.Timeout:
print("Error: La petición tardó demasiado")
return None
obtener_clima("Lima")
obtener_clima("Madrid")
4. Automatizar Excel y CSV
Generar reportes es una de las automatizaciones que más tiempo ahorra en entornos empresariales:
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from datetime import datetime
def generar_reporte_ventas(datos):
"""Genera un reporte de ventas en Excel con formato profesional."""
wb = Workbook()
ws = wb.active
ws.title = "Reporte de Ventas"
# Estilos
header_font = Font(bold=True, color="FFFFFF", size=12)
header_fill = PatternFill(start_color="1e3a5f", end_color="1e3a5f", fill_type="solid")
border = Border(
left=Side(style='thin'),
right=Side(style='thin'),
top=Side(style='thin'),
bottom=Side(style='thin')
)
# Título del reporte
ws.merge_cells('A1:E1')
ws['A1'] = f"Reporte de Ventas - {datetime.now().strftime('%B %Y')}"
ws['A1'].font = Font(bold=True, size=16)
ws['A1'].alignment = Alignment(horizontal='center')
# Encabezados
headers = ['Producto', 'Cantidad', 'Precio Unitario', 'Total', 'Fecha']
for col, header in enumerate(headers, start=1):
cell = ws.cell(row=3, column=col, value=header)
cell.font = header_font
cell.fill = header_fill
cell.alignment = Alignment(horizontal='center')
cell.border = border
# Datos
total_general = 0
for row_num, venta in enumerate(datos, start=4):
total = venta['cantidad'] * venta['precio']
total_general += total
ws.cell(row=row_num, column=1, value=venta['producto']).border = border
ws.cell(row=row_num, column=2, value=venta['cantidad']).border = border
ws.cell(row=row_num, column=3, value=venta['precio']).border = border
ws.cell(row=row_num, column=3).number_format = '$#,##0.00'
ws.cell(row=row_num, column=4, value=total).border = border
ws.cell(row=row_num, column=4).number_format = '$#,##0.00'
ws.cell(row=row_num, column=5, value=venta['fecha']).border = border
# Fila de total
fila_total = len(datos) + 4
ws.cell(row=fila_total, column=3, value="TOTAL:").font = Font(bold=True)
ws.cell(row=fila_total, column=4, value=total_general).font = Font(bold=True, size=12)
ws.cell(row=fila_total, column=4).number_format = '$#,##0.00'
# Ajustar ancho de columnas
for col in ['A', 'B', 'C', 'D', 'E']:
ws.column_dimensions[col].width = 18
# Guardar
archivo = f"reporte_ventas_{datetime.now().strftime('%Y%m%d')}.xlsx"
wb.save(archivo)
print(f"Reporte generado: {archivo}")
return archivo
# Datos de ejemplo
ventas = [
{'producto': 'Laptop Dell', 'cantidad': 5, 'precio': 899.99, 'fecha': '2026-02-01'},
{'producto': 'Monitor 27"', 'cantidad': 12, 'precio': 349.99, 'fecha': '2026-02-05'},
{'producto': 'Teclado mecánico', 'cantidad': 25, 'precio': 79.99, 'fecha': '2026-02-10'},
{'producto': 'Mouse gaming', 'cantidad': 30, 'precio': 49.99, 'fecha': '2026-02-15'},
{'producto': 'Webcam HD', 'cantidad': 8, 'precio': 129.99, 'fecha': '2026-02-20'},
]
generar_reporte_ventas(ventas)
5. Enviar correos automáticos
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import os
from dotenv import load_dotenv
load_dotenv()
def enviar_email(destinatario, asunto, cuerpo_html, adjunto=None):
"""Envía un email con formato HTML y adjunto opcional."""
remitente = os.getenv('EMAIL_USER')
password = os.getenv('EMAIL_PASSWORD')
smtp_server = os.getenv('EMAIL_SMTP', 'smtp.gmail.com')
smtp_port = int(os.getenv('EMAIL_PORT', 587))
msg = MIMEMultipart()
msg['From'] = remitente
msg['To'] = destinatario
msg['Subject'] = asunto
# Cuerpo HTML
msg.attach(MIMEText(cuerpo_html, 'html'))
# Adjuntar archivo (opcional)
if adjunto and os.path.exists(adjunto):
with open(adjunto, 'rb') as f:
parte = MIMEBase('application', 'octet-stream')
parte.set_payload(f.read())
encoders.encode_base64(parte)
parte.add_header(
'Content-Disposition',
f'attachment; filename={os.path.basename(adjunto)}'
)
msg.attach(parte)
# Enviar
try:
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls()
server.login(remitente, password)
server.send_message(msg)
print(f"Email enviado a {destinatario}")
return True
except Exception as e:
print(f"Error enviando email: {e}")
return False
# Uso con Gmail (necesitas un App Password)
enviar_email(
destinatario="cliente@example.com",
asunto="Reporte mensual de ventas",
cuerpo_html="""
Reporte de Febrero 2026
Adjunto encontrará el reporte de ventas del mes.
Saludos cordiales.
""",
adjunto="reporte_ventas_20260226.xlsx"
)
Para Gmail, necesitas generar un App Password específico en lugar de tu contraseña normal.
6. Programar tareas automáticas
Puedes hacer que tus scripts se ejecuten automáticamente usando la librería schedule:
import schedule
import time
def tarea_diaria():
"""Se ejecuta todos los días a las 8:00 AM."""
print(f"Ejecutando tarea diaria...")
# Aquí pones tu lógica: scraping, reportes, emails, etc.
datos = scrape_noticias_hackernews()
print(f"Extraídas {len(datos)} noticias")
def backup_semanal():
"""Se ejecuta los lunes a las 6:00 AM."""
print("Ejecutando backup semanal...")
# Tu lógica de backup
# Programar tareas
schedule.every().day.at("08:00").do(tarea_diaria)
schedule.every().monday.at("06:00").do(backup_semanal)
schedule.every(2).hours.do(lambda: print("Ping cada 2 horas"))
print("Scheduler iniciado. Esperando tareas...")
while True:
schedule.run_pending()
time.sleep(60)
Para producción, es mejor usar cron (Linux/Mac) o Task Scheduler (Windows) en lugar de un script Python corriendo permanentemente. Más robusto y no consume recursos cuando no hay tareas.
Buenas prácticas de automatización
- Usa variables de entorno para credenciales (
.env+python-dotenv). Nunca hardcodees contraseñas en el código. - Maneja errores siempre: Usa
try/excepten operaciones de red, archivos y APIs. Los scripts de automatización deben ser resistentes a fallos. - Agrega logging: Usa el módulo logging de Python en lugar de
print()para scripts de producción. - Usa entornos virtuales: Cada proyecto con su propio
venvevita conflictos de dependencias. - Documenta tus scripts: Un
READMEcon instrucciones de instalación y uso ahorra tiempo futuro. - Respeta los límites: En web scraping, respeta
robots.txty agrega delays entre peticiones. En APIs, no excedas los rate limits.
Próximos pasos
- Selenium: Automatiza navegadores web (llenar formularios, hacer clicks, tomar screenshots).
- asyncio + aiohttp: Para hacer múltiples peticiones HTTP simultáneas (web scraping rápido).
- Pandas: Procesamiento y análisis de datos a gran escala.
- GitHub Actions: Ejecuta tus scripts de Python automáticamente en la nube, gratis.
La automatización con Python es una habilidad que se paga sola. Cada hora que inviertes en escribir un script te ahorra decenas de horas de trabajo manual. Empieza con algo simple — organizar tus descargas, por ejemplo — y ve aumentando la complejidad conforme te sientas cómodo.