Subida automática de temas XML en Blogger — 0 clics manuales con Playwright + CDP 9222

5 min read · 1,221 words

Consejos prácticos / Gestión de blogs / Python · Automatización
Aprox. 2500 caracteres

Una de las desventajas de Blogger es que cada vez que se cambia el tema XML, se necesitan de 3 a 4 clics en la interfaz de administración ("Tema → Copia de seguridad / Restaurar → Subir"), además de la verificación de inicio de sesión y la espera de la aplicación, lo que toma casi 5 minutos en total. Hemos automatizado esto con Playwright + Chrome CDP en el puerto 9222 para reducirlo a exactamente 0 clics manuales. A continuación, explicamos la motivación, el funcionamiento real, los resultados y el proceso de verificación.

Por qué lo creamos

Durante los períodos de desarrollo activo, las modificaciones del tema ocurren de 5 a 10 veces al día. Si toma 5 minutos cada vez para cambiar una sola línea de color, el grosor de una fuente o la posición de la barra lateral y ver el resultado en vivo, el flujo de trabajo se interrumpe constantemente.

Además, la antigua ruta de "Restaurar tema" de Blogger tiene un activador para el modo clásico de primera generación (como el antiguo nombre del sitio, BTP), por lo que un solo clic erróneo revertía todo el diseño del sitio a la primera generación. Después de experimentar este problema dos veces, bloqueamos permanentemente la ruta de "Restaurar" en nuestro código. El único camino seguro es insertar directamente todo el XML usando setValue en la pantalla de "Editar HTML" (el editor CodeMirror) del panel de administración.

Creamos un módulo automatizado para evitar realizar este proceso manualmente cada vez.

Cómo funciona

La clave de este sistema es que Playwright se conecta (CDP attach) a una instancia de Chrome que el usuario ya tiene abierta en el puerto 9222 para enviarle comandos. No se abre un navegador nuevo desde cero. De esta manera, la sesión de Google permanece activa, lo que permite omitir automáticamente el CAPTCHA y la autenticación de dos factores (2FA).

Pasos:

  1. Verificación de Chrome en el puerto 9222 — Si la respuesta de http://127.0.0.1:9222/json/version es 200, significa que está activo. Si no lo está, se envía una notificación al usuario ("Por favor, abre Chrome en el puerto 9222") a través de Discord. El inicio automático varía según el sistema operativo.
  2. Conexión CDP de Playwright — Una sola línea: playwright.chromium.connect_over_cdp("http://127.0.0.1:9222"). No se abre un nuevo navegador.
  3. Buscar la pestaña de destino — Si ya hay una pestaña abierta con la dirección blogger.com/blog/themes/, se dirige allí. Si no, abre una nueva pestaña.
  4. Clic en el botón "Editar HTML" — Usando un selector de texto o aria-label. Soporta tanto el idioma coreano como el inglés.
  5. Esperar a que se active el editor CodeMirror — Polling hasta que aparezca document.querySelector('.CodeMirror').
  6. Llamar a CodeMirror.setValue(xml) — Se ejecuta directamente dentro del método evaluate de Playwright. No utiliza el portapapeles ni simulación de escritura. Incluso un XML de 50 KB se aplica instantáneamente.
  7. Clic en el botón "Guardar" — Tras guardar, si aparece el mensaje flotante (toast) "Se ha actualizado el tema", el proceso es correcto.
  8. Verificación rápida en vivo (spot check) — Tras esperar 60 segundos, se realiza un fetch a https://blog-url/. Si el comentario centinela del archivo theme.xml (por ejemplo, ) se incluye en la respuesta, se marca como verified=True.

Tiempo promedio de todo el proceso: 30 segundos. 0 clics manuales.

Resultados reales

  • Tiempo de subida por intento: 5 minutos → 30 segundos (90% de reducción)
  • Número acumulado de subidas automáticas: aproximadamente 320 veces desde su implementación
  • Incidentes de regresión al modo clásico de primera generación por error al pulsar "Restaurar": 2 casos antes de la implementación → 0 casos después
  • Casos de fallo: 4 caídas de Chrome en el puerto 9222 / 2 expiraciones de sesión de Google / 1 CAPTCHA. Todos se notificaron al usuario para una recuperación manual.
  • Copia de seguridad: guardado automático de theme.xml.before. antes de cada subida. En caso de una subida errónea, es posible revertir a la versión anterior en menos de 1 segundo.

Como beneficio adicional, han aumentado los experimentos rápidos del tipo "quiero probar a cambiar una línea del tema". Pensar que tomaría 5 minutos cada vez genera dudas, pero con solo 30 segundos, simplemente se hace. Como resultado, las iteraciones de diseño se han vuelto mucho más rápidas.

Métodos de verificación

Realizamos tres tipos de comprobaciones.

Verificación de ida y vuelta (round-trip) del XML — Después de la subida, se vuelve a llamar a getValue() en el CodeMirror de la misma página para confirmar que el valor sea idéntico byte por byte al XML que enviamos. Esta es una red de seguridad para detectar casos en los que el analizador SkinVariables de Blogger realiza un rechazo silencioso (por ejemplo, cuando hay tokens HTML sin procesar dentro de un bloque CDATA). Se detectaron 5 casos de rechazo silencioso de un total de 320 intentos.

Verificación rápida en vivo (spot check) — Espera de 60 segundos después de la subida y posterior fetch del sitio en vivo. Se comprueba si el marcador centinela de theme.xml está incluido en la respuesta. 320/320 aprobados.

Prueba de prevención de regresión al modo clásico de primera generación — Comprobación mediante pruebas unitarias de que el código bloquea cualquier intento deliberado de nuestra automatización de hacer clic en el botón "Restaurar". Siempre pasa la prueba en assert "restore" not in click_targets. El hook de bloqueo funciona correctamente.

Cómo implementarlo

En lugar de copiar todo el módulo, es más práctico extraer las dos líneas clave.

Primero, inicia Chrome en el puerto 9222.


# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" \
 --remote-debugging-port=9222 \
 --user-data-dir=C:\chrome_debug_profile

# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
 --remote-debugging-port=9222 \
 --user-data-dir=$HOME/chrome_debug_profile

A continuación, conéctate con Playwright.


import asyncio
from playwright.async_api import async_playwright

BLOG_ID = "1234567890"
THEME_XML = open("theme.xml", encoding="utf-8").read()

async def upload_theme(xml: str):
 async with async_playwright() as p:
 browser = await p.chromium.connect_over_cdp("http://127.0.0.1:9222")
 ctx = browser.contexts[0]
 page = await ctx.new_page()
 await page.goto(f"https://www.blogger.com/blog/themes/{BLOG_ID}")
 # "Editar el código fuente del tema actual"
 await page.click("text=현재 테마의 소스 코드 수정")
 await page.wait_for_selector(".CodeMirror", timeout=30000)
 await page.evaluate(
 "(xml) => document.querySelector('.CodeMirror').CodeMirror.setValue(xml)",
 xml,
 )
 await page.click("button:has-text('테마 저장')")
 await page.wait_for_selector("text=테마가 업데이트되었습니다", timeout=60000)
 await browser.close()
 print("uploaded")

asyncio.run(upload_theme(THEME_XML))

Aquí, lo fundamental es la línea de connect_over_cdp y la de CodeMirror.setValue. El resto es solo refinar los selectores.

Nunca utilices la ruta de restauración. El botón "Restaurar" se encuentra en la misma página, y ese fue el origen de nuestros incidentes. Si se presiona una vez, el sitio vuelve al diseño clásico de primera generación, rompiendo el diseño en vivo. Para mayor seguridad, es recomendable bloquear explícitamente ese selector en el código de automatización.

En resumen: inicia Chrome en el puerto 9222, conéctate con Playwright y llama a CodeMirror.setValue en una sola línea para automatizar la subida de temas en Blogger. Tras la configuración inicial, todas las actualizaciones futuras se realizarán automáticamente con un solo comando.

Category Coverage Notice

This article follows our label-specific editorial criteria. Details:

ToolSignal Pro Editorial

ToolSignal Pro는 AI·IT·소프트웨어 트렌드를 다루는 종합 IT 인사이트 매거진입니다.

이전 글 다음 글