Powłoka Chrome bez interfejsu graficznego została udostępniona w Chrome 59. Umożliwia ona uruchamianie przeglądarki Chrome w środowisku bez interfejsu graficznego. Zasadniczo jest to uruchamianie Chrome bez Chrome. Dzięki temu w wierszu poleceń dostępne są wszystkie nowoczesne funkcje platformy internetowej zapewniane przez Chromium i silnik renderowania Blink.
Przeglądarka bez interfejsu graficznego to doskonałe narzędzie do automatycznego testowania i środowisk serwerowych, w których nie jest potrzebna widoczna powłoka interfejsu użytkownika. Możesz na przykład przeprowadzić testy na prawdziwej stronie internetowej, utworzyć jej plik PDF lub po prostu sprawdzić, jak przeglądarka renderuje adres URL.
Uruchamianie wersji bez interfejsu graficznego (interfejs wiersza poleceń)
Najłatwiejszym sposobem na rozpoczęcie pracy z trybem bez interfejsu graficznego jest otwarcie pliku binarnego Chrome z wiersza poleceń. Jeśli masz zainstalowaną przeglądarkę Chrome w wersji 59 lub nowszej, uruchom ją za pomocą flagi --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ć instalację Chrome. Dokładna lokalizacja będzie się różnić w zależności od platformy. Ponieważ korzystam z komputera Mac, utworzyłem wygodne aliasy dla każdej zainstalowanej wersji Chrome.
Jeśli korzystasz z stabilnego kanału Chrome i nie możesz uzyskać wersji beta, użyj 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.
Funkcje wiersza poleceń
W niektórych przypadkach nie musisz programowo tworzyć skryptów dla Chrome bez interfejsu graficznego. Do wykonywania typowych zadań służą przydatne flagi wiersza poleceń.
Drukowanie DOM
Flaga --dump-dom drukuje document.body.innerHTML na standardowe wyjście:
chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/
### Create a PDF
The `--print-to-pdf` flag creates a PDF of the page:
```shell
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 z flagą --screenshot spowoduje utworzenie pliku o nazwie screenshot.png w bieżącym katalogu roboczym. Jeśli chcesz zrobić zrzut całego ekranu, musisz wykonać nieco więcej czynności. Więcej informacji znajdziesz w świetnym poście na blogu Davida Schnurra. Przeczytaj artykuł
Using headless Chrome as an automated screenshot tool (Używanie Chrome bez interfejsu graficznego jako automatycznego narzędzia do robienia zrzutów ekranu).
Tryb REPL (pętla odczytu, obliczania i drukowania)
Flaga --repl uruchamia Chrome bez interfejsu graficznego w trybie, w którym możesz obliczać wyrażenia JS w przeglądarce bezpośrednio z 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 za pomocą flagi --remote-debugging-port=9222, zostanie uruchomiona instancja
z włączonym protokołem Narzędzi deweloperskich. Protokół służy do komunikacji z Chrome i sterowania instancją przeglądarki bez interfejsu graficznego. Jest on też używany przez narzędzia takie jak Sublime, VS Code i Node do zdalnego debugowania aplikacji. #synergy
Ponieważ nie masz interfejsu przeglądarki, aby zobaczyć stronę, otwórz w innej przeglądarce adres http://localhost:9222, aby sprawdzić, czy wszystko działa. Zobaczysz listę stron, które można sprawdzić. Możesz kliknąć dowolną z nich i zobaczyć, co renderuje Chrome bez interfejsu graficznego:
W tym miejscu możesz używać znanych funkcji Narzędzi deweloperskich do sprawdzania, debugowania i dostosowywania strony. Jeśli używasz Chrome bez interfejsu graficznego programowo, ta strona jest też przydatnym narzędziem do debugowania, które pozwala zobaczyć wszystkie surowe polecenia protokołu Narzędzi deweloperskich przesyłane przez sieć i komunikujące się z przeglądarką.
Używanie programowo (Node)
Animator
Animator to biblioteka Node opracowana przez zespół Chrome. Udostępnia interfejs API wysokiego poziomu do sterowania Chrome bez interfejsu graficznego (lub pełnego). Jest podobna do innych bibliotek do automatycznego testowania, takich jak Phantom i NightmareJS, ale działa tylko z najnowszymi wersjami Chrome.
Animator może być używany m.in. do łatwego robienia zrzutów ekranu, tworzenia plików PDF, nawigowania po stronach i pobierania informacji o tych stronach. Zalecam korzystanie z tej biblioteki, jeśli chcesz szybko zautomatyzować testowanie przeglądarki. Ukrywa ona złożoność protokołu Narzędzi deweloperskich i zajmuje się powtarzalnymi zadaniami, takimi jak uruchamianie instancji debugowania Chrome.
Zainstaluj ją:
npm i --save puppeteer
Przykład – drukowanie agenta użytkownika
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch();
console.log(await browser.version());
await browser.close();
})();
Przykład – robienie zrzutu 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ą Animatora.
Biblioteka CRI
chrome-remote-interface to biblioteka niższego poziomu niż interfejs API Animatora. Zalecam jej używanie, jeśli chcesz mieć bezpośredni dostęp do protokołu Narzędzi deweloperskich.
Uruchamianie Chrome
chrome-remote-interface nie uruchamia Chrome, więc musisz to zrobić samodzielnie.
W sekcji dotyczącej interfejsu wiersza poleceń uruchomiliśmy Chrome ręcznie za pomocą
--headless --remote-debugging-port=9222. Aby jednak w pełni zautomatyzować testy, prawdopodobnie będziesz musiał uruchomić Chrome z poziomu 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) => {
...
});
Jeśli jednak chcesz mieć przenośne rozwiązanie, które działa na różnych platformach, sytuacja się komplikuje. Spójrz tylko na ten zakodowany na stałe ścieżkę do Chrome :(
Używanie ChromeLauncher
Lighthouse to doskonałe
narzędzie do testowania jakości aplikacji internetowych. W Lighthouse opracowano niezawodny moduł do uruchamiania Chrome, który został teraz wyodrębniony do samodzielnego użytku.
Moduł NPM chrome-launcher
`chrome-launcher`
znajdzie miejsce instalacji Chrome, skonfiguruje instancję debugowania, uruchomi przeglądarkę i zamknie ją
po zakończeniu działania programu. Najlepsze jest to, że dzięki Node działa na wielu platformach.
Domyślnie chrome-launcher spróbuje uruchomić Chrome Canary (jeśli jest zainstalowana), ale możesz to zmienić, aby ręcznie wybrać, której wersji Chrome chcesz użyć. Aby użyć tego modułu, najpierw zainstaluj go za pomocą npm:
npm i --save chrome-launcher
Przykład – używanie chrome-launcher do uruchamiania wersji bez interfejsu graficznego
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 spowoduje żadnych zmian, ale w Menedżerze zadań powinna pojawić się instancja Chrome, która wczytała about:blank. Pamiętaj, że nie będzie żadnego interfejsu przeglądarki. Używamy wersji bez interfejsu graficznego.
Aby sterować przeglądarką, potrzebujemy protokołu Narzędzi deweloperskich.
Pobieranie informacji o stronie
Aby zainstalować bibliotekę:
npm i --save chrome-remote-interface
Przykłady
Przykład – drukowanie agenta 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']);
});
Wynik będzie podobny do: HeadlessChrome/60.0.3082.0
Przykład – sprawdzanie, czy witryna ma 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ębnianie elementu <title> strony za pomocą interfejsów 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.
});
})();
Używanie Selenium, WebDriver i ChromeDriver
Obecnie Selenium otwiera pełną instancję Chrome. Innymi słowy, jest to rozwiązanie zautomatyzowane, ale nie w pełni bez interfejsu graficznego. Selenium można jednak skonfigurować tak, aby uruchamiało Chrome bez interfejsu graficznego. Jeśli chcesz uzyskać pełne instrukcje dotyczące samodzielnej konfiguracji, przeczytaj artykuł Running Selenium with Headless Chrome. Poniżej znajdziesz kilka przykładów, które pomogą Ci zacząć.
Używanie ChromeDriver
ChromeDriver 2.32 używa Chrome 61 i dobrze współpracuje z Chrome bez interfejsu graficznego.
Zainstaluj:
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();
Używanie WebDriverIO
WebDriverIO to interfejs API wyższego poziomu oparty na Selenium WebDriver.
Zainstaluj:
npm i --save-dev webdriverio chromedriver
Przykład: filtrowanie funkcji CSS na 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();
})();
Pobieranie starej wersji Chrome bez interfejsu graficznego jako chrome-headless-shell
Od wersji 112 Chrome dostępny jest nowy tryb bez interfejsu graficznego (--headless=new). Ten tryb umożliwia deweloperom uruchamianie samego Chrome, a nie osobnego pliku binarnego, w środowisku nienadzorowanym bez widocznego interfejsu użytkownika. Jest to przydatne w przypadku testowania i automatyzacji.
Istnieją różne przypadki użycia starej powłoki bez interfejsu graficznego i nowego trybu bez interfejsu graficznego:
- Stara powłoka bez interfejsu graficznego to lekka otoczka wokół modułu
//contentChromium, dlatego ma znacznie mniej zależności. W szczególności nie wymaga X11/Wayland, D-Bus i jest pod pewnymi względami wydajniejsza niż pełna przeglądarka Chrome. Dzięki temu nadaje się do przypadków użycia takich jak automatyczne robienie zrzutów ekranu czy pobieranie danych ze stron internetowych. - Z kolei nowy tryb bez interfejsu graficznego to prawdziwa przeglądarka Chrome, dlatego jest bardziej autentyczny, niezawodny i oferuje więcej funkcji. Dzięki temu lepiej nadaje się do testowania aplikacji internetowych typu end-to-end z dużą dokładnością lub testowania rozszerzeń przeglądarki.
Innymi słowy, istnieje kompromis między wydajnością a autentycznością. Który tryb bez interfejsu graficznego jest dla Ciebie najlepszy? To zależy od przypadku użycia.
Deweloperzy i testerzy, którzy nie potrzebują pełnej funkcjonalności Chrome do automatyzacji, mogą używać starej wersji bez interfejsu graficznego. W przeciwnym razie prawdopodobnie najlepszym wyborem będzie nowa wersja bez interfejsu graficznego.
Aby deweloperzy i testerzy nadal mieli wybór między tymi 2 opcjami, z przyjemnością informujemy, że stara implementacja bez interfejsu graficznego jest teraz dostępna jako samodzielny plik binarny chrome-headless-shell. Te nowe chrome-headless-shell pliki binarne są generowane dla każdej wersji Chrome przeznaczonej dla użytkowników i można je pobrać za pomocą infrastruktury Chrome for Testing począwszy od Chrome 120.
Jak mogę uzyskać pliki binarne chrome-headless-shell?
Podobnie jak w przypadku innych plików binarnych Chrome for Testing, najłatwiejszym sposobem na pobranie chrome-headless-shell na swoją platformę jest użycie naszego narzędzia wiersza poleceń, które jest dostępne za pomocą npm.@puppeteer/browsers Oto kilka przykładów:
# Download the latest available `chrome-headless-shell` binary corresponding to the Stable channel.
npx @puppeteer/browsers install chrome-headless-shell@stable
# Download a specific `chrome-headless-shell` version.
npx @puppeteer/browsers install chrome-headless-shell@120.0.6098.0
Jeśli wolisz tworzyć własne skrypty automatyczne do pobierania plików binarnych chrome-headless-shell, mamy dla Ciebie rozwiązanie. Chrome for Testing udostępnia punkty końcowe JSON API z najnowszymi dostępnymi wersjami w każdym kanale wersji Chrome (stabilnym, beta, deweloperskim i Canary). Krótkie podsumowanie jej najnowszego stanu znajdziesz w panelu dostępności Chrome for Testing.
Prześlij opinię
Czekamy na Twoją opinię o chrome-headless-shell. Jeśli napotkasz jakieś problemy, zgłoś je tutaj.
Dodatkowe zasoby
Oto kilka przydatnych materiałów, które pomogą Ci zacząć:
Dokumenty
- Przeglądarka protokołu Narzędzi deweloperskich – dokumentacja API
Narzędzia
- chrome-remote-interface – moduł Node, który opakowuje protokół Narzędzi deweloperskich
- Lighthouse – automatyczne narzędzie do testowania jakości aplikacji internetowych; intensywnie korzysta z protokołu
- chrome-launcher – moduł Node do uruchamiania Chrome, gotowy do automatyzacji
Prezentacje
- „The Headless Web” – świetny post na blogu Paula Kinlana na temat używania wersji bez interfejsu graficznego z api.ai.
Najczęstsze pytania
Czy potrzebuję flagi --disable-gpu?
Tylko w systemie Windows. Inne platformy nie wymagają już tej flagi. Flaga --disable-gpu to tymczasowe obejście kilku błędów. W przyszłych wersjach Chrome nie będzie ona potrzebna. Więcej informacji znajdziesz na stronie crbug.com/737678.
Czy nadal potrzebuję Xvfb?
Nie. Chrome bez interfejsu graficznego nie używa okna, więc serwer wyświetlania taki jak Xvfb nie jest już potrzebny. Możesz bez problemu uruchamiać automatyczne testy bez niego.
Co to jest Xvfb? Xvfb to serwer wyświetlania w pamięci dla systemów podobnych do Uniksa, który umożliwia uruchamianie aplikacji graficznych (takich jak Chrome) bez podłączonego fizycznego wyświetlacza. Wiele osób używa Xvfb do uruchamiania starszych wersji Chrome w celu przeprowadzania testów „bez interfejsu graficznego”.
Jak utworzyć kontener Dockera, który uruchamia Chrome bez interfejsu graficznego?
Sprawdź lighthouse-ci. Zawiera on
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ć tego z Selenium / WebDriver / ChromeDriver?
Tak. Zapoznaj się z sekcją Używanie Selenium, WebDriver i ChromeDriver.
Jaki ma to związek z PhantomJS?
Chrome bez interfejsu graficznego jest podobny do narzędzi takich jak PhantomJS. Oba mogą być używane do automatycznego testowania w środowisku bez interfejsu graficznego. Główna różnica między nimi polega na tym, że Phantom używa starszej wersji WebKit jako silnika renderowania, a Chrome bez interfejsu graficznego – najnowszej wersji Blink.
Obecnie Phantom udostępnia też interfejs API wyższego poziomu niż protokół Narzędzi deweloperskich.
Gdzie mam zgłaszać błędy?
Błędy dotyczące Chrome bez interfejsu graficznego zgłaszaj na stronie crbug.com.
Błędy w protokole Narzędzi deweloperskich zgłaszaj na stronie github.com/ChromeDevTools/devtools-protocol.