Tryb bez interfejsu graficznego w Chrome

Peter Kvitek
Peter Kvitek

W 2017 roku w Chrome 59 wprowadziliśmy tryb bez interfejsu graficznego, który umożliwia uruchamianie przeglądarki w środowisku nienadzorowanym bez widocznego interfejsu użytkownika. Możesz używać Chrome bez Chrome.

Tryb bez interfejsu graficznego jest często wybierany do automatyzacji przeglądarek w ramach projektów takich jak Puppeteer czy ChromeDriver. Oto krótki przykład wiersza poleceń, który pozwala utworzyć plik PDF o danym adresie URL w trybie bez interfejsu graficznego:

chrome --headless --print-to-pdf https://developer.chrome.com/

Jak działa bez interfejsu graficznego

Zanim omówimy, jak działa wersja bez interfejsu graficznego, musisz dowiedzieć się, jak działała wersja „poprzednia” wersja. Poprzedni fragment kodu wiersza poleceń używa flagi wiersza poleceń --headless, co sugeruje, że bez interfejsu graficznego to tylko tryb działania zwykłej przeglądarki Chrome. Co zaskakujące, w rzeczywistości nie było to prawdą. Stara wersja bez interfejsu graficznego była osobną implementacją alternatywnej przeglądarki, która została udostępniona w ramach tego samego pliku binarnego Chrome. Nie udostępnia żadnego kodu przeglądarki Chrome w witrynie //chrome.

Wdrożenie i obsługa osobnej przeglądarki bez interfejsu graficznego wiązało się z dużymi nakładami pracy inżynieryjnej. Ponieważ była ona osobną implementacją, miała własne błędy i funkcje, których nie było w przytulnym Chrome. Spowodowało to zamieszanie w automatycznych testach przeglądarki, które mogą nie działać w trybie nagłówka, ale w trybie bez interfejsu graficznego się nie udać lub odwrotnie.

Firma wykluczyła też wszystkie automatyczne testy, które polegały na zainstalowaniu rozszerzenia do przeglądarki. To samo dotyczy innych funkcji na poziomie przeglądarki; jeśli interfejs Headless nie miał osobnej implementacji, nie był on obsługiwany.

Zespół Chrome ujednolicił tryby bez interfejsu graficznego i tryb interfejsu graficznego.

Nowa wersja Chrome bez interfejsu graficznego nie jest już oddzielną implementacją przeglądarki. Zamiast tego udostępnia kod Chrome.

Nowy tryb bez interfejsu graficznego jest dostępny w Chrome 112. W tym trybie Chrome tworzy żadne okna platformy, ale nie wyświetla żadnych okien. Wszystkie inne funkcje, istniejące i przyszłe, są dostępne bez ograniczeń.

Korzystanie z trybu bez interfejsu graficznego

Aby użyć nowego trybu bez interfejsu graficznego, przekaż flagę wiersza poleceń --headless=new:

chrome --headless=new

Na razie stary tryb bez interfejsu graficznego jest nadal dostępny w przypadku:

chrome --headless=old

W Puppeteer

Aby włączyć nowy tryb bez interfejsu graficznego w Puppeteer:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  headless: 'new',
  // `headless: true` (default) enables old Headless;
  // `headless: 'new'` enables new Headless;
  // `headless: false` enables "headful" mode.
});

const page = await browser.newPage();
await page.goto('https://developer.chrome.com/');

// …

await browser.close();

W Selenium-WebDriver

Aby użyć nowego trybu bez interfejsu graficznego w Selenium-WebDriver:

const driver = await env
  .builder()
  .setChromeOptions(options.addArguments('--headless=new'))
  .build();

await driver.get('https://developer.chrome.com/');

// …

await driver.quit();

Więcej informacji, w tym przykłady zastosowania innych wiązań językowych, znajdziesz w poście na blogu zespołu Sellenium.

Flagi wiersza poleceń

W nowym trybie bez interfejsu graficznego dostępne są następujące flagi wiersza poleceń.

--dump-dom

Flaga --dump-dom wyświetla zserializowany DOM strony docelowej do stdout. Na przykład:

chrome --headless=new --dump-dom https://developer.chrome.com/

Różni się to od drukowania kodu źródłowego HTML, którego można użyć w kodzie curl. Aby wyświetlić dane wyjściowe interfejsu --dump-dom, Chrome najpierw analizuje kod HTML w model DOM, wykonuje wszystkie wywołania <script>, które mogą zmieniać DOM, a następnie przekształca ten DOM z powrotem w serializowany ciąg kodu HTML.

--screenshot

Flaga --screenshot powoduje wykonanie zrzutu ekranu strony docelowej i zapisanie go w bieżącym katalogu roboczym jako screenshot.png. Przydaje się to szczególnie w połączeniu z flagą --window-size.

Na przykład:

chrome --headless=new --screenshot --window-size=412,892 https://developer.chrome.com/

--print-to-pdf

Flaga --print-to-pdf zapisuje stronę docelową w bieżącym katalogu roboczym jako plik PDF o nazwie output.pdf. Na przykład:

chrome --headless=new --print-to-pdf https://developer.chrome.com/

Opcjonalnie możesz dodać flagę --no-pdf-header-footer, aby pomijać nagłówek wydruku (z bieżącą datą i godziną) i stopkę (z adresem URL i numerem strony).

chrome --headless=new --print-to-pdf --no-pdf-header-footer https://developer.chrome.com/

Nie: funkcje flagi --no-pdf-header-footer były wcześniej dostępne z flagą --print-to-pdf-no-header. Jeśli używasz poprzedniej wersji, być może trzeba będzie wrócić do starej nazwy flagi.

--timeout

Flaga --timeout określa maksymalny czas oczekiwania (w milisekundach), po którym treść strony jest przechwytywana przez funkcje --dump-dom, --screenshot i --print-to-pdf, nawet jeśli strona nadal się wczytuje.

chrome --headless=new --print-to-pdf --timeout=5000 https://developer.chrome.com/

Flaga --timeout=5000 informuje Chrome, że plik PDF może zostać wydrukowany dopiero po 5 sekundach. Z tego powodu ten proces może potrwać maksymalnie 5 sekund.

--virtual-time-budget

Element --virtual-time-budget działa jak „przewijanie do przodu” w przypadku dowolnego kodu zależnego od czasu (np. setTimeout/setInterval). Zmusza przeglądarkę do jak najszybszego wykonywania kodu strony, a jednocześnie da jej pewność, że czas rzeczywiście upływa.

Aby zilustrować jego zastosowanie, spójrz na tę wersję demonstracyjną, która zwiększa, logi i wyświetla licznik co sekundę za pomocą funkcji setTimeout(fn, 1000). Oto odpowiedni kod:

<output>0</output>
<script>
  const element = document.querySelector('output');
  let counter = 0;
  setInterval(() => {
    counter++;
    console.log(counter);
    element.textContent = counter;
  }, 1_000);
</script>

Po jednej sekundzie strona zawiera wartość „1”, po dwóch sekundach – „2” itd. Aby zapisać stan strony po 42 sekundach i zapisać ją jako plik PDF:

chrome --headless=new --print-to-pdf --virtual-time-budget=42000 https://mathiasbynens.be/demo/time

--allow-chrome-scheme-url

Flaga --allow-chrome-scheme-url jest wymagana, aby uzyskać dostęp do adresów URL chrome://. Ta flaga jest dostępna od Chrome 123. Oto przykład:

chrome --headless=new --print-to-pdf --allow-chrome-scheme-url chrome://gpu

Debugowanie

Chrome jest niewidoczny w trybie bez interfejsu graficznego, więc rozwiązanie problemu może wydawać się trudne. Można debugować Chrome bez interfejsu graficznego w sposób bardzo podobny do interfejsu graficznego.

Uruchom Chrome w trybie bez interfejsu graficznego z flagą wiersza poleceń --remote-debugging-port.

chrome --headless=new --remote-debugging-port=0 https://developer.chrome.com/

Powoduje to wydrukowanie unikalnego adresu URL WebSocket na potrzeby protokołu stdout, na przykład:

DevTools listening on ws://127.0.0.1:60926/devtools/browser/b4bd6eaa-b7c8-4319-8212-225097472fd9

W konkretnej instancji Chrome możemy następnie użyć zdalnego debugowania przy użyciu Narzędzi deweloperskich w Chrome, aby połączyć się z celem bez interfejsu graficznego i je sprawdzić.

  1. Przejdź na stronę chrome://inspect i kliknij przycisk Konfiguruj....
  2. Wpisz adres IP i numer portu z adresu URL WebSocket.
    • W poprzednim przykładzie mam wpisany ciąg 127.0.0.1:60926.
  3. Kliknij Gotowe. Powinien wyświetlić się cel zdalny z listą wszystkich jego kart i innych celów.
  4. Kliknij sprawdź, aby uzyskać dostęp do Narzędzi deweloperskich w Chrome i sprawdzić zdalne środowisko docelowe bez interfejsu graficznego, w tym podgląd na żywo strony.

Narzędzia deweloperskie w Chrome mogą sprawdzać zdalną stronę docelową bez interfejsu graficznego

Prześlij opinię

Chętnie poznamy Twoją opinię na temat nowego trybu bez interfejsu graficznego. Jeśli napotkasz jakieś problemy, zgłoś błąd.