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:
- Verificación de Chrome en el puerto 9222 — Si la respuesta de
http://127.0.0.1:9222/json/versiones 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. - 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. - 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. - Clic en el botón "Editar HTML" — Usando un selector de texto o aria-label. Soporta tanto el idioma coreano como el inglés.
- Esperar a que se active el editor CodeMirror — Polling hasta que aparezca
document.querySelector('.CodeMirror'). - Llamar a
CodeMirror.setValue(xml)— Se ejecuta directamente dentro del métodoevaluatede Playwright. No utiliza el portapapeles ni simulación de escritura. Incluso un XML de 50 KB se aplica instantáneamente. - Clic en el botón "Guardar" — Tras guardar, si aparece el mensaje flotante (toast) "Se ha actualizado el tema", el proceso es correcto.
- Verificación rápida en vivo (spot check) — Tras esperar 60 segundos, se realiza un
fetchahttps://blog-url/. Si el comentario centinela del archivo theme.xml (por ejemplo,) se incluye en la respuesta, se marca comoverified=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: