TL;DR
Chrome bez interfejsu graficznego jest dostępny w wersji 59. Umożliwia on uruchamianie przeglądarki Chrome w środowisku bez interfejsu graficznego.Krótko mówiąc, korzystanie z Chrome bez Chrome. Wprowadza do wiersza poleceń wszystkie nowoczesne funkcje platformy internetowej udostępniane przez Chromium i silnik renderowania Blink.
Dlaczego jest to przydatne?
Przeglądarka bez interfejsu graficznego to świetne narzędzie do automatycznego testowania i stosowania środowisk serwera, w których nie potrzebujesz widocznej powłoki UI. Możesz na przykład przeprowadzić testy na rzeczywistej stronie internetowej, utworzyć jej plik PDF lub po prostu sprawdzić, jak przeglądarka renderuje URL.
Uruchamiam bez interfejsu graficznego (interfejs wiersza poleceń)
Najłatwiejszym sposobem na rozpoczęcie pracy w trybie bez interfejsu graficznego jest otwarcie pliku binarnego Chrome z poziomu wiersza poleceń. Jeśli masz zainstalowaną przeglądarkę Chrome 59 lub nowszą, 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.
Adres chrome
powinien wskazywać Twoją instalację Chrome. Dokładna lokalizacjaróżni się w zależności od platformy. Używam Maca, więc utworzyłem wygodne aliasydla każdej zainstalowanej wersji Chrome.
Jeśli korzystasz z wersji stabilnej Chrome, a nie możesz pobrać wersji beta, zalecamy 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"
Chrome Canary możesz pobrać stąd.
Funkcje wiersza poleceń
W niektórych przypadkach nie trzeba programować tworzenia skryptów w Chrome bez interfejsu graficznego.W wierszu poleceń jest kilka przydatnych flag wiersza poleceń, które ułatwiają wykonywanie typowych zadań.
Drukowanie DOM
Flaga --dump-dom
pokazuje document.body.innerHTML
do standardowego protokołu:
chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/
Utwórz 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 5xchrome --headless --disable-gpu --screenshot --window-size=412,732 https://www.chromestatus.com/
Wykonanie polecenia --screenshot
spowoduje utworzenie w bieżącym katalogu roboczym pliku o nazwie screenshot.png
. Zrzuty całej strony są nieco większe. Na blogu Davida Schnurraznajdziesz świetny post na blogu. Zapoznaj się z artykułem Używanie Chrome bez interfejsu graficznego jako automatycznego narzędzia do tworzenia zrzutów ekranu .
Tryb REPL (pętla odczytu-eval-print)
Flaga --repl
uruchamia się w trybie bez interfejsu graficznego w trybie, w którym możesz oceniać 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$
debugujesz Chrome bez użycia interfejsu przeglądarki?
Kiedy używasz Chrome z --remote-debugging-port=9222
, uruchamiana jest instancja z włączonym protokołem Narzędzi deweloperskich. Protokół ten służy do komunikacji z Chrome i kierowania instancji przeglądarki bez interfejsu graficznego. Umożliwia ona też zdalne debugowanie aplikacji za pomocą takich narzędzi jak Sublime, VS Code i Node. #synergy
Ponieważ nie masz interfejsu przeglądarki, który pozwala wyświetlić stronę, otwórz http://localhost:9222
w innej przeglądarce, aby sprawdzić, czy wszystko działa. Pojawi się lista stron, które można sprawdzić, aby sprawdzić, co renderuje bez interfejsu graficznego:
Możesz tu sprawdzać, debugować i dostosowywać stronę w zwykły sposób, korzystając z znanych funkcji Narzędzi deweloperskich. Jeśli używasz interfejsu bez interfejsu graficznego, ta strona jest też zaawansowanym narzędziem do debugowania, w którym zobaczysz wszystkie nieprzetworzone polecenia protokołu DevNarzędzia przechodzące przez przewód, komunikujące się z przeglądarką.
Korzystanie z automatyzacji (węzeł)
Animator
Puppeteer to biblioteka węzłów opracowana przez zespół Chrome. Udostępnia ogólny interfejs API do sterowania Chrome bez interfejsu graficznego (lub z pełną funkcjonalnością). Działa ona podobnie do innych bibliotek testowania automatycznego, takich jak Phantom czy NightmareJS, ale działa tylko z najnowszymi wersjami Chrome.
Aplikacja Puppeteer umożliwia m.in. łatwe wykonywanie zrzutów ekranu, tworzenie plików PDF, poruszanie się po stronach i pobieranie informacji o nich. Polecam bibliotekę,jeśli chcecie szybko zautomatyzować testowanie przeglądarki. Ukrywa ono złożoność protokołu Narzędzi deweloperskich i zajmuje się nadmiarowymi zadaniami, takimi jak uruchamianie instancji debugowania Chrome.
Zainstaluj:
npm i --save puppeteer
Przykład – wydrukowanie informacji o kliencie 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();})();
Więcej informacji o pełnej wersji interfejsu API znajdziesz w dokumentacji Puppeteer.
Biblioteka CRI
chrome-remote-interface to biblioteka niższego poziomu niż interfejs API Puppeteer. Polecam go, jeśli chcesz zbliżyć się do metalu i korzystać z protokołu DevTools.
Uruchamiam Chrome
chrome-remote-interface nie uruchamia za Ciebie Chrome, więc musisz zająć się tym samodzielnie.
W sekcji interfejsu wiersza poleceń uruchomiliśmy Chrome ręcznie za pomocą --headless --remote-debugging-port=9222
. Jednak aby w pełni zautomatyzować testy, trzeba będzie prawdopodobnie wygenerować Chrome z aplikacji.
Jednym ze sposobów jest użycie polecenia 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) => { ...});
Jednak jeśli potrzebujesz przenośnego rozwiązania działającego na wielu platformach, będziesz mieć problemy. Spójrzmy tylko na zakodowaną na stałe ścieżkę do Chrome :(
Korzystanie z ChromeLauncher
Lighthouse to wspaniałe narzędzie do testowania jakości aplikacji internetowych. W Lighthouse został opracowany rozbudowany modułumożliwiający uruchamianie Chrome, który teraz można z niego wydobyć w trybie samodzielnym.Moduł NPM chrome-launcher
znajdzie informacje o tym, gdzie zainstalowano Chrome, skonfiguruje instancję debugowania, uruchomi przeglądarkę i zamknie ją, gdy program będzie gotowy. A najlepsze jest to, że dzięki Node.js 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ć Chrome, którego chcesz używać. Aby użyć tej funkcji, najpierw zainstaluj ją z npm:
npm i --save chrome-launcher
Przykład – użycie interfejsu chrome-launcher
do uruchomienia interfejsu 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 skryptu niewiele daje, ale w menedżerze zadań, który wczytał about:blank
, powinno się uruchomić wystąpienie Chrome. Pamiętaj, że nie będzie żadnegointerfejsu przeglądarki. Nie mamy głowy.
Do kontrolowania przeglądarki potrzebny jest protokół Narzędzi deweloperskich.
Pobieranie informacji o stronie
Zainstalujmy bibliotekę:
npm i --save chrome-remote-interface
Przykłady
Przykład – wydrukowanie informacji o kliencie 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 w rodzaju: HeadlessChrome/60.0.3082.0
Przykład – sprawdź, 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ę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.});})();
Używanie Selenium, WebDriver i ChromeDriver
Obecnie Selenium otwiera pełną instancję Chrome. Innymi słowy, jest to rozwiązanie automatyczne,ale nie całkowicie pozbawione interfejsu graficznego. Selenium można jednak skonfigurować tak, żeby bez interfejsu graficznego Chrome działał z niewielkim nakładem pracy. Jeśli potrzebujesz szczegółowych instrukcji konfiguracji, zalecamy uruchomienie Selenium w Chrome bez interfejsu graficznego. Na początek skorzystam z poniższych przykładów.
Przy użyciu ChromeDriver
ChromeDriver 2.32 korzysta z Chrome 61 i działa dobrze w przypadku 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();
Korzystanie z WebDriverIO
WebDriverIO to interfejs API wyższego poziomu będący alternatywą dla Selenium WebDriver.
Zainstaluj:
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 kilka przydatnych zasobów na początek:
Dokumenty
- Wyświetlający protokoły DevTools – dokumentacja API
Narzędzia
- chrome-remote-interface – modułwęzła opakowujący protokół Narzędzi deweloperskich
- Lighthouse – automatyczne narzędzie do testowaniajakości aplikacji internetowych, które intensywnie korzysta z protokołu
- chrome-launcher –moduł węzła do uruchamiania Chrome, gotowy do automatyzacji.
Przykłady
- „The Headless Web” – świetny post Paula Kinlana na temat korzystania z interfejsu Headless i api.ai.
Najczęstsze pytania
Czy potrzebuję flagi --disable-gpu
?
Tylko w systemie Windows. Na innych platformach nie jest on już wymagany. Flaga --disable-gpu
to tymczasowe rozwiązanie w przypadku kilku błędów. Ta flaga nie jest potrzebnaw kolejnych wersjach Chrome. Więcej informacji znajdziesz na stronie crbug.com/737678.
Czy w dalszym ciągu 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 niego przeprowadzać automatyczne testy.
Co to jest Xvfb? Xvfb to wewnętrzny serwer wyświetlania dla systemów typu Unix, który pozwala uruchamiać aplikacje graficzne (takie jak Chrome) bez podłączonego fizycznego wyświetlacza.Wiele osób używa Xvfb do uruchamiania wcześniejszych wersji Chrome do testów bez interfejsu graficznego.
Jak utworzyć kontener Dockera, który będzie obsługiwać Chrome bez interfejsu graficznego?
Spójrz na to miejsce: Lighthouse-ci. Zawiera przykładowy plik Dockerfile, który używa node:8-slim
jako obrazu podstawowego, instaluje i uruchamia Lighthouse w App Engine Flex.
Czy mogę używać tego rozwiązania z usługą Selenium / WebDriver / ChromeDriver?
Tak. Zobacz Using Selenium, WebDriver i ChromeDriver.
Jaki jest związek z PhantomJS?
Chrome bez interfejsu graficznego jest podobny do narzędzi takich jak PhantomJS. Oba modele można stosować do automatycznych testów w środowisku bez interfejsu graficznego. {/1}
Obecnie Phantom zapewnia też interfejs API wyższego poziomu niż protokół narzędzi deweloperskich.
Gdzie zgłaszać błędy?
Błędy dotyczące Chrome bez interfejsu graficznego możesz zgłaszać na stronie crbug.com.
Błędy w protokole narzędzi deweloperskich możesz zgłaszać na stronie github.com/ChromeDevTools/devtools-protocol.