TL;DR
Headless Chrome est disponible dans Chrome 59. Il permet d'exécuter le navigateur Chrome dans un environnement headless. En gros, l'exécution Chrome sans Chrome ! Il intègre toutes les fonctionnalités modernes des plates-formes Web fournies par Chromium et le moteur de rendu Blink à la ligne de commande.
En quoi est-ce utile ?
Un navigateur headless est un excellent outil pour les tests automatisés et les environnements de serveur dans lesquels vous n'ont pas besoin d'un shell d'interface utilisateur visible. Par exemple, vous pouvez exécuter des tests sur une vraie page Web, en créer un PDF ou simplement inspecter la façon dont le navigateur affiche une URL.
Démarrage sans interface graphique (CLI)
Pour commencer à utiliser le mode headless, le plus simple est d'ouvrir le fichier binaire Chrome.
depuis la ligne de commande. Si vous avez installé Chrome 59 ou une version ultérieure, démarrez Chrome avec l'indicateur --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
doit renvoyer vers votre installation de Chrome. L'emplacement exact sera
varient d'une plateforme à l'autre. Comme je suis sous Mac, j'ai créé des alias pratiques
pour chaque version de Chrome que j'ai installée.
Si vous utilisez la version stable de Chrome et que vous ne pouvez pas obtenir la version bêta, je vous recommande
à l'aide de 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"
Téléchargez Chrome Canary ici.
Fonctionnalités de la ligne de commande
Dans certains cas, vous n'aurez peut-être pas besoin d'écrire un script pour Chrome sans interface graphique. Il existe des indicateurs de ligne de commande utiles. pour effectuer des tâches courantes.
Imprimer le DOM
L'indicateur --dump-dom
imprime document.body.innerHTML
sur stdout:
chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/
Créer un PDF
L'indicateur --print-to-pdf
crée un PDF de la page:
chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/
Effectuer des captures d'écran
Pour effectuer une capture d'écran d'une page, utilisez l'indicateur --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/
L'exécution avec --screenshot
génère un fichier nommé screenshot.png
dans
répertoire de travail actuel. Si vous recherchez des captures d'écran en pleine page,
sont un peu plus impliquées. Il y a un super blog
de David Schnurr pour vous aider. Départ
Utiliser Headless Chrome comme outil automatisé de capture d'écran :
Mode REPL (boucle lecture-évaluation-impression)
L'option --repl
s'exécute sans interface graphique dans un mode permettant d'évaluer les expressions JS.
dans le navigateur, directement à partir de la ligne de commande:
$ 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
$
Déboguer Chrome sans interface de navigateur ?
Lorsque vous exécutez Chrome avec --remote-debugging-port=9222
, une instance démarre
avec le protocole DevTools activé. La
est utilisé pour communiquer avec Chrome
Compute Engine. C'est aussi ce que des outils comme Sublime, VS Code et Node utilisent pour
pour déboguer une application à distance. #synergy
Comme vous n'avez pas d'interface utilisateur de navigateur pour voir la page, accédez à http://localhost:9222
dans un autre navigateur pour vérifier
que tout fonctionne correctement. Une liste de
des pages Inspectable sur lesquelles vous pouvez cliquer pour voir le rendu Headless:
![Outils de développement distants](https://developer.chrome.com/static/blog/headless-chrome/image/devtools-remote-012fcea42f334.jpg?authuser=19&hl=fr)
Vous pouvez alors utiliser les fonctionnalités familières des outils de développement pour inspecter, déboguer et ajuster la page selon la procédure habituelle. Si vous utilisez la programmation sans interface graphique, cette est également un puissant outil de débogage qui vous permet de voir tous les protocoles bruts des outils de développement des commandes à travers le fil, en communiquant avec le navigateur.
Utiliser de façon automatisée (nœud)
Marionnettiste
Puppeteer est une bibliothèque Node. développés par l'équipe Chrome. Il fournit une API de haut niveau pour contrôler le mode sans interface graphique Chrome (ou complet). Elle est semblable à d'autres bibliothèques de test automatisées comme Phantom. et NightmareJS, mais ne fonctionne qu'avec les dernières versions de Chrome.
Puppeteer permet, entre autres, de faire des captures d'écran, de créer des PDF, naviguer dans les pages et récupérer des informations sur ces pages. Je recommande la bibliothèque pour automatiser rapidement les tests des navigateurs. Elle masque les complexités du protocole DevTools et gère les tâches redondantes, comme le lancement l'instance de débogage de Chrome.
Installez-la:
npm i --save puppeteer
Exemple : imprimer le user-agent
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
console.log(await browser.version());
await browser.close();
})();
Exemple : Faire une capture d'écran de la page
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();
})();
Consultez la documentation de Puppeteer. pour en savoir plus sur l'API complète.
La bibliothèque CRI
chrome-remote-interface est une bibliothèque de niveau inférieur à celui de l'API de Puppeteer. Je le recommande si vous voulez être à proximité du métal et utilisez directement le protocole DevTools.
Lancer Chrome
chrome-remote-interface ne lance pas Chrome. vous en occuper vous-même.
Dans la section CLI, nous avons démarré Chrome manuellement en utilisant
--headless --remote-debugging-port=9222
Toutefois, pour automatiser entièrement les tests,
que vous voulez générer Chrome depuis votre application.
Vous pouvez utiliser 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) => {
...
});
Mais les choses se compliquent si vous voulez une solution portable compatible avec plusieurs plates-formes. Regardez simplement le chemin d'accès codé en dur vers Chrome :(
Utilisation de ChromeLauncher
Lighthouse est une merveille
pour tester la qualité de vos applications Web. Un module efficace pour lancer
Chrome a été développé dans Lighthouse et est désormais extrait pour une utilisation autonome.
Module GPR de chrome-launcher
trouvera
Chrome est installé. Configurez une instance de débogage, lancez le navigateur et fermez-le.
lorsque votre programme est terminé. Cerise sur le gâteau : elle fonctionne
sur plusieurs plates-formes grâce à
Node!
Par défaut, chrome-launcher
tente de lancer Chrome Canary (s'il est
installé), mais vous pouvez modifier cela pour sélectionner manuellement le navigateur Chrome à utiliser. À
l'utiliser, installez d'abord à partir de npm:
npm i --save chrome-launcher
Exemple : Utilisation de chrome-launcher
pour lancer sans interface graphique
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();
});
L'exécution de ce script ne fait pas grand-chose, mais vous devriez voir une instance de
Chrome est lancé dans le gestionnaire de tâches qui a chargé about:blank
. Rappelez-vous, il y a
il n'y aura aucune UI de navigateur. Nous n'avons pas de tête.
Pour contrôler le navigateur, nous avons besoin du protocole DevTools.
Récupérer des informations sur la page
Installons la bibliothèque:
npm i --save chrome-remote-interface
Exemples
Exemple : imprimer le user-agent
const CDP = require('chrome-remote-interface');
...
launchChrome().then(async chrome => {
const version = await CDP.Version({port: chrome.port});
console.log(version['User-Agent']);
});
Vous obtenez un résultat semblable au suivant: HeadlessChrome/60.0.3082.0
Exemple : Vérifier si le site dispose d'un fichier manifeste d'application 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.
});
})();
Exemple : Extrayez le <title>
de la page à l'aide des API 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.
});
})();
Utiliser Selenium, WebDriver et ChromeDriver
Pour le moment, Selenium ouvre une instance complète de Chrome. En d'autres termes, il s'agit automatisée, mais pas complètement headless. Cependant, le sélénium peut être configuré pour exécuter Chrome headless avec un peu de travail. Je recommande Course de Selenium avec Headless Chrome si vous souhaitez que des instructions complètes sur la façon de configurer les choses par vous-même, mais j'ai ici quelques exemples ci-dessous pour vous lancer.
Utiliser ChromeDriver
ChromeDriver 2.32 utilise Chrome 61 et fonctionne bien avec Headless Chrome.
Installer :
npm i --save-dev selenium-webdriver chromedriver
Exemple :
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();
Utiliser WebDriverIO
WebDriverIO est une API de niveau supérieur qui vient compléter Selenium WebDriver.
Installer :
npm i --save-dev webdriverio chromedriver
Exemple: Filtrer les fonctionnalités CSS sur 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();
})();
Autres ressources
Voici quelques ressources utiles pour vous lancer:
Docs
- Lecteur de protocole DevTools : documentation de référence de l'API
Outils
- chrome-remote-interface : nœud qui encapsule le protocole des outils de développement.
- Lighthouse : outil de test automatisé la qualité des applications Web ; fait une utilisation intensive du protocole
- chrome-launcher : module de nœud pour lancer Chrome, prêt pour l'automatisation
Démonstrations
- "The Headless Web" - L'excellent blog de Paul Kinlan comment utiliser Headless avec api.ai.
Questions fréquentes
Ai-je besoin de l'option --disable-gpu
?
Uniquement sous Windows. Les autres plates-formes n'en ont plus besoin. L'option --disable-gpu
est une
une solution temporaire pour
quelques bugs. Vous n'aurez plus besoin de cet indicateur dans les futures versions de
Chrome. Consultez la page crbug.com/737678.
pour en savoir plus.
J'ai toujours besoin de Xvfb ?
Non. Headless Chrome n'utilise pas de fenêtre. Un serveur d'affichage comme Xvfb ne sont plus nécessaires. Sans cela, vous pourrez exécuter vos tests automatisés sans problème.
Qu'est-ce que Xvfb ? Xvfb est un serveur d’affichage en mémoire pour les systèmes de type Unix qui vous permet pour exécuter des applications graphiques (comme Chrome) sans écran physique connecté. De nombreux utilisateurs utilisent Xvfb pour exécuter des versions antérieures de Chrome afin d'effectuer des opérations "headless". tests.
Comment créer un conteneur Docker qui exécute Headless Chrome ?
Regardez lighthouse-ci. Il comporte une
Exemple de Dockerfile
qui utilise node:8-slim
comme image de base, installe +
utilise Lighthouse
sur l'environnement flexible App Engine.
Puis-je l'utiliser avec Selenium / WebDriver / ChromeDriver ?
Oui. Consultez la page Utiliser Selenium, WebDriver et ChromeDriver.
Quel est le lien avec PhantomJS ?
Headless Chrome est semblable à des outils tels que PhantomJS. Les deux pour des tests automatisés dans un environnement sans interface graphique. La principale différence entre les deux est que Phantom utilise une ancienne version de WebKit pour le rendu tandis que Headless Chrome utilise la dernière version de Blink.
Pour le moment, Phantom fournit une API de niveau supérieur à celle du protocole DevTools.
Où puis-je signaler des bugs ?
Si vous rencontrez un bug lié à Chrome sans interface graphique, signalez-le sur crbug.com.
Pour les bugs du protocole des outils de développement, signalez-les à l'adresse github.com/ChromeDevTools/devtools-protocol.