A modo de resumen
Chrome sin interfaz gráfica se envía en Chrome 59. Es una forma de ejecutar el navegador Chrome en un entorno sin interfaz gráfica. Básicamente, ejecutar ¡Chrome sin Chrome! Brinda todas las funciones modernas de la plataforma web por Chromium y el motor de procesamiento Blink en la línea de comandos.
¿Por qué es útil?
Un navegador sin interfaz gráfica es una excelente herramienta para las pruebas automatizadas y entornos de servidor en los que no necesitan una shell de IU visible. Por ejemplo, tal vez quieras ejecutar algunas pruebas una página web real, crear un PDF de ella o simplemente inspeccionar cómo el navegador renderiza una URL.
Cómo iniciar sin interfaz gráfica (CLI)
La forma más sencilla de comenzar a usar el modo sin interfaz gráfica es abrir el objeto binario de Chrome
desde la línea de comandos. Si tienes instalado Chrome 59 o una versión posterior, inicia Chrome con la marca --headless
:
chrome \
--headless \ # Runs Chrome in headless mode.
--disable-gpu \ # Temporarily needed if running on Windows.
--remote-debugging-port=9222 \
https://www.chromestatus.com # URL to open. Defaults to about:blank.
chrome
debería apuntar a tu instalación de Chrome. La ubicación exacta
varían de una plataforma a otra. Como estoy usando Mac, creé alias convenientes
para cada versión de Chrome que instalé.
Si estás en el canal estable de Chrome y no puedes obtener la versión beta, te recomiendo
usando chrome-canary
:
alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
alias chrome-canary="/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary"
alias chromium="/Applications/Chromium.app/Contents/MacOS/Chromium"
Descarga Chrome Canary aquí.
Funciones de la línea de comandos
En algunos casos, es posible que no necesites crear secuencias de comandos de manera programática con Headless Chrome. Hay algunas marcas de línea de comandos útiles para realizar tareas comunes.
Cómo imprimir el DOM
La marca --dump-dom
imprime document.body.innerHTML
en stdout:
chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/
Crea un PDF
La marca --print-to-pdf
crea un PDF de la página:
chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/
Toma capturas de pantalla
Para tomar una captura de pantalla de una página, usa la marca --screenshot
:
chrome --headless --disable-gpu --screenshot https://www.chromestatus.com/
# Size of a standard letterhead.
chrome --headless --disable-gpu --screenshot --window-size=1280,1696 https://www.chromestatus.com/
# Nexus 5x
chrome --headless --disable-gpu --screenshot --window-size=412,732 https://www.chromestatus.com/
Si ejecutas con --screenshot
, se generará un archivo llamado screenshot.png
en el
directorio de trabajo actual. Si buscas capturas de pantalla de página completa,
están un poco más involucrados. Hay un blog excelente
de David Schnurr. Finalizar la compra
Usa Chrome sin interfaz gráfica como herramienta automatizada de captura de pantalla .
Modo REPL (bucle de lectura, evaluación e impresión)
La marca --repl
ejecuta Headless en un modo en el que puedes evaluar expresiones JS
en el navegador, directamente desde la línea de comandos:
$ chrome --headless --disable-gpu --repl --crash-dumps-dir=./tmp https://www.chromestatus.com/
[0608/112805.245285:INFO:headless_shell.cc(278)] Type a Javascript expression to evaluate or "quit" to exit.
>>> location.href
{"result":{"type":"string","value":"https://www.chromestatus.com/features"}}
>>> quit
$
¿Depurar Chrome sin una IU del navegador?
Cuando ejecutas Chrome con --remote-debugging-port=9222
, se inicia una instancia
con el protocolo de Herramientas para desarrolladores habilitado El
se usa para comunicarse con Chrome y conducir la interfaz
de navegador de Google. También es lo que usan herramientas como Sublime, VS Code y Node
depurar de forma remota una aplicación. #synergy
Dado que no tienes la IU del navegador para ver la página, navega a http://localhost:9222
en otro navegador para comprobar que todo funcione correctamente. Verás una lista de
páginas inspeccionables en las que puedes hacer clic para ver qué está renderizando Headless:
Desde aquí, puedes usar las funciones conocidas de Herramientas para desarrolladores para inspeccionar, depurar y ajustar la página como lo harías normalmente. Si usas Headless de manera programática, esta también es una poderosa herramienta de depuración para ver todos los protocolos sin procesar de Herramientas para desarrolladores que pasan por el cable y se comunican con el navegador.
Uso de manera programática (nodo)
Titiritero
Puppeteer es una biblioteca de nodos desarrolladas por el equipo de Chrome. Proporciona una API de alto nivel para controlar (o la versión completa) de Chrome. Es similar a otras bibliotecas de pruebas automatizadas, como Phantom. y NightmareJS, pero solo funciona con las versiones más recientes de Chrome.
Entre otras cosas, Puppeteer se puede utilizar para tomar capturas de pantalla, crear archivos PDF, navegar páginas y recuperar información sobre esas páginas. Recomiendo la biblioteca si quieres automatizar rápidamente las pruebas del navegador. Esconde las complejidades del protocolo de Herramientas para desarrolladores y se encarga de tareas redundantes como iniciar un instancia de depuración de Chrome.
Instálalo:
npm i --save puppeteer
Ejemplo: imprime el usuario-agente.
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
console.log(await browser.version());
await browser.close();
})();
Ejemplo: tomar una captura de pantalla de la página
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.chromestatus.com', {waitUntil: 'networkidle2'});
await page.pdf({path: 'page.pdf', format: 'A4'});
await browser.close();
})();
Consulta la documentación de Puppeteer para obtener más información sobre la API completa.
La biblioteca CRI
chrome-remote-interface es una biblioteca de nivel inferior que la API de Puppeteer. Lo recomiendo si quieres cerca del metal y usar el protocolo de Herramientas para desarrolladores directamente.
Iniciando Chrome
chrome-remote-interface no inicia Chrome por ti, por lo que deberás usar ocuparse de eso tú mismo.
En la sección de la CLI, iniciamos Chrome de forma manual con
--headless --remote-debugging-port=9222
Sin embargo, para automatizar completamente las pruebas, probablemente
deseas generar Chrome desde tu aplicación.
Una forma es usar child_process
:
const execFile = require('child_process').execFile;
function launchHeadlessChrome(url, callback) {
// Assuming MacOSx.
const CHROME = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome';
execFile(CHROME, ['--headless', '--disable-gpu', '--remote-debugging-port=9222', url], callback);
}
launchHeadlessChrome('https://www.chromestatus.com', (err, stdout, stderr) => {
...
});
Pero las cosas se complican si buscas una solución portátil que funcione en múltiples y plataformas de Google Cloud. Solo tienes que ver esa ruta codificada para Chrome :(
Uso de ChromeLauncher
Lighthouse es una maravillosa
para probar la calidad de tus apps web. Un módulo sólido para iniciar
Chrome se desarrolló en Lighthouse y ahora se extrajo para uso independiente.
El módulo chrome-launcher
de NPM
encontrarás dónde
Chrome está instalado, se configura una instancia de depuración, se inicia el navegador y se cierra.
cuando termine el programa. Lo mejor es que funciona en varias plataformas gracias a
¡Nodo!
De forma predeterminada, chrome-launcher
intentará iniciar Chrome Canary (si es
instalada), pero puedes cambiar esta configuración para seleccionar manualmente el Chrome que deseas usar. Para
utilízalo. Primero, instálalo desde npm:
npm i --save chrome-launcher
Ejemplo: Cómo usar chrome-launcher
para iniciar Headless
const chromeLauncher = require('chrome-launcher');
// Optional: set logging level of launcher to see its output.
// Install it using: npm i --save lighthouse-logger
// const log = require('lighthouse-logger');
// log.setLevel('info');
/**
* Launches a debugging instance of Chrome.
* @param {boolean=} headless True (default) launches Chrome in headless mode.
* False launches a full version of Chrome.
* @return {Promise<ChromeLauncher>}
*/
function launchChrome(headless=true) {
return chromeLauncher.launch({
// port: 9222, // Uncomment to force a specific port of your choice.
chromeFlags: [
'--window-size=412,732',
'--disable-gpu',
headless ? '--headless' : ''
]
});
}
launchChrome().then(chrome => {
console.log(`Chrome debuggable on port: ${chrome.port}`);
...
// chrome.kill();
});
Ejecutar esta secuencia de comandos no hace mucho, pero deberías ver una instancia de
Se inicia Chrome en el Administrador de tareas que cargó about:blank
Recuerda que hay
no habrá ninguna IU del navegador. No tenemos interfaz gráfica.
Para controlar el navegador, necesitamos el protocolo de Herramientas para desarrolladores.
Recuperar información sobre la página
Instalemos la biblioteca:
npm i --save chrome-remote-interface
Ejemplos
Ejemplo: imprime el usuario-agente.
const CDP = require('chrome-remote-interface');
...
launchChrome().then(async chrome => {
const version = await CDP.Version({port: chrome.port});
console.log(version['User-Agent']);
});
El resultado es similar a lo siguiente: HeadlessChrome/60.0.3082.0
Ejemplo: Verifica si el sitio tiene un manifiesto de aplicación web
const CDP = require('chrome-remote-interface');
...
(async function() {
const chrome = await launchChrome();
const protocol = await CDP({port: chrome.port});
// Extract the DevTools protocol domains we need and enable them.
// See API docs: https://chromedevtools.github.io/devtools-protocol/
const {Page} = protocol;
await Page.enable();
Page.navigate({url: 'https://www.chromestatus.com/'});
// Wait for window.onload before doing stuff.
Page.loadEventFired(async () => {
const manifest = await Page.getAppManifest();
if (manifest.url) {
console.log('Manifest: ' + manifest.url);
console.log(manifest.data);
} else {
console.log('Site has no app manifest');
}
protocol.close();
chrome.kill(); // Kill Chrome.
});
})();
Ejemplo: Extrae el <title>
de la página usando las APIs del DOM.
const CDP = require('chrome-remote-interface');
...
(async function() {
const chrome = await launchChrome();
const protocol = await CDP({port: chrome.port});
// Extract the DevTools protocol domains we need and enable them.
// See API docs: https://chromedevtools.github.io/devtools-protocol/
const {Page, Runtime} = protocol;
await Promise.all([Page.enable(), Runtime.enable()]);
Page.navigate({url: 'https://www.chromestatus.com/'});
// Wait for window.onload before doing stuff.
Page.loadEventFired(async () => {
const js = "document.querySelector('title').textContent";
// Evaluate the JS expression in the page.
const result = await Runtime.evaluate({expression: js});
console.log('Title of page: ' + result.result.value);
protocol.close();
chrome.kill(); // Kill Chrome.
});
})();
Usa Selenium, WebDriver y ChromeDriver
En este momento, Selenium abre una instancia completa de Chrome. En otras palabras, es una y automatizada, pero no sin interfaz gráfica. Sin embargo, el selenio puede para ejecutar Chrome sin interfaz gráfica con un poco de trabajo. Recomiendo Cómo ejecutar Selenium con Headless Chrome si quieres instrucciones completas para hacerlo tú mismo, pero aquí incluimos algunas ejemplos a continuación para comenzar.
Uso de ChromeDriver
ChromeDriver 2.32 utiliza Chrome 61 y funciona bien con Chrome sin interfaz gráfica.
Instala:
npm i --save-dev selenium-webdriver chromedriver
Ejemplo:
const fs = require('fs');
const webdriver = require('selenium-webdriver');
const chromedriver = require('chromedriver');
const chromeCapabilities = webdriver.Capabilities.chrome();
chromeCapabilities.set('chromeOptions', {args: ['--headless']});
const driver = new webdriver.Builder()
.forBrowser('chrome')
.withCapabilities(chromeCapabilities)
.build();
// Navigate to google.com, enter a search.
driver.get('https://www.google.com/');
driver.findElement({name: 'q'}).sendKeys('webdriver');
driver.findElement({name: 'btnG'}).click();
driver.wait(webdriver.until.titleIs('webdriver - Google Search'), 1000);
// Take screenshot of results page. Save to disk.
driver.takeScreenshot().then(base64png => {
fs.writeFileSync('screenshot.png', new Buffer(base64png, 'base64'));
});
driver.quit();
Cómo usar WebDriverIO
WebDriverIO es una API de nivel superior, además de Selenium WebDriver.
Instala:
npm i --save-dev webdriverio chromedriver
Ejemplo: Filtra las funciones de CSS en chromestatus.com
const webdriverio = require('webdriverio');
const chromedriver = require('chromedriver');
const PORT = 9515;
chromedriver.start([
'--url-base=wd/hub',
`--port=${PORT}`,
'--verbose'
]);
(async () => {
const opts = {
port: PORT,
desiredCapabilities: {
browserName: 'chrome',
chromeOptions: {args: ['--headless']}
}
};
const browser = webdriverio.remote(opts).init();
await browser.url('https://www.chromestatus.com/features');
const title = await browser.getTitle();
console.log(`Title: ${title}`);
await browser.waitForText('.num-features', 3000);
let numFeatures = await browser.getText('.num-features');
console.log(`Chrome has ${numFeatures} total features`);
await browser.setValue('input[type="search"]', 'CSS');
console.log('Filtering features...');
await browser.pause(1000);
numFeatures = await browser.getText('.num-features');
console.log(`Chrome has ${numFeatures} CSS features`);
const buffer = await browser.saveScreenshot('screenshot.png');
console.log('Saved screenshot...');
chromedriver.stop();
browser.end();
})();
Más recursos
A continuación, te presentamos algunos recursos útiles para comenzar:
Documentos
- Visualizador de protocolos de DevOps: Documentos de referencia de la API
Herramientas
- chrome-remote-interface: Nodo que une el protocolo de Herramientas para desarrolladores
- Lighthouse: Es una herramienta automatizada para pruebas. calidad de las apps web; hace un uso intensivo del protocolo
- chrome-launcher módulo de nodo para iniciar Chrome, listo para la automatización
Demostraciones
- “La Web sin interfaz gráfica” - El excelente blog de Paul Kinlan publicaremos sobre el uso de Headless con api.ai.
Preguntas frecuentes
¿Necesito la marca --disable-gpu
?
Solo en Windows. Otras plataformas ya no lo requieren. La marca --disable-gpu
es un
una solución temporal para algunos errores. No necesitarás esta marca en versiones futuras de
Chrome. Consulta crbug.com/737678
para obtener más información.
¿Entonces necesito Xvfb?
No. Headless Chrome no usa una ventana, por lo que un servidor de visualización como Xvfb funciona ya no es necesario. Sin él, puedes ejecutar tus pruebas automatizadas con tranquilidad.
¿Qué es Xvfb? Xvfb es un servidor de visualización en memoria para sistemas similares a Unix que te permite para ejecutar aplicaciones gráficas (como Chrome) sin una pantalla física conectada. Muchas personas utilizan Xvfb para ejecutar versiones anteriores de Chrome para trabajar sin interfaz gráfica. y pruebas.
¿Cómo creo un contenedor de Docker que ejecute Headless Chrome?
Consulta Lighthouse-ci. Tiene un
ejemplo de Dockerfile
que usa node:8-slim
como imagen base, instala +
ejecuta Lighthouse
en App Engine Flex.
¿Puedo usar esta función con Selenium, WebDriver o ChromeDriver?
Sí. Consulta Cómo usar Selenium, WebDriver y ChromeDriver.
¿Cómo se relaciona esto con PhantomJS?
Headless Chrome es similar a herramientas como PhantomJS. Ambas opciones se pueden usar para pruebas automatizadas en un entorno sin interfaz gráfica. La principal diferencia entre ambos es que Phantom usa una versión anterior de WebKit como mientras que Headless Chrome usa la última versión de Blink.
Por el momento, Phantom también ofrece una API de nivel superior que el protocolo de Herramientas para desarrolladores.
¿Dónde puedo informar errores?
Si tienes errores de Headless Chrome, infórmalos en crbug.com.
Si tienes errores en el protocolo de Herramientas para desarrolladores, infórmalos en github.com/ChromeDevTools/devtools-protocol.