Kurzfassung
Headless Chrome wird in Chrome 59 eingeführt. Damit lässt sich der Chrome-Browser in einer monitorlosen Umgebung ausführen. Chrome ohne Chrome auszuführen. Damit werden alle modernen Webplattformfunktionen, die von Chromium und der Blink-Rendering-Engine bereitgestellt werden, über die Befehlszeile bereitgestellt.
Warum ist das nützlich?
Ein monitorloser Browser ist ein hervorragendes Tool für automatisierte Tests und Serverumgebungen, in denen Sie keine sichtbare UI-Shell benötigen. Sie können beispielsweise Tests für eine echte Webseite durchführen, eine PDF-Datei davon erstellen oder einfach prüfen, wie der Browser eine URL rendert.
Monitorlos starten (CLI)
Am einfachsten starten Sie den monitorlosen Modus, indem Sie die Chrome-Binärdatei über die Befehlszeile ö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 Standort variiert
je nach Plattform. Auf dem Mac habe ich für jede installierte
Chrome-Version einen Alias erstellt.
Wenn Sie die stabile Version von Chrome verwenden und die Betaversion nicht nutzen 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"
Hier können Sie Chrome Canary herunterladen.
Befehlszeilenfunktionen
In einigen Fällen ist ein programmatisches Scripting von Headless Chrome nicht erforderlich. Für häufige Aufgaben stehen einige nützliche Befehlszeilen-Flags zur Verfügung.
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
Mit dem Flag --print-to-pdf
wird eine PDF-Datei der Seite erstellt:
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 Ausführung mit --screenshot
wird im aktuellen Arbeitsverzeichnis eine Datei mit dem Namen screenshot.png
erstellt. Wenn Sie Screenshots der ganzen Seite benötigen, ist die Sache ein bisschen komplizierter. Es gibt einen tollen Blogbeitrag von
David Schnurr, über den Sie informiert wurden. Weitere Informationen finden Sie unter Headless Chrome als automatisiertes Screenshot-Tool verwenden .
REPL-Modus (Read-Eval-Print-Schleife)
Das Flag --repl
wird „headless“ 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
$
Fehlerbehebung in Chrome ohne Browser-Benutzeroberfläche?
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 die Steuerung der monitorlosen Browserinstanz verwendet. Es wird auch von Tools wie Sublime, VS Code und Node verwendet, um das Debugging einer Anwendung per Fernzugriff auszuführen. #synergy
Da Sie keine Browser-UI haben, um die Seite anzusehen, rufen Sie http://localhost:9222
in einem anderen Browser auf und prüfen Sie, ob alles funktioniert. Sie sehen eine Liste von Inspectable-Seiten, auf die Sie klicken können, um zu sehen, was „Headless“ rendert:
Von hier aus können Sie die bekannten Entwicklertools verwenden, um die Seite wie gewohnt zu untersuchen, zu debuggen und zu optimieren. Wenn Sie Headless programmatisch verwenden, ist diese Seite auch ein leistungsstarkes Debugging-Tool, mit dem Sie alle unformatierten Befehle des DevTools-Protokolls über die Leitung übertragen und mit dem Browser kommunizieren können.
Programmatisch verwenden (Node)
Puppenspieler
Puppeteer ist eine vom Chrome-Team entwickelte Knotenbibliothek. Es bietet eine allgemeine API zur Steuerung der monitorlosen oder vollständigen Chrome-Version. Es ähnelt anderen automatisierten Testbibliotheken wie Phantom und NightmareJS, funktioniert jedoch nur mit den neuesten Versionen von Chrome.
Mit Puppeteer können Sie unter anderem ganz einfach Screenshots erstellen, PDFs erstellen, durch Seiten navigieren und Informationen zu diesen Seiten abrufen. Ich empfehle die Bibliothek, wenn Sie Browsertests schnell automatisieren möchten. Er verbirgt die Komplexität des DevTools-Protokolls und übernimmt redundante Aufgaben wie das Starten einer Debug-Instanz von Chrome.
Installieren:
npm i --save puppeteer
Beispiel – User-Agent ausgeben
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();
})();
Sehen Sie sich die Puppeteer-Dokumentation an, um mehr über die vollständige API zu erfahren.
CRI-Bibliothek
chrome-remote-interface ist eine untergeordnete Bibliothek als die API von Puppeteer. Ich empfehle es, wenn Sie nah am Metal arbeiten und das DevTools-Protokoll direkt verwenden möchten.
Chrome wird gestartet
Chrome wird nicht von "chrome-remote-interface" gestartet, in diesem Fall müssen Sie das selbst erledigen.
Im Befehlszeilenabschnitt haben wir mit --headless --remote-debugging-port=9222
Chrome manuell gestartet. Um Tests jedoch vollständig zu automatisieren, empfiehlt es sich, Chrome aus Ihrer Anwendung zu generieren.
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 portable Lösung benötigen, die auf mehreren Plattformen funktioniert, wird es komplizierter. Werfen Sie einfach einen Blick auf diesen hartcodierten Pfad zu Chrome.
ChromeLauncher verwenden
Lighthouse ist ein hervorragendes Tool zum Testen der Qualität Ihrer Webanwendungen. In Lighthouse wurde ein robustes Modul zum Starten von Chrome entwickelt, das jetzt für die eigenständige Verwendung extrahiert wird.
Das NPM-Modul chrome-launcher
ermittelt, wo Chrome installiert ist, richtet eine Debug-Instanz ein, startet den Browser und beendet ihn nach Abschluss des Programms. Das Beste daran ist, dass es dank Node plattformübergreifend funktioniert.
chrome-launcher
versucht standardmäßig, Chrome Canary zu starten (sofern installiert). Sie können dies aber ändern, um manuell auszuwählen, welche Chrome-Version verwendet werden soll. Installieren Sie zuerst von npm aus, um es zu verwenden:
npm i --save chrome-launcher
Beispiel: Headless mit chrome-launcher
starten
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();
});
Das Ausführen dieses Skripts führt nicht viel dazu, aber Sie sollten sehen, dass im Task-Manager eine Instanz von Chrome gestartet wird, die about:blank
geladen hat. Denken Sie daran, dass es
keine Browser-UI gibt. Wir sind ohne Kopf.
Um den Browser zu steuern, benötigen wir das Entwicklertools-Protokoll.
Informationen über die Seite abrufen
Installieren wir nun die Bibliothek:
npm i --save chrome-remote-interface
Beispiele
Beispiel – User-Agent ausgeben
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: Prü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
Derzeit öffnet Selenium eine vollständige Instanz von Chrome. Es handelt sich also um eine automatisierte Lösung, aber nicht komplett ohne Kopf. Selenium kann jedoch mit ein wenig Aufwand für die monitorlose Ausführung von Chrome konfiguriert werden. Wenn Sie eine vollständige Anleitung für die Einrichtung benötigen, empfehlen wir Ihnen, Selenium mit Headless Chrome auszuführen. Im Folgenden finden Sie jedoch einige Beispiele für den Einstieg.
ChromeDriver verwenden
ChromeDriver 2.32 verwendet Chrome 61 und funktioniert gut mit der monitorlosen Chrome-Version.
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 über Selenium WebDriver.
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:
Dokumentation
- DevTools-Protokollbetrachter – API-Referenzdokumentation
Tools
- chrome-remote-interface – Knotenmodul, das das DevTools-Protokoll umschließt
- Lighthouse: automatisiertes Tool zum Testen der Qualität von Webanwendungen; nutzt stark das Protokoll
- chrome-Launcher – Knotenmodul zum Starten von Chrome, bereit für die Automatisierung
Demos
- The Headless Web – Paul Kinlans großartiger Blogpost zur Verwendung von Headless mit api.ai.
Häufig gestellte Fragen
Benötige ich das Flag --disable-gpu
?
Nur unter Windows. Auf anderen Plattformen ist sie nicht mehr erforderlich. Das Flag --disable-gpu
ist eine temporäre Problemumgehung für einige Programmfehler. Sie werden dieses Flag in zukünftigen Chrome-Versionen nicht mehr benötigen. Weitere Informationen finden Sie unter crbug.com/737678.
Ich brauche also immer noch Xvfb?
Nein. Bei Headless Chrome wird kein Fenster verwendet, sodass ein Anzeigeserver wie Xvfb nicht mehr benötigt wird. Sie können Ihre automatisierten Tests auch ohne diese Funktion ausführen.
Was ist Xvfb? Xvfb ist ein speicherinterner Anzeigeserver für Unix-ähnliche Systeme, mit dem Sie grafische Anwendungen wie Chrome ohne angeschlossenen physischen Bildschirm ausführen können. Viele Nutzer verwenden Xvfb für ältere Versionen von Chrome, um "monitorlose" Tests durchzuführen.
Wie erstelle ich einen Docker-Container, auf dem die monitorlose Chrome-Version ausgeführt wird?
Sehen Sie sich lighthouse-ci an. Es gibt ein Beispiel-Dockerfile, das node:8-slim
als Basis-Image verwendet und Lighthouse auf App Engine Flex installiert und ausführt.
Kann ich dies mit Selenium / WebDriver / ChromeDriver verwenden?
Ja. Weitere Informationen finden Sie unter Selenium, WebDriver und ChromeDriver verwenden.
Was hat das mit PhantomJS zu tun?
Headless Chrome ist vergleichbar mit 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 nutzt.
Derzeit bietet Phantom auch eine API auf höherer Ebene als das DevTools-Protokoll.
Wo kann ich Fehler melden?
Melden Sie Fehler bei Headless Chrome unter crbug.com.
Fehler im DevTools-Protokoll können Sie unter github.com/ChromeDevTools/devtools-protocol einreichen.