Automatizacion con Python: Emails, PDFs y Web Scraping Basico
Una de las fortalezas de Python es automatizar tareas repetitivas. En esta leccion aprenderemos a enviar emails, generar PDFs y hacer web scraping basico para extraer datos de sitios web.
Enviar emails con PythonPython incluye el modulo smtplib para enviar emails a traves de SMTP.
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
def enviar_email(destinatario, asunto, cuerpo, remitente, contrasenia):
mensaje = MIMEMultipart('alternative')
mensaje['From'] = remitente
mensaje['To'] = destinatario
mensaje['Subject'] = asunto
parte_texto = MIMEText(cuerpo, 'plain', 'utf-8')
mensaje.attach(parte_texto)
try:
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as servidor:
servidor.login(remitente, contrasenia)
servidor.sendmail(remitente, destinatario, mensaje.as_string())
print(f'Email enviado a {destinatario}')
return True
except Exception as e:
print(f'Error al enviar: {e}')
return False
enviar_email(
destinatario='[email protected]',
asunto='Tu pedido fue confirmado',
cuerpo='Hola! Tu pedido #1234 fue confirmado. Llegara en 2-3 dias.',
remitente='[email protected]',
contrasenia='mi_contrasenia_de_aplicacion'
)
Nota: Para Gmail, necesitas una 'Contrasenia de aplicacion' (no tu contrasenia normal). Ve a Cuenta de Google > Seguridad > Verificacion en dos pasos > Contrasenias de aplicacion.
Enviar email HTML
def enviar_email_html(destinatario, asunto, html_cuerpo, remitente, contrasenia):
mensaje = MIMEMultipart('alternative')
mensaje['From'] = remitente
mensaje['To'] = destinatario
mensaje['Subject'] = asunto
parte_html = MIMEText(html_cuerpo, 'html', 'utf-8')
mensaje.attach(parte_html)
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as servidor:
servidor.login(remitente, contrasenia)
servidor.sendmail(remitente, destinatario, mensaje.as_string())
html = """
<html>
<body>
<h1>Bienvenido!</h1>
<p>Tu cuenta fue creada exitosamente.</p>
<a href="https://ejemplo.com/login">Iniciar sesion</a>
</body>
</html>
"""
enviar_email_html('[email protected]', 'Bienvenido a nuestra plataforma', html, '[email protected]', 'pass')
Enviar emails en lote
import csv
def enviar_campania(archivo_csv, plantilla_asunto, plantilla_cuerpo, remitente, contrasenia):
enviados = 0
errores = 0
with open(archivo_csv, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for contacto in reader:
asunto = plantilla_asunto.format(**contacto)
cuerpo = plantilla_cuerpo.format(**contacto)
if enviar_email(contacto['email'], asunto, cuerpo, remitente, contrasenia):
enviados += 1
else:
errores += 1
print(f'Campania completada: {enviados} enviados, {errores} errores')
plantilla_asunto = 'Hola {nombre}, tenemos una oferta para ti!'
plantilla_cuerpo = 'Hola {nombre},\nTenemos un descuento especial del {descuento}% solo para ti.'
enviar_campania('contactos.csv', plantilla_asunto, plantilla_cuerpo, '[email protected]', 'pass')
Web Scraping basico con requests y BeautifulSoup
El web scraping permite extraer datos de paginas web automaticamente.
# Instalar primero: pip install requests beautifulsoup4
import requests
from bs4 import BeautifulSoup
def obtener_pagina(url):
try:
headers = {'User-Agent': 'Mozilla/5.0'}
respuesta = requests.get(url, headers=headers, timeout=10)
respuesta.raise_for_status() # Error si el status no es 200
return respuesta.text
except requests.RequestException as e:
print(f'Error al obtener {url}: {e}')
return None
def extraer_titulos(html):
soup = BeautifulSoup(html, 'html.parser')
titulos = soup.find_all('h2')
return [t.get_text(strip=True) for t in titulos]
html = obtener_pagina('https://news.ycombinator.com')
if html:
soup = BeautifulSoup(html, 'html.parser')
titulos = soup.select('.titleline > a')
print('Titulos en Hacker News:')
for i, titulo in enumerate(titulos[:5], 1):
print(f'{i}. {titulo.get_text()}')
Extraccion estructurada de datos
def scrape_productos(url):
html = obtener_pagina(url)
if not html:
return []
soup = BeautifulSoup(html, 'html.parser')
productos = []
# Ejemplo generico - adaptar a la estructura HTML real
for item in soup.find_all('div', class_='producto'):
nombre = item.find('h3')
precio = item.find('span', class_='precio')
if nombre and precio:
productos.append({
'nombre': nombre.get_text(strip=True),
'precio': precio.get_text(strip=True)
})
return productos
productos = scrape_productos('https://ejemplo.com/catalogo')
for p in productos:
print(f"{p['nombre']}: {p['precio']}")
Guardar datos scrapeados en CSV
import csv
def scrape_y_guardar(url, archivo_salida):
datos = scrape_productos(url)
if not datos:
print('Sin datos para guardar')
return
with open(archivo_salida, 'w', newline='', encoding='utf-8') as f:
campos = datos[0].keys()
writer = csv.DictWriter(f, fieldnames=campos)
writer.writeheader()
writer.writerows(datos)
print(f'{len(datos)} productos guardados en {archivo_salida}')
scrape_y_guardar('https://ejemplo.com/productos', 'productos_scrapeados.csv')
Automatizacion con el sistema operativo
import os
import shutil
from pathlib import Path
from datetime import datetime
def organizar_descargas(carpeta_origen, carpeta_destino):
origen = Path(carpeta_origen)
destino = Path(carpeta_destino)
destino.mkdir(exist_ok=True)
extensiones = {
'.jpg': 'Imagenes',
'.jpeg': 'Imagenes',
'.png': 'Imagenes',
'.pdf': 'PDFs',
'.doc': 'Documentos',
'.docx': 'Documentos',
'.xlsx': 'Excel',
'.csv': 'Datos',
'.py': 'Python',
'.mp4': 'Videos',
'.mp3': 'Audio',
}
movidos = 0
for archivo in origen.iterdir():
if archivo.is_file():
tipo = extensiones.get(archivo.suffix.lower(), 'Otros')
carpeta_tipo = destino / tipo
carpeta_tipo.mkdir(exist_ok=True)
destino_archivo = carpeta_tipo / archivo.name
if not destino_archivo.exists():
shutil.move(str(archivo), str(destino_archivo))
movidos += 1
print(f'Movido: {archivo.name} -> {tipo}/')
print(f'Total movidos: {movidos} archivos')
organizar_descargas('/Users/usuario/Downloads', '/Users/usuario/Organizado')
Scheduler: Automatizacion programada
# Instalar: pip install schedule
import schedule
import time
from datetime import datetime
def tarea_diaria():
ahora = datetime.now().strftime('%Y-%m-%d %H:%M')
print(f'[{ahora}] Ejecutando tarea diaria...')
# Aqui va tu logica
# generar_reporte()
# enviar_email_resumen()
print('Tarea completada')
def verificar_alertas():
print('Verificando alertas...')
# Logica de alertas
# Programar tareas
schedule.every().day.at('09:00').do(tarea_diaria)
schedule.every(30).minutes.do(verificar_alertas)
print('Scheduler iniciado. Esperando tareas...')
while True:
schedule.run_pending()
time.sleep(60) # Revisar cada minuto
Consideraciones eticas del web scraping
- Revisa el archivo robots.txt del sitio antes de scrapear
- No sobrecarges el servidor con demasiadas peticiones
- Agrega delays entre peticiones (time.sleep(1))
- Respeta los terminos de servicio del sitio
- Muchos sitios prefieren que uses su API oficial si existe
💡 Concepto Clave
Revisemos los puntos más importantes de esta lección antes de continuar.
Resumen
- smtplib permite enviar emails desde Python
- requests descarga el contenido de paginas web
- BeautifulSoup parsea y extrae datos del HTML
- os y shutil automatizan tareas del sistema de archivos
- schedule permite ejecutar tareas en horarios especificos
En la proxima leccion aprenderemos a consumir APIs REST para obtener datos del mundo real.
🧠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.