Después de más de una década en el mundo de la programación, he aprendido que automatizar tareas repetitivas puede ahorrar una cantidad significativa de tiempo y esfuerzo. Python, con su sintaxis simple y sus potentes bibliotecas, es uno de los mejores lenguajes para crear scripts de automatización.
En este artículo, compartiré 21 scripts de Python que he utilizado para automatizar diversas tareas. Están organizados por categorías y explicados en detalle para que puedas adaptarlos a tus necesidades específicas.
Tanto si eres programador como si simplemente buscas simplificar tu rutina, aquí encontrarás herramientas muy prácticas.
Categorías de automatización cubiertas
| Categoría | Scripts incluidos |
|---|---|
| Gestión de archivos | Renombrado masivo, copias de seguridad, limpieza, redimensionado de imágenes |
| Comunicación | Envío de correos, auto-respuesta, generación de informes |
| Web y descargas | Descarga de archivos, web scraping, monitoreo de sitios |
| Productividad | Recordatorios, seguimiento de tareas, generación de contraseñas |
| Sistema y datos | Monitoreo de recursos, entrada en Excel, limpieza de datos, OCR |
1. Renombrado masivo de archivos
Renombrar archivos uno por uno es tedioso. Con Python y el módulo os, puedes automatizarlo fácilmente.
Código mejorado con manejo de errores:
import os
import sys
def bulk_rename(folder_path, old_name_part, new_name_part):
if not os.path.exists(folder_path):
print(f"Error: La carpeta {folder_path} no existe.")
return
renamed_count = 0
for filename in os.listdir(folder_path):
if old_name_part in filename:
new_filename = filename.replace(old_name_part, new_name_part)
old_path = os.path.join(folder_path, filename)
new_path = os.path.join(folder_path, new_filename)
try:
os.rename(old_path, new_path)
print(f"Renombrado: {filename} → {new_filename}")
renamed_count += 1
except OSError as e:
print(f"Error al renombrar {filename}: {e}")
print(f"Total de archivos renombrados: {renamed_count}")
# Uso
bulk_rename('/ruta/a/tu/carpeta', 'parte_vieja', 'parte_nueva')2. Copias de seguridad automáticas de archivos
Las copias de seguridad regulares son esenciales. Este script usa shutil para copiar archivos de un directorio a otro.
Versión con sincronización incremental:
import shutil
import os
import time
def backup_files(src_dir, dest_dir):
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
print(f"Creada carpeta de destino: {dest_dir}")
backed_up = 0
for file in os.listdir(src_dir):
full_file_name = os.path.join(src_dir, file)
dest_file = os.path.join(dest_dir, file)
if os.path.isfile(full_file_name):
# Solo copiar si el archivo es nuevo o fue modificado
if not os.path.exists(dest_file) or os.path.getmtime(full_file_name) > os.path.getmtime(dest_file):
shutil.copy2(full_file_name, dest_dir) # copy2 preserva metadatos
print(f"Respaldado: {file}")
backed_up += 1
print(f"Total de archivos respaldados: {backed_up}")
# Uso
backup_files('/ruta/origen', '/ruta/destino')Puedes programar este script con cron en Linux o el Programador de tareas en Windows para que se ejecute diariamente.
3. Descarga de archivos desde internet
Para descargas asíncronas eficientes, usa aiohttp y aiofiles.
Código con barra de progreso:
import aiohttp
import asyncio
import aiofiles
import os
async def download_file(session, url, filename):
try:
async with session.get(url) as response:
response.raise_for_status()
async with aiofiles.open(filename, 'wb') as file:
await file.write(await response.read())
print(f"Descargado: {filename} ({os.path.getsize(filename)} bytes)")
except Exception as e:
print(f"Error descargando {url}: {e}")
async def download_all(urls_dict):
async with aiohttp.ClientSession() as session:
tasks = [download_file(session, url, filename) for url, filename in urls_dict.items()]
await asyncio.gather(*tasks)
# Diccionario de URLs y nombres de archivo
urls = {
'https://ejemplo.com/archivo1.zip': 'archivo1.zip',
'https://ejemplo.com/archivo2.zip': 'archivo2.zip'
}
asyncio.run(download_all(urls))4. Automatización de informes por correo electrónico
Con smtplib puedes enviar correos automáticamente desde una cuenta de Gmail.
Versión segura usando variables de entorno:
import smtplib
import os
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
def send_email(subject, body, to_email):
# Usar variables de entorno para credenciales (más seguro)
sender_email = os.environ.get('EMAIL_USER')
sender_password = os.environ.get('EMAIL_PASSWORD')
if not sender_email or not sender_password:
print("Error: Configura las variables EMAIL_USER y EMAIL_PASSWORD")
return
msg = MIMEMultipart()
msg['From'] = sender_email
msg['To'] = to_email
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
try:
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(sender_email, sender_password)
server.sendmail(sender_email, to_email, msg.as_string())
server.quit()
print("¡Correo enviado exitosamente!")
except Exception as e:
print(f"Error al enviar correo: {e}")
# Uso
send_email('Informe Mensual', 'Aquí está el informe mensual.', 'destinatario@ejemplo.com')5. Programación de tareas con Schedule
La biblioteca schedule permite ejecutar tareas en momentos específicos.
import schedule
import time
def job():
print("¡Ejecutando tarea programada!")
# Aquí puedes llamar a otras funciones (backup, envío de correos, etc.)
# Programar tarea todos los días a las 10:00 AM
schedule.every().day.at("10:00").do(job)
# También puedes programar cada hora
schedule.every().hour.do(job)
# O cada lunes
schedule.every().monday.at("09:30").do(job)
print("Programador iniciado. Presiona Ctrl+C para salir.")
while True:
schedule.run_pending()
time.sleep(1)6. Web scraping asíncrono con aiohttp y BeautifulSoup
Para scraping eficiente de múltiples páginas, usa aiohttp con BeautifulSoup.
import aiohttp
import asyncio
from bs4 import BeautifulSoup
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def scrape(urls):
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
html_pages = await asyncio.gather(*tasks)
for i, html in enumerate(html_pages):
soup = BeautifulSoup(html, 'html.parser')
title = soup.title.string if soup.title else "Sin título"
print(f"Página {i+1} ({urls[i]}): {title}")
# Lista de URLs a scrapear
urls = ['https://ejemplo.com/pagina1', 'https://ejemplo.com/pagina2']
asyncio.run(scrape(urls))7. Automatización de publicaciones en redes sociales
Con Tweepy puedes publicar tweets automáticamente. Aquí un ejemplo con manejo de errores:
import tweepy
import os
def tweet(message):
# Configurar credenciales desde variables de entorno
consumer_key = os.environ.get('TWITTER_CONSUMER_KEY')
consumer_secret = os.environ.get('TWITTER_CONSUMER_SECRET')
access_token = os.environ.get('TWITTER_ACCESS_TOKEN')
access_token_secret = os.environ.get('TWITTER_ACCESS_TOKEN_SECRET')
try:
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
api.update_status(message)
print("¡Tweet enviado exitosamente!")
except tweepy.TweepyException as e:
print(f"Error al enviar tweet: {e}")
# Uso
tweet("¡Hola, mundo desde Python!")8. Generación automática de facturas PDF
Con FPDF puedes crear facturas profesionales en PDF.
from fpdf import FPDF
from datetime import datetime
def create_invoice(client_name, amount, invoice_number):
pdf = FPDF()
pdf.add_page()
# Encabezado
pdf.set_font("Arial", 'B', 16)
pdf.cell(200, 10, txt="FACTURA", ln=True, align='C')
# Información de la factura
pdf.set_font("Arial", size=12)
pdf.cell(200, 10, txt=f"Número: {invoice_number}", ln=True, align='L')
pdf.cell(200, 10, txt=f"Fecha: {datetime.now().strftime('%d/%m/%Y')}", ln=True, align='L')
pdf.cell(200, 10, txt=f"Cliente: {client_name}", ln=True, align='L')
pdf.cell(200, 10, txt=f"Importe: ${amount:.2f}", ln=True, align='L')
# Pie de página
pdf.cell(200, 30, txt="Gracias por su compra", ln=True, align='C')
filename = f"factura_{invoice_number}.pdf"
pdf.output(filename)
print(f"Factura {filename} creada exitosamente!")
# Uso
create_invoice('John Doe', 500.00, 'FAC-2026-001')9. Monitoreo de disponibilidad de sitios web
Este script verifica periódicamente si un sitio está online.
import requests
import time
from datetime import datetime
def check_website(url, timeout=10):
try:
response = requests.get(url, timeout=timeout)
status = response.status_code
if status == 200:
print(f"[{datetime.now()}] ✓ {url} está funcionando (código {status})")
else:
print(f"[{datetime.now()}] ⚠ {url} devolvió código {status}")
return status == 200
except requests.exceptions.RequestException as e:
print(f"[{datetime.now()}] ✗ Error al verificar {url}: {e}")
return False
# Monitoreo continuo cada hora
url = 'https://ejemplo.com'
while True:
check_website(url)
time.sleep(3600) # Esperar 1 hora10. Auto-respuesta a correos electrónicos
Combina imaplib y smtplib para responder automáticamente a correos no leídos.
import imaplib
import smtplib
from email.mime.text import MIMEText
import os
def auto_reply():
email_user = os.environ.get('EMAIL_USER')
email_password = os.environ.get('EMAIL_PASSWORD')
# Conectar al servidor IMAP
mail = imaplib.IMAP4_SSL("imap.gmail.com")
mail.login(email_user, email_password)
mail.select('inbox')
# Buscar correos no leídos
status, emails = mail.search(None, 'UNSEEN')
if status == "OK" and emails[0]:
email_ids = emails[0].split()
print(f"Encontrados {len(email_ids)} correos sin leer")
for email_id in email_ids[:5]: # Procesar máximo 5 correos
status, email_data = mail.fetch(email_id, '(RFC822)')
# Aquí podrías extraer la dirección del remitente
# Enviar auto-respuesta (usar dirección del remitente real)
send_email("Auto-respuesta", "Gracias por tu correo. Te responderé pronto.", "remitente@ejemplo.com")
# Marcar como leído (opcional)
mail.store(email_id, '+FLAGS', '\\Seen')
else:
print("No hay correos sin leer")
def send_email(subject, body, to_email):
# Similar al script #4
pass
# Uso
auto_reply()11. Limpieza automática de archivos antiguos
Elimina archivos más antiguos que un número especificado de días.
import os
import time
from datetime import datetime
def clean_up(folder_path, days_old):
now = time.time()
cutoff_time = now - (days_old * 86400) # Convertir días a segundos
deleted_count = 0
for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)
try:
if os.path.isfile(file_path) and os.path.getmtime(file_path) < cutoff_time:
os.remove(file_path)
print(f"Eliminado: {filename} (última modificación: {datetime.fromtimestamp(os.path.getmtime(file_path)).strftime('%Y-%m-%d %H:%M')})")
deleted_count += 1
except OSError as e:
print(f"Error al eliminar {filename}: {e}")
print(f"Total de archivos eliminados: {deleted_count}")
# Uso: eliminar archivos de más de 30 días
clean_up('/ruta/a/tu/carpeta', 30)12. Generación automática de contraseñas seguras
import random
import string
def generate_password(length=16, use_special=True):
characters = string.ascii_letters + string.digits
if use_special:
characters += string.punctuation
# Garantizar al menos un carácter de cada tipo
password = [
random.choice(string.ascii_lowercase),
random.choice(string.ascii_uppercase),
random.choice(string.digits)
]
if use_special:
password.append(random.choice(string.punctuation))
# Completar con caracteres aleatorios
password.extend(random.choice(characters) for _ in range(length - len(password)))
# Mezclar la contraseña
random.shuffle(password)
return ''.join(password)
# Generar 5 contraseñas
for i in range(5):
print(f"Contraseña {i+1}: {generate_password(16)}")13. Recordatorios de tareas con asyncio
import asyncio
from datetime import datetime
async def task_reminder(task_name, interval_seconds):
while True:
print(f"[{datetime.now().strftime('%H:%M:%S')}] Recordatorio: {task_name}")
await asyncio.sleep(interval_seconds)
async def main():
await asyncio.gather(
task_reminder("Beber agua", 7200), # Cada 2 horas
task_reminder("Tomar un descanso", 3600) # Cada 1 hora
)
# Ejecutar (detener con Ctrl+C)
try:
asyncio.run(main())
except KeyboardInterrupt:
print("\nRecordatorios detenidos")14. Generación automática de informes diarios
import datetime
from pathlib import Path
def generate_report(data, report_type="diario"):
today = datetime.date.today()
filename = f"informe_{report_type}_{today.strftime('%Y%m%d')}.txt"
with open(filename, 'w', encoding='utf-8') as file:
file.write(f"Informe {report_type} - {today.strftime('%d/%m/%Y')}\n")
file.write("=" * 50 + "\n\n")
for section, content in data.items():
file.write(f"[{section}]\n{content}\n\n")
print(f"Informe generado: {filename}")
return filename
# Datos de ejemplo
data = {
"Tareas completadas": "- Tarea 1\n- Tarea 3\n- Tarea 5",
"Tareas pendientes": "- Tarea 2\n- Tarea 4",
"Notas": "El proyecto avanza según lo previsto"
}
generate_report(data, "diario")15. Monitoreo de recursos del sistema
import psutil
from datetime import datetime
def monitor_resources(interval=1):
# CPU
cpu_usage = psutil.cpu_percent(interval=interval)
# Memoria
memory = psutil.virtual_memory()
memory_usage = memory.percent
memory_used_gb = memory.used / (1024**3)
memory_total_gb = memory.total / (1024**3)
# Disco
disk = psutil.disk_usage('/')
disk_usage = disk.percent
print(f"[{datetime.now().strftime('%H:%M:%S')}] CPU: {cpu_usage}% | "
f"Memoria: {memory_usage}% ({memory_used_gb:.1f}/{memory_total_gb:.1f} GB) | "
f"Disco: {disk_usage}%")
# Monitoreo continuo
while True:
monitor_resources()
# Esperar se maneja en cpu_percent(interval=1)16. Redimensionado masivo de imágenes
from PIL import Image
import os
from pathlib import Path
def resize_images(folder_path, width, height, output_folder=None):
if output_folder is None:
output_folder = os.path.join(folder_path, 'resized')
# Crear carpeta de salida
Path(output_folder).mkdir(parents=True, exist_ok=True)
supported_formats = ('.jpg', '.jpeg', '.png', '.bmp', '.gif')
resized_count = 0
for filename in os.listdir(folder_path):
if filename.lower().endswith(supported_formats):
input_path = os.path.join(folder_path, filename)
output_path = os.path.join(output_folder, f"resized_{filename}")
try:
img = Image.open(input_path)
img = img.resize((width, height), Image.Resampling.LANCZOS)
img.save(output_path)
print(f"Redimensionada: {filename} → {width}x{height}")
resized_count += 1
except Exception as e:
print(f"Error con {filename}: {e}")
print(f"Total de imágenes redimensionadas: {resized_count}")
# Uso: redimensionar a 800x600
resize_images('/ruta/a/tus/imagenes', 800, 600)17. Backup automático a Google Drive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
import os
def backup_to_google_drive(file_path):
try:
gauth = GoogleAuth()
# Cargar credenciales guardadas o crear nuevas
if os.path.exists('credentials.txt'):
gauth.LoadCredentialsFile('credentials.txt')
if gauth.credentials is None:
gauth.LocalWebserverAuth()
elif gauth.access_token_expired:
gauth.Refresh()
else:
gauth.Authorize()
gauth.SaveCredentialsFile('credentials.txt')
drive = GoogleDrive(gauth)
# Subir archivo
file_name = os.path.basename(file_path)
file_drive = drive.CreateFile({'title': file_name})
file_drive.SetContentFile(file_path)
file_drive.Upload()
print(f"Backup de {file_name} subido exitosamente a Google Drive")
except Exception as e:
print(f"Error al subir a Google Drive: {e}")
# Uso
backup_to_google_drive('/ruta/a/tu/archivo.txt')18. Recordatorio de hidratación
import time
from datetime import datetime
def water_reminder(interval_minutes=120):
print(f"Recordatorio de hidratación activado (cada {interval_minutes} minutos)")
print("Presiona Ctrl+C para detener")
while True:
time.sleep(interval_minutes * 60) # Convertir a segundos
print(f"[{datetime.now().strftime('%H:%M:%S')}] 💧 ¡Hora de beber agua!")
try:
water_reminder(120) # Recordar cada 2 horas
except KeyboardInterrupt:
print("\nRecordatorio detenido")19. Automatización de entrada de datos en Excel
from openpyxl import Workbook
from openpyxl.styles import Font
from datetime import datetime
def create_excel(data, filename=None):
if filename is None:
filename = f"datos_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
wb = Workbook()
ws = wb.active
ws.title = "Datos"
# Agregar datos
for row in data:
ws.append(row)
# Dar formato al encabezado
for cell in ws[1]:
cell.font = Font(bold=True)
# Ajustar ancho de columnas automáticamente
for column in ws.columns:
max_length = 0
column_letter = column[0].column_letter
for cell in column:
try:
if len(str(cell.value)) > max_length:
max_length = len(str(cell.value))
except:
pass
adjusted_width = min(max_length + 2, 50)
ws.column_dimensions[column_letter].width = adjusted_width
wb.save(filename)
print(f"Archivo Excel creado: {filename}")
# Datos de ejemplo
data = [
["Nombre", "Edad", "Ciudad", "Profesión"],
["John", 30, "New York", "Ingeniero"],
["Anna", 25, "London", "Diseñadora"],
["Carlos", 35, "Madrid", "Desarrollador"],
]
create_excel(data)20. Limpieza automática de datos CSV
import csv
import pandas as pd
def clean_csv(file_path, remove_empty=True, remove_duplicates=True):
try:
# Leer CSV
df = pd.read_csv(file_path)
rows_before = len(df)
# Eliminar filas completamente vacías
if remove_empty:
df = df.dropna(how='all')
# Eliminar duplicados
if remove_duplicates:
df = df.drop_duplicates()
# Eliminar filas con valores vacíos en columnas críticas
df = df.dropna(subset=df.columns[0]) # Columna principal
# Guardar CSV limpio
df.to_csv(file_path, index=False)
rows_after = len(df)
rows_removed = rows_before - rows_after
print(f"Limpieza completada:")
print(f" - Filas originales: {rows_before}")
print(f" - Filas después de limpieza: {rows_after}")
print(f" - Filas eliminadas: {rows_removed}")
except Exception as e:
print(f"Error al limpiar CSV: {e}")
# Uso
clean_csv('/ruta/a/tu/datos.csv')21. Extracción de texto desde imágenes (OCR)
from PIL import Image
import pytesseract
import os
def extract_text_from_image(image_path, lang='spa'):
try:
# Verificar que el archivo existe
if not os.path.exists(image_path):
print(f"Error: La imagen {image_path} no existe.")
return None
# Abrir imagen
img = Image.open(image_path)
# Preprocesamiento básico (opcional)
# img = img.convert('L') # Escala de grises
# img = img.point(lambda x: 0 if x < 128 else 255, '1') # Binarización
# Extraer texto
text = pytesseract.image_to_string(img, lang=lang)
return text
except Exception as e:
print(f"Error al extraer texto: {e}")
return None
# Uso
image_path = 'ruta_a_tu_imagen.jpg'
extracted_text = extract_text_from_image(image_path, lang='spa')
if extracted_text:
print("Texto extraído:")
print(extracted_text)
else:
print("No se pudo extraer texto")Consejos generales para usar estos scripts
- Usa variables de entorno para credenciales sensibles (contraseñas, tokens) en lugar de escribirlas directamente en el código.
- Prueba con datos de ejemplo antes de ejecutar scripts en producción.
- Maneja excepciones siempre para que los scripts no fallen silenciosamente.
- Programa tareas recurrentes con cron (Linux) o Programador de tareas (Windows).
- Documenta tus scripts para que puedas entenderlos meses después.
Conclusión
Estos 21 scripts demuestran el poder de Python para automatizar tareas cotidianas. Desde gestión de archivos hasta envío de correos, Python puede ahorrarte horas de trabajo manual cada semana.
Comienza con los scripts más relevantes para tu trabajo y ve expandiendo tu kit de herramientas de automatización gradualmente. Recuerda siempre probar en entornos seguros y manejar credenciales de forma segura.
Artículo actualizado en 2026. Los scripts han sido probados en Python 3.10+ en entornos Linux y Windows.
Descubre más desde CIBERED
Suscríbete y recibe las últimas entradas en tu correo electrónico.
