Eventos y depuración
Qué eventos de la página llegan a tu cliente de automatización, cómo capturar de todos modos la salida de la consola y cómo comprobar qué renderizador pinta realmente la página.
Eventos de consola y de errores de página
El motor no reenvía los eventos de consola ni de errores de página a los clientes de automatización, así que page.on("console") y page.on("pageerror") no reciben nada. Es así por diseño: reenviarlos es precisamente lo que mide una sonda de presencia de automatización. Los handlers window.onerror y unhandledrejection dentro de la página se disparan con normalidad, así que, para capturar la salida de la consola, recógela dentro de la página y léela con page.evaluate(). Los SDK de Python y Node muestran un aviso sobre esto una sola vez, al lanzar.
Dos llamadas del driver dependen de esos eventos. page.setContent() de Playwright espera un evento de consola, así que se agota el tiempo de espera (el de Puppeteer funciona): abre el HTML como una URL data: o escríbelo en la página con page.evaluate(). exposeFunction() y exposeBinding(), en Playwright y Puppeteer, funcionan en la página que está abierta cuando las llamas y desaparecen en cuanto esa página navega: llámalas después de la última navegación o devuelve los resultados desde page.evaluate().
from urllib.parse import quote
# Instead of page.set_content(html):
# short HTML: a data: URL (the page gets no origin of its own, so no cookies or storage)
page.goto("data:text/html," + quote(html))
# any HTML: write it into a page you have navigated to; it keeps that page's origin
page.evaluate("html => { document.open(); document.write(html); document.close(); }", html)Comprobación de coherencia del backend de renderizado (checkRenderCoherence)
Una persona puede declarar una GPU, pero si en realidad la página la pinta un rasterizador por software (SwiftShader / llvmpipe, algo habitual en headless sin GPU), un detector estricto puede notarlo. Analiza una página en vivo: la función lee el vendor/renderer de WebGL (sin enmascarar) que la página ve realmente, señala un fallback a rasterizador por software (una señal fatal de headless: activa el canvas bridge o ejecuta en modo headed sobre una GPU real) o un par vendor/renderer incoherente, y devuelve un veredicto estructurado. Pasa la GPU declarada para comprobar también la familia renderizada. Disponible en síncrono, en asíncrono y en Node.
from clearcote import launch, check_render_coherence
browser = launch(fingerprint="seed-123")
page = browser.new_page(); page.goto("about:blank")
verdict = check_render_coherence(page) # {'renderer', 'software_suspected', 'coherent', 'warnings'}
if not verdict["coherent"]:
print(verdict["warnings"]) # e.g. software rasterizer / incoherent GPU family
browser.close()