# regex-con-python-desde-cero
Regex con Python desde Cero
Volver a la portada del cursoProyecto Final: Análisis de Texto
Sección 4 · Aplicaciones Prácticas
Proyecto final: la bandeja de soporte de PyShop en una tabla
Durante el curso cada herramienta de regex resolvió una parte del caos de la bandeja de soporte: pedidos escritos de tres formas, fechas en tres formatos, teléfonos en cuatro y montos con o sin signo de pesos. En este proyecto se unen todas en un solo proceso: de 600 tickets escritos a mano a una tabla limpia, una versión anonimizada que se puede compartir y un reporte con cifras. Se usa Python 3.11 o superior, el módulo re, collections.Counter y pandas. El notebook proyecto-tickets contiene una solución de referencia completa: consúltalo al terminar, no antes.
Contexto
El equipo de soporte de PyShop quiere saber de qué se quejan los clientes, cuánto dinero está en juego en cada tipo de queja y en qué meses se concentran. Hoy esa información está atrapada en texto libre. Cada ticket tiene tres líneas: el identificador, el remitente y el mensaje:
Ticket T-0002
De: María Gómez <maria.gomez90@ejemplo.org>
Hola, la guía del pedido PS-46421 no se actualiza.
Pagué 4491.00 MXN con efectivo el 2026-06-25.
Mi teléfono es 8116155940.
En la bandeja real el mensaje va en una sola línea; aquí se partió para que quepa.
Datos
La función generar_tickets(n=600, semilla=42) produce la bandeja, siempre igual. Está en la primera celda de código de cualquier notebook del curso, junto con generar_log y la lista MESES; cópiala al inicio de tu notebook. Para clasificar el tema se usan estas palabras clave, revisadas en orden (gana el primer tema que coincide):
TEMAS = {
"envio": r"no ha llegado|retraso|guía",
"devolucion": r"devolver|reembolso|cambiar",
"pago": r"cobraron|rechazado|reflejado",
"danado": r"dañado|roto|faltan",
"factura": r"factura",
}
tickets = generar_tickets()
print(len(tickets)) # 600
Requisitos mínimos
- Patrones con nombre. Define cada patrón una sola vez con
re.compile, en un bloque o módulopatrones.py, con al menos dos pruebasassertpor patrón: una que debe coincidir y otra que no. - Tabla limpia. Un DataFrame con una fila por ticket y las columnas
ticket,cliente,dominio,pedido(normalizado aPS-ddddd),fecha(ISOaaaa-mm-dd),monto(float),metodo,temaytelefono(10 dígitos). Si un ticket no trae el dato, la celda queda vacía (NoneoNaN), nunca con un valor inventado. - Fechas. Convierte los tres formatos (
2026-06-25,28/02/2026y «24 de febrero de 2026») a ISO confullmatchy grupos. - Montos. Extrae el monto que sigue a «Pagué» en sus tres formatos y conviértelo a número.
- Versión anonimizada. Reemplaza cada correo por
***@dominioy cada teléfono por** **** ****, y demuestra con una búsqueda que no queda ninguno. - Calidad de datos. Cuenta los tickets cuyo pedido no viene en el formato oficial
PS-dddddy los pedidos repetidos. - Reporte. Tickets por tema y por mes, monto total por tema, métodos de pago y las palabras más frecuentes del cuerpo (4 letras o más).
Cifras esperadas
Tu solución debe reproducir estos valores:
- 600 tickets, 600 pedidos normalizados y 597 distintos (3 repetidos); 131 tickets traen el pedido con minúsculas o con espacio.
- 488 tickets con fecha, todas convertidas a ISO (0 sin convertir). Por mes: enero 44, febrero 55, marzo 51, abril 43, mayo 39, junio 51, julio 58, agosto 53, septiembre 51 y octubre 43.
- 488 montos, que suman 1,211,689.39 MXN; media 2,482.97 y máximo 4,984.50.
- Métodos de pago: efectivo 151, tarjeta 118, PayPal 115 y transferencia 104.
- 369 tickets con teléfono. Dominios: correo.com 167, ejemplo.org 156, mail.net 139 y pyshop.mx 138.
- Temas: devolución 131, dañado 129, envío 126, factura 117 y pago 97; ningún ticket sin tema.
- Monto por tema: dañado 266,843.12, envío 262,079.44, factura 259,447.61, devolución 255,815.33 y pago 167,503.89.
- Palabras más frecuentes: hola 600, pedido 600, pagué 488, teléfono 369 y efectivo 151.
- Anonimizada: 0 correos y 0 teléfonos restantes.
Si una cifra no coincide, el error casi siempre está en un formato que el patrón no cubre: imprime los tickets en los que la columna quedó vacía.
Pistas de implementación
pandas aplica regex a una columna completa con .str.extract, que devuelve una columna por grupo; los grupos con nombre se convierten en el nombre de la columna:
import pandas as pd
df = pd.DataFrame({"texto": tickets})
num = df["texto"].str.extract(
r"(?i)\bps[- ]?(\d{5})\b", expand=False)
df["pedido"] = "PS-" + num
print(df["pedido"].nunique()) # 597
Para las fechas y los montos conviene una función de Python por formato y .map: un patrón gigante con todas las alternativas es difícil de probar.
Extras opcionales
- Log del servidor. Con
generar_log(), extrae los campos con un patrón de grupos con nombre: las 2000 líneas deben coincidir. Estados esperados: 200 con 1623, 201 con 34, 301 con 93, 404 con 192 y 500 con 58; 45 peticiones tardan más de 1 s. - Cruce con el log. Normaliza las rutas a
/api/pedidos/{id}(232 peticiones GET) y explica por qué no se pueden cruzar con los pedidos de la bandeja: los identificadores del log van de 1 a 500 y los pedidos tienen cinco dígitos. - Validación de calendario. Comprueba cada fecha ISO con
datetime.date.fromisoformat. - Gráfica. Tickets por mes y monto por tema con matplotlib.
Entregables
- Un notebook que corra de principio a fin sin errores, con la estructura: datos, patrones y pruebas, tabla limpia, anonimización, calidad de datos, reporte y conclusiones.
- Dos archivos CSV: la tabla limpia y la versión anonimizada.
- Un resumen de media página para el equipo de soporte: temas principales, monto en juego por tema, meses con más tickets y qué formato de captura conviene exigir en el formulario.
Rúbrica (100 puntos)
- Patrones y pruebas (20 puntos): compilados, con nombre, raw strings y pruebas positivas y negativas.
- Tabla limpia (25 puntos): las nueve columnas, valores vacíos donde falta el dato y cifras esperadas.
- Fechas y montos (15 puntos): los tres formatos de cada uno convertidos sin pérdidas.
- Anonimización (15 puntos): correos y teléfonos reemplazados y verificación de 0 restantes.
- Reporte (15 puntos): tablas por tema, mes, monto y método, y calidad de datos.
- Comunicación (10 puntos): resumen claro, con cifras y recomendaciones concretas.
Los extras suman hasta 10 puntos adicionales y no sustituyen a los requisitos mínimos.