Kurzfassung
Headless Chrome ist ab Chrome 59 verfügbar. Damit kann der Chrome-Browser in einer monitorlosen Umgebung ausgeführt werden. Chrome ohne Chrome auszuführen! Damit stehen alle modernen Webplattformfunktionen von Chromium und der Blink-Rendering-Engine in die Befehlszeile zur Verfügung.
Warum ist das nützlich?
Ein monitorloser Browser ist ein großartiges Tool für automatisierte Tests und Serverumgebungen, in denen Sie keine sichtbare UI-Shell benötigen. Sie können beispielsweise Tests mit einer echten Webseite durchführen, eine PDF-Datei davon erstellen oder einfach prüfen, wie der Browser eine URL rendert.
Monitorlos starten (CLI)
Die einfachste Möglichkeit für den Einstieg in den monitorlosen Modus besteht darin, das Chrome-Binärprogramm über die Befehlszeile zu öffnen. Wenn Sie Chrome 59 oder höher installiert haben, starten Sie Chrome mit dem Flag --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
sollte auf Ihre Installation von Chrome verweisen. Der genaue Ort variiert je nach Plattform. Da ich mit einem Mac bin, habe ich praktische Aliase
für jede installierte Chrome-Version erstellt.
Wenn Sie die stabile Version von Chrome verwenden und die Betaversion nicht erhalten können, empfehlen wir die Verwendung von 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"
Befehlszeilenfunktionen
In einigen Fällen müssen Sie kein programmatisches Script für die monitorlose Chrome-Version erstellen. Es gibt einige nützliche Befehlszeilen-Flags, um gängige Aufgaben auszuführen.
DOM drucken
Das Flag --dump-dom
gibt document.body.innerHTML
in stdout aus:
chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/
PDF erstellen
Das Flag --print-to-pdf
erstellt eine PDF-Datei der Seite:
chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/
Screenshots erstellen
Verwenden Sie das Flag --screenshot
, um einen Screenshot einer Seite zu erstellen:
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/
Bei der Ausführung mit --screenshot
wird im aktuellen Arbeitsverzeichnis eine Datei mit dem Namen screenshot.png
erstellt. Wenn ihr nach ganzseitigen Screenshots sucht, ist die Sache etwas komplizierter. Es gibt einen großartigen Blogpost von
David Schnurr, der Sie behandelt. Weitere Informationen finden Sie unter Die monitorlose Chrome-Version als automatisiertes Screenshot-Tool verwenden .
REPL-Modus (Lese-Eval-Print-Schleife)
Das Flag --repl
wird monitorlos in einem Modus ausgeführt, in dem Sie JS-Ausdrücke im Browser direkt über die Befehlszeile auswerten können:
$ 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
$
Sie beheben Chrome ohne Browser-UI?
Wenn Sie Chrome mit --remote-debugging-port=9222
ausführen, wird eine Instanz mit aktiviertem DevTools-Protokoll gestartet. Das Protokoll wird für die Kommunikation mit Chrome und zum Steuern der monitorlosen Browserinstanz verwendet. Es ist auch das, was Tools wie Sublime, VS Code und Node für das Remote-Debugging einer Anwendung verwenden. #synergy
Da Sie keine Browser-UI zum Anzeigen der Seite haben, rufen Sie http://localhost:9222
in einem anderen Browser auf, um zu prüfen, ob alles funktioniert. Sie sehen dann eine Liste von Inspectable-Seiten, auf die Sie klicken können, um zu sehen, was Headless rendert:
Von hier aus kannst du die bekannten Entwicklertools wie gewohnt verwenden, um die Seite zu untersuchen, zu debuggen und zu optimieren. Wenn Sie Headless programmatisch verwenden, ist diese Seite auch ein leistungsstarkes Debugging-Tool, mit dem alle unformatierten Entwicklertools-Protokollbefehle angezeigt werden, die mit dem Browser kommunizieren.
Programmgesteuert verwenden (Node)
Puppenspieler
Puppeteer ist eine Node-Bibliothek, die vom Chrome-Team entwickelt wurde. Es bietet eine API auf höchster Ebene zur Steuerung der monitorlosen Chrome-Version (oder einer vollständigen Version). Sie ähnelt anderen automatischen Testbibliotheken wie Phantom und NightmareJS, funktioniert jedoch nur mit den neuesten Versionen von Chrome.
Mit Puppeteer können unter anderem ganz einfach Screenshots aufgenommen, PDFs erstellt, Seiten aufgerufen und Informationen über diese Seiten abgerufen werden. Ich empfehle die Bibliothek, wenn du Browsertests schnell automatisieren möchtest. Es verbirgt die Komplexität des Entwicklertools-Protokolls und erledigt redundante Aufgaben wie das Starten einer Fehlerbehebungsinstanz von Chrome.
Installieren:
npm i --save puppeteer
Beispiel: User-Agent drucken
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
console.log(await browser.version());
await browser.close();
})();
Beispiel – Screenshot der Seite erstellen
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();
})();
In der Dokumentation von Puppeteer erfahren Sie mehr über die vollständige API.
CRI-Bibliothek
chrome-remote-interface ist eine untergeordnete Bibliothek als die API von Puppeteer. Diese Vorgehensweise empfiehlt sich, wenn Sie nah an der Metal-Lösung sein und das DevTools-Protokoll direkt verwenden möchten.
Chrome wird gestartet
„chrome-remote-interface“ startet Chrome nicht für Sie, Sie müssen sich also selbst darum kümmern.
Im Abschnitt zur Befehlszeile haben wir Chrome manuell mit --headless --remote-debugging-port=9222
gestartet. Für die vollständige Automatisierung von Tests können Sie Chrome jedoch über Ihre Anwendung erstellen.
Eine Möglichkeit ist die Verwendung von 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) => {
...
});
Wenn Sie jedoch eine mobile Lösung suchen, die auf mehreren Plattformen funktioniert, wird es schwierig. Seht euch einfach den hartcodierten Pfad zu Chrome an :(
ChromeLauncher verwenden
Lighthouse ist ein hervorragendes Tool zum Testen der Qualität Ihrer Web-Apps. Ein robustes Modul für die Einführung von Chrome wurde in Lighthouse entwickelt und wird jetzt für die eigenständige Verwendung extrahiert.
Das NPM-Modul chrome-launcher
ermittelt, wo Chrome installiert ist, richtet eine Debug-Instanz ein, startet den Browser und beendet ihn, wenn das Programm beendet ist. Das Beste daran ist, dass es dank
Node! plattformübergreifend funktioniert.
chrome-launcher
versucht standardmäßig, Chrome Canary zu starten, sofern Chrome Canary installiert ist. Sie können dies jedoch ändern, um manuell auszuwählen, welcher Chrome-Browser verwendet werden soll. Installieren Sie zuerst aus npm, um sie zu verwenden:
npm i --save chrome-launcher
Beispiel – Verwendung von chrome-launcher
zum Starten von 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();
});
Dieses Skript bewirkt nicht viel, aber im Task-Manager sollte eine Chrome-Instanz ausgelöst werden, über die about:blank
geladen wurde. Denken Sie daran, dass es
keine Browser-Benutzeroberfläche gibt. Wir sind monitorlos.
Zur Steuerung des Browsers benötigen wir das DevTools-Protokoll.
Informationen über die Seite abrufen
Installieren wir die Bibliothek:
npm i --save chrome-remote-interface
Beispiele
Beispiel: User-Agent drucken
const CDP = require('chrome-remote-interface');
...
launchChrome().then(async chrome => {
const version = await CDP.Version({port: chrome.port});
console.log(version['User-Agent']);
});
Ergebnisse in etwa: HeadlessChrome/60.0.3082.0
Beispiel – Überprüfen Sie, ob die Website ein Web-App-Manifest hat.
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.
});
})();
Beispiel: Extrahieren Sie die <title>
der Seite mithilfe von DOM APIs.
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.
});
})();
Selenium, WebDriver und ChromeDriver verwenden
Im Moment öffnet Selenium eine vollständige Instanz von Chrome. Es handelt sich also um eine automatisierte Lösung, aber nicht vollständig monitorlos. Selenium kann jedoch mit ein wenig Arbeitsaufwand zur Ausführung von monitorlosem Chrome konfiguriert werden. Ich empfehle Selenium mit monitorlosem Chrome ausführen, wenn Sie eine vollständige Anleitung zur Einrichtung selbst benötigen. Für den Einstieg finden Sie unten einige Beispiele.
ChromeDriver verwenden
ChromeDriver 2.32 verwendet Chrome 61 und funktioniert gut mit monitorlosem Chrome.
Installieren:
npm i --save-dev selenium-webdriver chromedriver
Beispiel:
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();
WebDriverIO verwenden
WebDriverIO ist eine API auf höherer Ebene, die auf Selenium WebDriver basiert.
Installieren:
npm i --save-dev webdriverio chromedriver
Beispiel: CSS-Funktionen auf chromestatus.com filtern
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();
})();
Weitere Ressourcen
Hier sind einige nützliche Ressourcen für den Einstieg:
Docs
- DevTools Protocol Viewer – API-Referenzdokumentation
Tools
- chrome-remote-interface – Knotenmodul, das das Entwicklertools-Protokoll umschließt
- Lighthouse: automatisiertes Tool zum Testen der Qualität von Webanwendungen; verwendet das Protokoll intensiv
- chrome-launcher – Knotenmodul zum Starten von Chrome, bereit für die Automatisierung
Demos
- The Headless Web: Paul Kinlans großer Blogpost zur Verwendung von Headless mit api.ai
Häufig gestellte Fragen
Benötige ich das Flag --disable-gpu
?
Nur unter Windows. Für andere Plattformen ist sie nicht mehr erforderlich. Das Flag --disable-gpu
ist eine vorübergehende Problemumgehung für einige Programmfehler. Dieses Flag wird in zukünftigen Chrome-Versionen nicht mehr benötigt. Weitere Informationen finden Sie unter crbug.com/737678.
Ich brauche also trotzdem Xvfb?
Nein. Da monitorloser Chrome-Browser kein Fenster nutzt, wird ein Anzeigeserver wie Xvfb nicht mehr benötigt. Sie können Ihre automatisierten Tests auch ohne diese Software ausführen.
Was ist Xvfb? Xvfb ist ein In-Memory-Anzeigeserver für Unix-ähnliche Systeme, mit dem Sie grafische Anwendungen wie Chrome ohne angeschlossenes physisches Display ausführen können. Viele Nutzer verwenden Xvfb, um frühere Versionen von Chrome für "monitorlose" Tests auszuführen.
Wie erstelle ich einen Docker-Container, in dem Headless Chrome ausgeführt wird?
Dann sehen Sie sich lighthouse-ci an. Es enthält ein Beispiel-Dockerfile, das node:8-slim
als Basis-Image verwendet und Lighthouse auf der App Engine Flex installiert und ausführt.
Kann ich diese Funktion mit Selenium / WebDriver / ChromeDriver verwenden?
Ja. Weitere Informationen finden Sie unter Selenium, WebDriver und ChromeDriver verwenden.
In welchem Zusammenhang steht dies mit PhantomJS?
Das monitorlose Chrome ähnelt Tools wie PhantomJS. Beide können für automatisierte Tests in einer monitorlosen Umgebung verwendet werden. Der Hauptunterschied zwischen den beiden besteht darin, dass Phantom eine ältere Version von WebKit als Rendering-Engine verwendet, während Headless Chrome die neueste Version von Blink verwendet.
Derzeit bietet Phantom auch eine API auf höherer Ebene als das DevTools-Protokoll.
Wo kann ich Fehler melden?
Fehler in der monitorlosen Chrome-Version können Sie unter crbug.com melden.
Fehler im DevTools-Protokoll können Sie unter github.com/ChromeDevTools/devtools-protocol melden.