Publicación indirecta de artículos de ChatGPT, Claude y Gemini en el blog: aprovecha el límite gratuito de los LLM con una sola línea de curl

#185

Consejos prácticos / Gestión de blogs / Python · API Aprox. 2400 caracteres

Al escribir artículos de blog con LLM, el patrón más común es escribir "escribe una guía sobre este tema" en la ventana de chat de ChatGPT o Claude, copiar manualmente el HTML recibido y pegarlo en la interfaz de administración de Blogger. Esto toma unos 5 minutos, y hay que configurar las etiquetas, la meta descripción y las categorías manualmente cada vez. Hemos creado un endpoint de desvío que envía la salida del chat del LLM directamente a un borrador (DRAFT) de Blogger con una sola línea de curl.

Por qué lo creamos

Llamar directamente a las API de los LLM (por ejemplo, Anthropic o Google) acumula costos de tokens, lo que cuesta entre $0.10 y $0.50 por artículo. Para 100 artículos, esto representa entre $10 y $50. Para un blog gestionado por una sola persona, como el nuestro, esto es una carga financiera.

Por otro lado, las suscripciones a ChatGPT Plus, Claude Pro o Gemini Advanced tienen una tarifa plana de $20 al mes. Incluso si escribes 100 artículos al mes, el costo adicional es cero. Sin embargo, el flujo de trabajo de copiar y pegar desde la ventana del chat a Blogger es tan lento que al final terminas volviendo a las llamadas de API.

Solución: Envías el HTML recibido del chat del LLM a un endpoint de publicación de la webapp en una sola línea → pasa por la inyección automática de etiquetas, metadatos y gráficos, y la cadena de hooks de validación SEO → se convierte en un borrador (DRAFT) de Blogger. Lo único que tiene que hacer el usuario es recibir la respuesta en el chat y ejecutar curl una vez.

Con una tarifa plana de $20 al mes, puedes publicar 100 artículos pasando por toda la cadena de hooks de publicación de la webapp (desinfección, control de calidad y 5 canales de indexación).

Cómo funciona

Existe un endpoint independiente dentro de la webapp: POST /api/writer/external-publish.

Estructura de la solicitud (Request shape)

{
 "title": "Título del artículo",
 "content_html": "<p>HTML del cuerpo...</p><h2>Sección</h2>...",
 "label": "Consejos prácticos",
 "post_type": "guide",
 "primary_keyword": "palabra clave",
 "meta_description": "Meta descripción de 100-160 caracteres"
}

Solo tienes que insertar el HTML recibido del chat del LLM directamente en content_html y completar los otros 5 campos.

Procesamiento en el servidor

  1. Autenticación: Limitado a localhost (127.0.0.1). Sin exposición externa.
  2. Normalización de etiquetas (Label normalize): Mapea automáticamente variaciones como ["활용 팁", "사용팁", "tips"] a una de las 6 etiquetas canónicas del sitio. Si no es una etiqueta conocida, responde con {"error":"unknown_label","allowed":["..."]}.
  3. Verificación de HTML: Elimina etiquetas <script> e <iframe>, y convierte automáticamente tablas sin formato (<table>) (hook publish_sanitizer). Incluso si recibiste el contenido en Markdown desde el LLM, se convierte automáticamente a HTML.
  4. Publicación en Blogger: Llama a blogger.publish_post. Pasa por toda la cadena de hooks (inyección de gráficos, SEO de imágenes, tabla de contenidos, tiempo de lectura, biografía del autor, pie de página de IP, pie de página de donaciones, desinfección final y control de calidad). Se fuerza como borrador (DRAFT) (la publicación en vivo requiere permisos adicionales).
  5. Respuesta: {ok: true, post_id, blogger_url, quality_gate: "15/15"}. Resultado de la publicación + puntuación de calidad.

Generación automática de plantillas de prompts

Al llamar a GET /api/writer/external-publish/prompt-template?topic=foo&label=활용+팁, se devuelve un bloque de prompt para el LLM adaptado al tono y la estructura del sitio. Solo tienes que pegarlo directamente en la ventana de chat de ChatGPT o Claude y recibir la respuesta.

Impacto real

  • Costo de la API de LLM: de $0.10-0.50 por artículo × 100 artículos al mes → tarifa plana de $20 al mes (ChatGPT Plus)
  • Tiempo de publicación por artículo (Respuesta del LLM → Borrador de Blogger): de 5 minutos a 30 segundos
  • Tasa de aprobación de la cadena de hooks de publicación: 47 de 47 artículos de LLM externos (promedio de aprobación de 15/15 en publish_quality_gate)
  • Errores de etiquetado incorrecto: promedio de 3 casos al mes antes de la implementación → 0 casos (gracias a la normalización canónica)
  • Patrón de uso más común: Chat en ChatGPT → Copiar respuesta → Una línea de curl en la terminal

Procesar 100 artículos al mes con una sola suscripción a ChatGPT Plus reduce el costo anual de LLM a $240 (suscripción) frente a $1,200-$6,000 (llamadas de API). Para un administrador independiente, esta es una diferencia que no se puede ignorar.

Métodos de validación

Tres tipos de validación:

Tasa de aprobación de la cadena de hooks de publicación

Se registraron todos los resultados de publish_quality_gate tras publicar 47 artículos de LLM externos. 47/47 obtuvieron una puntuación ≥ 90, con un promedio de 95. El hook publish_sanitizer limpia automáticamente el HTML descuidado de la salida del LLM (residuos de Markdown o etiquetas <div> vacías) para cumplir con la puntuación requerida.

Prueba de regresión de normalización de etiquetas

Se implementó un conjunto de pruebas unitarias con un "golden set" de 30 casos (entradas de etiquetas con variaciones). Mapeo exitoso de 30/30 casos, como "tips""활용 팁", "사용팁""활용 팁", "compare""비교", etc. Las etiquetas desconocidas devuelven una respuesta 400.

Control de seguridad (Spot check)

Al llamar al endpoint desde una IP externa, devuelve un error 403. Se fuerza la restricción solo a localhost. 5/5 pruebas aprobadas.

Cómo construirlo

La clave está en una sola función de endpoint de FastAPI.

from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel

app = FastAPI()

LABEL_MAP = {
 "활용 팁": "활용 팁", "tips": "활용 팁", "사용팁": "활용 팁",
 "비교": "비교", "compare": "비교",
 "가이드": "가이드", "howto": "가이드",
 # ... mapeo de etiquetas canónicas del sitio
}

class ExternalPublishBody(BaseModel):
 title: str
 content_html: str
 label: str
 post_type: str = "guide"
 primary_keyword: str = ""
 meta_description: str = ""

@app.post("/api/writer/external-publish")
async def external_publish(body: ExternalPublishBody, request: Request):
 # solo localhost
 client_ip = request.client.host if request.client else ""
 if client_ip not in ("127.0.0.1", "localhost", "::1"):
 raise HTTPException(403, "localhost-only")
 # normalización de etiquetas
 canonical = LABEL_MAP.get(body.label.strip().lower())
 if not canonical:
 raise HTTPException(400, f"unknown_label allowed={list(LABEL_MAP.values())}")
 # reenviar a la cadena de hooks publish_post
 from webapp.routers.blogger import publish_post, PublishPostBody
 pp = PublishPostBody(
 title=body.title,
 content=body.content_html,
 labels=[canonical],
 is_draft=True,
 meta_description=body.meta_description,
 primary_keyword=body.primary_keyword,
 )
 return await publish_post(pp)

Después de recibir el artículo en el chat de ChatGPT o Claude, ejecuta la llamada curl:

curl -X POST http://127.0.0.1:8766/api/writer/external-publish \
 -H "Content-Type: application/json" \
 -d '{
 "title": "Artículo de guía sobre este tema",
 "content_html": "<p>HTML del cuerpo...</p>",
 "label": "Consejos prácticos",
 "meta_description": "Meta de 100-160 caracteres..."
 }'

Respuesta: {"ok": true, "post_id": "1234567...", "blogger_url": "https://..."}

Resumen: Suscripción plana de LLM + endpoint de una sola línea de curl = publicación de 100 artículos al mes pasando por toda la cadena de hooks. Solo toma 30 segundos desde el chat, la respuesta, hasta la publicación. Puedes maximizar la generación de contenido dentro de los límites de presupuesto de un administrador independiente.

ToolSignal Pro Editorial

Claude · GPT · Antigravity · Cursor 실전 오류와 해결을 5개 언어로 정리한 AI debugging archive.

이전 글 다음 글