.
TL;DR
Chrome bez interfejsu graficznego jest dostępny w wersji 59. Jest to sposób na uruchomienie przeglądarki Chrome w sytuacji, gdy nie ma interfejsu graficznego. To tak, jakby uruchomić Chrome bez Chrome! Dodaje do wiersza poleceń wszystkie funkcje nowoczesnych platform internetowych udostępniane przez Chromium i silnik renderowania Blink.
Dlaczego to jest przydatne?
Bezgłowy przeglądarka to świetne narzędzie do automatycznego testowania i środowiska serwera, w których nie potrzebujesz widocznej powłoki interfejsu. Możesz na przykład przeprowadzić testy na prawdziwej stronie internetowej, utworzyć jej wersję PDF lub sprawdzić, jak przeglądarka renderuje adres URL.
Uruchamianie bez interfejsu graficznego (CLI)
Najprostszym sposobem na rozpoczęcie pracy w trybie bez obsługi grafiki jest otwarcie pliku binarnego Chrome z wiersza poleceń. Jeśli masz zainstalowaną przeglądarkę Chrome w wersji 59 lub nowszej, uruchom ją z 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
powinien wskazywać na instalację Chrome. Dokładna lokalizacja będzie się różnić w zależności od platformy. Korzystam z Maca, więc utworzyłem wygodne aliasy dla każdej zainstalowanej wersji Chrome.
Jeśli korzystasz z Chrome w wersji stabilnej i nie możesz zainstalować wersji beta, zalecam użycie 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"
Pobierz Chrome Canary tutaj.
Funkcje wiersza poleceń
W niektórych przypadkach nie trzeba programowo tworzyć skryptów dla przeglądarki bez ekranu Chrome. Do wykonywania typowych zadań możesz używać przydatnych flag wiersza poleceń.
Wyświetlanie DOM
Flaga --dump-dom
wypisuje document.body.innerHTML
na wyjście standardowe:
chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/
Tworzenie pliku PDF
Flaga --print-to-pdf
tworzy plik PDF strony:
chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/
Robienie zrzutów ekranu
Aby zrobić zrzut ekranu strony, użyj flagi --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/
Uruchomienie polecenia --screenshot
spowoduje utworzenie pliku o nazwie screenshot.png
w bieżącym katalogu roboczym. Jeśli chcesz uzyskać zrzuty ekranu całej strony, musisz wykonać kilka dodatkowych czynności. David Schnur napisał świetny post na blogu, który może Ci pomóc. Zapoznaj się z artykułem Używanie przeglądarki Chromium bez interfejsu jako narzędzia do automatycznego tworzenia zrzutów ekranu .
Tryb REPL (pętla odczyt-sprawdź-wypisz)
Flaga --repl
uruchamia Headless w trybie, w którym możesz oceniać wyrażenia JS w przeglądarce bezpośrednio z poziomu wiersza poleceń:
$ 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
$
Debugowanie Chrome bez interfejsu przeglądarki
Gdy uruchomisz Chrome z --remote-debugging-port=9222
, uruchomi instancję z włączonym protokołem Narzędzi deweloperskich. Protokół ten służy do komunikacji z Chrome i sterowania instancją przeglądarki pozbawionej interfejsu. Jest on również używany przez narzędzia takie jak Sublime, VS Code i Node do zdalnego debugowania aplikacji. #synergy
Ponieważ nie masz interfejsu przeglądarki, aby wyświetlić stronę, otwórz ją w innej przeglądarce (http://localhost:9222
), aby sprawdzić, czy wszystko działa. Zobaczysz listę stron do inspekcji, które możesz przeglądać, aby sprawdzić, co renderuje Headless:
Możesz tu korzystać ze znanych funkcji Narzędzi deweloperskich, aby sprawdzać, debugować i modyfikować stronę w zwykły sposób. Jeśli używasz bezgłowym programowo, ta strona jest też potężnym narzędziem do debugowania, które pozwala zobaczyć wszystkie nieprzetworzone polecenia protokołu DevTools przesyłane przez sieć i komunikujące się z przeglądarką.
Korzystanie z programu (węzeł)
Animator
Puppeteer to biblioteka Node opracowana przez zespół Chrome. Zapewnia on interfejs API wysokiego poziomu do sterowania Chrome (bez głowy) lub pełną wersją Chrome. Jest on podobny do innych bibliotek testowania automatycznego, takich jak PhantomJS i NightmareJS, ale działa tylko w najnowszych wersjach Chrome.
Puppeteer można m.in. używać do łatwego tworzenia zrzutów ekranu, plików PDF, poruszania się po stronach i pobierania informacji o tych stronach. Jeśli chcesz szybko zautomatyzować testowanie przeglądarki, zalecam użycie biblioteki. Ukrywa złożoność protokołu DevTools i zajmuje się zbędnymi zadaniami, takimi jak uruchamianie instancji debugowania Chrome.
Zainstaluj:
npm i --save puppeteer
Przykład: wydrukowanie klienta użytkownika
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
console.log(await browser.version());
await browser.close();
})();
Przykład – zrzut ekranu strony
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();
})();
Aby dowiedzieć się więcej o pełnym interfejsie API, zapoznaj się z dokumentacją Puppeteer.
Biblioteka CRI
chrome-remote-interface to biblioteka niskiego poziomu w porównaniu z interfejsem API Puppeteer. Zalecam to, jeśli chcesz mieć bezpośredni dostęp do źródeł i używać protokołu DevTools.
Uruchamianie Chrome
chrome-remote-interface nie uruchamia Chrome za Ciebie, więc musisz to zrobić samodzielnie.
W sekcji CLI uruchomiliśmy Chrome ręcznie za pomocą --headless --remote-debugging-port=9222
. Aby jednak w pełni zautomatyzować testy, prawdopodobnie będziesz musiał utworzyć proces Chrome w ramach aplikacji.
Jednym ze sposobów jest użycie 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) => {
...
});
Sprawy się komplikują, jeśli chcesz mieć przenośne rozwiązanie, które działa na wielu platformach. Wystarczy spojrzeć na tę zaszyfrowaną ścieżkę do Chrome :(
Korzystanie z ChromeLauncher
Lighthouse to wspaniałe narzędzie do testowania jakości aplikacji internetowych. W Lighthouse został opracowany niezawodny moduł uruchamiania Chrome, który teraz został wyodrębniony do samodzielnego użycia.
chrome-launcher
Moduł NPM znajdzie miejsce, w którym zainstalowana jest przeglądarka Chrome, skonfiguruje instancję debugowania, uruchomi przeglądarkę i zatrzyma ją, gdy program zakończy działanie. Najlepsze jest to, że dzięki Node działa na wielu platformach.
Domyślnie chrome-launcher
spróbuje uruchomić Chrome Canary (jeśli jest zainstalowany), ale możesz ręcznie wybrać wersję Chrome, której chcesz użyć. Aby go użyć, najpierw zainstaluj go z npm:
npm i --save chrome-launcher
Przykład: uruchamianie trybu bez interfejsu graficznego za pomocą chrome-launcher
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();
});
Uruchomienie tego skryptu nie powoduje żadnych efektów, ale w menedżerze zadań powinien pojawić się proces about:blank
. Pamiętaj, że nie będzie żadnego interfejsu przeglądarki. Nie mamy interfejsu graficznego.
Aby sterować przeglądarką, potrzebujemy protokołu DevTools.
Pobieranie informacji o stronie
Zainstaluj bibliotekę:
npm i --save chrome-remote-interface
Przykłady
Przykład: wydrukowanie klienta użytkownika
const CDP = require('chrome-remote-interface');
...
launchChrome().then(async chrome => {
const version = await CDP.Version({port: chrome.port});
console.log(version['User-Agent']);
});
Wyniki będą wyglądać mniej więcej tak: HeadlessChrome/60.0.3082.0
Przykład: sprawdź, czy witryna zawiera manifest aplikacji internetowej.
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.
});
})();
Przykład – wyodrębnij <title>
strony za pomocą interfejsów DOM API.
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.
});
})();
Korzystanie z Selenium, WebDriver i ChromeDriver
Obecnie Selenium otwiera pełną instancję Chrome. Inaczej mówiąc, jest to rozwiązanie automatyczne, ale nie całkowicie pozbawione interfejsu. Jednak Selenium można skonfigurować do uruchamiania Chrome bez interfejsu graficznego. Jeśli chcesz uzyskać pełne instrukcje samodzielnego konfigurowania Selenium, zapoznaj się z artykułem Uruchamianie Selenium w Chrome bez wyświetlacza. Poniżej znajdziesz kilka przykładów, które pomogą Ci zacząć.
Korzystanie z ChromeDriver
ChromeDriver 2.32 używa Chrome 61 i działa dobrze z Chrome bez interfejsu graficznego.
Instalacja:
npm i --save-dev selenium-webdriver chromedriver
Przykład:
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();
Korzystanie z WebDriverIO
WebDriverIO to interfejs API wyższego poziomu oparty na Selenium WebDriver.
Instalacja:
npm i --save-dev webdriverio chromedriver
Przykład: filtrowanie funkcji CSS na stronie 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();
})();
Dodatkowe zasoby
Oto przydatne materiały na początek:
Dokumenty
- Wyświetlający interfejs DevTools Protocol – dokumentacja interfejsu API
Narzędzia
- chrome-remote-interface – moduł node’a, który otacza protokół DevTools.
- Lighthouse – automatyczne narzędzie do testowania jakości aplikacji internetowych, które intensywnie korzysta z protokołu.
- chrome-launcher – moduł node do uruchamiania Chrome, gotowy do automatyzacji
Prezentacje
- „The Headless Web” – świetny wpis na blogu Paula Kinlana na temat korzystania z Headless z api.ai.
Najczęstsze pytania
Czy potrzebuję flagi --disable-gpu
?
Tylko w systemie Windows. Inne platformy nie wymagają już tego. Flaga --disable-gpu
to tymczasowe obejście kilku błędów. W przyszłych wersjach Chrome nie będziesz już potrzebować tego parametru. Więcej informacji znajdziesz na stronie crbug.com/737678.
Czy nadal potrzebuję Xvfb?
Nie. Bezgłowa przeglądarka Chrome nie używa okna, więc serwer wyświetlania, taki jak Xvfb, nie jest już potrzebny. Możesz bez problemu przeprowadzać testy automatyczne bez tego.
Co to jest Xvfb? Xvfb to serwer wyświetlacza w pamięci dla systemów typu Unix, który umożliwia uruchamianie aplikacji graficznych (takich jak Chrome) bez podłączonego wyświetlacza fizycznego. Wiele osób używa Xvfb do uruchamiania starszych wersji Chrome w celu przeprowadzenia testów bez wyświetlania interfejsu.
Jak utworzyć kontener Dockera, w którym działa Chrome bez interfejsu graficznego?
Sprawdź lighthouse-ci. Zawiera przykładowy plik Dockerfile, który używa node:8-slim
jako obrazu bazowego, instaluje i uruchamia Lighthouse w App Engine Flex.
Czy mogę używać tej funkcji z Selenium, WebDriver lub ChromeDriver?
Tak. Zobacz Używanie Selenium, WebDriver i ChromeDriver.
Jak to się ma do PhantomJS?
Tryb bez głowy w Chrome jest podobny do narzędzi takich jak PhantomJS. Oba te rozwiązania można stosować do testowania automatycznego w sytuacji, gdy środowisko jest bez głowicy. Główna różnica między nimi polega na tym, że Phantom używa starszej wersji WebKit jako silnika do renderowania, a Chrome bez interfejsu użytkownika korzysta z najnowszej wersji Blink.
Obecnie Phantom udostępnia też interfejs API wyższego poziomu niż protokół Narzędzi deweloperskich.
Gdzie zgłaszam błędy?
Błędy w Chrome bez interfejsu graficznego zgłaszaj na stronie crbug.com.
Błędy w protokole DevTools zgłaszaj na stronie github.com/ChromeDevTools/devtools-protocol.