5 min read · 1,126 words
Consejos prácticos / Gestión de blogs / Python y automatización
Aprox. 2300 caracteres
Cuando gestionas un blog con más de 200 artículos, es inevitable que se pasen detalles por alto, incluso si una persona revisa el texto manualmente. Hablamos de residuos de Markdown (como negrita que se muestra tal cual), infracciones de la lista blanca de emojis, fuentes omitidas, tablas vacías o restos de estilos de cajas. Por eso, creamos un paso independiente para revisar y corregir automáticamente el artículo justo antes de que se envíe a la API del blog.
En este artículo explicamos con qué intención creamos este sistema de QC automático, cómo funciona, qué resultados reales obtuvimos y cómo lo validamos. Hemos resumido los puntos clave para que cualquier administrador que se enfrente al mismo problema pueda implementarlo con tan solo una página de código.
Por qué lo creamos
Durante el primer año, nos encontramos a menudo con dos tipos de incidentes.
El primero son los residuos de la salida del modelo. Al generar contenido con un LLM, a veces quedaban tokens de Markdown como negrita, ## subtítulo o --- sin convertirse a HTML. En el sitio en vivo, los asteriscos se mostraban tal cual.
El segundo son los casos en los que el texto estaba perfecto justo después de escribirlo, pero algún hook lo estropeaba justo antes de la publicación. Por ejemplo, una función que abría un El punto de control consta de dos etapas. Etapa 1: Sanitize (Saneamiento) — Corrección incondicional Recibe el HTML y aplica lo siguiente de manera uniforme: Esta etapa es un proceso mecánico que no requiere el juicio de una persona. Se diseñó para que produzca el mismo resultado consistente para cualquier artículo. Etapa 2: Quality Gate (Filtro de calidad) — Bloqueo de publicación en caso de fallo Comprueba automáticamente las omisiones que una persona habría detectado. Si no supera esta fase, se rechaza la publicación. Resultados tras 6 meses de implementación: Los 38 artículos bloqueados no se perdieron. Simplemente, el autor se dio cuenta del error, lo corrigió y volvió a intentarlo, logrando que todos se publicaran correctamente. La distribución de los motivos de bloqueo fue: omisión de fuentes (41%), texto demasiado corto (26%), 0 imágenes (21%) y otros motivos (12%). Estas son las validaciones que realizamos tras crear el punto de control: Prueba de regresión con un "Golden Set" — Reunimos los borradores originales de 41 artículos que habían presentado fallos en el pasado para crear un "Golden Set". Comparamos automáticamente si los patrones de error desaparecían en los 41 artículos tras pasarlos por el proceso de sanitize + quality gate. Inicialmente, pasaron 39 de 41. Tras analizar los 2 fallidos, reforzamos las expresiones regulares hasta lograr que pasaran los 41 de 41. Verificación aleatoria en vivo (Spot-check) — Durante la primera semana de aplicación del nuevo sanitize, seleccionamos al azar 8 de los 18 artículos publicados y realizamos un fetch directo de sus páginas en vivo. Comprobamos si aparecía scroll horizontal, si el texto se salía del contenedor o si las imágenes se rompían en dos anchos de pantalla: desktop (1280px) y mobile (360px). El resultado fue 8 de 8 correctos. Idempotencia de doble paso (Double pass) — Verificamos si el resultado de pasar el proceso de sanitize una vez era idéntico al volver a pasarlo por segunda vez. Esta validación sirve para prevenir problemas en caso de que la cadena de hooks de publicación (publish hook chain) se ejecute dos veces. El resultado fue 100 de 100 idénticos. En lugar de copiar todo el código, es mejor que adopte uno o dos puntos clave adaptándolos a su propio entorno. Solo necesita llamar a estas dos funciones en un único punto justo antes de la publicación. Si En resumen, se puede definir en una sola frase: "un único punto de control antes de publicar evita todos los incidentes de forma automática". El tiempo que antes se dedicaba a la revisión manual desaparecerá por completo. Category Coverage Notice This article follows our label-specific editorial criteria. Details:
Cómo funciona
width:800px, margin-left:-30px, position:absolute, etc.)width y height en las etiquetas → Preservación del diseño responsivoX → X, --- arbitrarios → )border, box-shadow o padding>20px)
max-width:100%, overflow-wrap:anywhere)
→ fail (para artículos de tipo guía o comparativos)
Resultados reales
Métodos de validación
Cómo implementarlo
import re
def sanitize_pre_publish(html: str) -> tuple[str, list[str]]:
fixes = []
# Eliminar anchos en línea peligrosos
html, n = re.subn(r'width\s*:\s*(?:[4-9]\d{2}|[1-9]\d{3,})px\s*;?', '', html)
if n: fixes.append('strip_wide_width')
# Residuos de Markdown → HTML
html, n = re.subn(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', html)
if n: fixes.append('md_bold')
# Eliminar emojis (si es necesario)
html, n = re.subn(r'[\U0001F300-\U0001FAFF]', '', html)
if n: fixes.append('strip_emoji')
return html, fixes
def quality_gate(html: str, post_type: str) -> tuple[bool, list[str]]:
fails = []
text = re.sub(r'<[^>]+>', '', html)
if len(text.replace(' ', '')) < 600: fails.append('too_short')
if html.count('<h2') < 3 and post_type in ('howto', 'compare'): fails.append('few_h2')
if '<img' not in html: fails.append('no_image')
if 'TODO' in html or 'REDACTED' in html: fails.append('placeholder')
return (len(fails) == 0), fails
quality_gate devuelve un fallo (fail), detenga la publicación y muestre el motivo al usuario. En cuanto a sanitize, simplemente tome el HTML resultante y envíelo directamente a la API de publicación.