Uaktualniliśmy tryb bez interfejsu graficznego w Chrome: wprowadzenie --headless=new

Tryb bez interfejsu graficznego w Chrome jest teraz znacznie lepszy.

Peter Kvitek
Peter Kvitek

Tryb bez interfejsu graficznego w Chrome jest teraz znacznie lepszy. Ten artykuł zawiera przegląd ostatnich prac technicznych mających na celu zwiększenie przydatności interfejsu graficznego bez interfejsu graficznego dla programistów przez przybliżenie trybu „headless” do zwykłego trybu „headful” w Chrome.

Wprowadzenie

W 2017 roku w Chrome 59 wprowadziliśmy tzw. tryb bez interfejsu graficznego, który umożliwia uruchamianie przeglądarki w środowisku porzuconym bez widocznego interfejsu użytkownika. Zasadniczo korzystasz z Chrome bez Chrome.

Tryb bez interfejsu graficznego jest często używany do automatyzacji przeglądarek w projektach takich jak Puppeteer czy ChromeDriver. Oto krótki przykład użycia trybu bez interfejsu graficznego do utworzenia pliku PDF z danym adresem URL w wierszu poleceń:

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

Co nowego w Headless?

Zanim przejdziemy do ostatnich ulepszeń interfejsu API bez interfejsu graficznego, warto dowiedzieć się, jak działa „stara” wersja tej funkcji. Omówiony wcześniej fragment kodu wiersza poleceń zawiera flagę wiersza poleceń --headless, co sugeruje, że interfejs bez interfejsu graficznego to tylko tryb działania zwykłej przeglądarki Chrome. Może to być zaskakujące, ale to nieprawda. Technicznie rzecz biorąc, stary interfejs Headless był oddzielną, alternatywną implementacją przeglądarki, która była dostarczana jako część tego samego pliku binarnego Chrome. Nie udostępnia żadnego kodu przeglądarki Chrome w obszarze //chrome.

Jak łatwo sobie wyobrazić, wdrożenie i utrzymywanie tej osobnej przeglądarki bez interfejsu graficznego wymagało wiele pracy inżynierskiej – ale nie był to jedyny problem. Interfejs Headless był odrębną implementacją, więc miał własne błędy i funkcje, których brakowało w głównej wersji Chrome. Było to niejasne: każdy automatyczny test przeglądarki mógł przejść w trybie nagłówka, ale w trybie bez interfejsu graficznego kończyć się niepowodzeniem lub na odwrót. Był to poważny problem dla inżynierów automatyzacji. Wykluczono też wszystkie automatyczne testy, które polegały na przykład na zainstalowaniu rozszerzenia do przeglądarki. To samo dotyczy innych funkcji na poziomie przeglądarki – nie były obsługiwane, o ile interfejs Headless nie miał własnej implementacji.

W 2021 roku zespół Chrome postanowił rozwiązać ten problem, jednocześnie łącząc tryby bez interfejsu graficznego i gościnne.

Nowy interfejs Chrome Headless nie jest już osobną implementacją – teraz korzysta z tego samego kodu udostępnianych Chrome.

Z przyjemnością informujemy, że w Chrome 112 jest już dostępny nowy tryb bez interfejsu graficznego. W tym trybie Chrome tworzy, ale nie wyświetla żadnych okien platformy. Wszystkie pozostałe funkcje (obecne i przyszłe) są dostępne bez ograniczeń.

Wypróbuj nową wersję bez interfejsu graficznego

Aby wypróbować nowy tryb bez interfejsu graficznego, przekaż flagę wiersza poleceń --headless=new:

chrome --headless=new

Na razie stary tryb bez interfejsu graficznego jest nadal dostępny w tych usługach:

chrome --headless=old

Obecnie przekazanie flagi wiersza poleceń --headless bez konkretnej wartości nadal aktywuje stary tryb bez interfejsu graficznego, ale planujemy zmienić go z czasem na nowy.

Planujemy całkowicie usunąć starą wersję interfejsu bez interfejsu graficznego z Chrome i przestać obsługiwać ten tryb w Puppeteer jeszcze w tym roku. W ramach tej zmiany udostępnimy starą wersję bez interfejsu graficznego jako oddzielny, samodzielny plik binarny dla użytkowników, którzy jeszcze nie mogą przejść na nowszą wersję.

Nowość w grze Puppeteer bez interfejsu graficznego

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();

Nowy interfejs bez interfejsu graficznego w Selelenium-WebDriver

Aby korzystać z 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 użycia powiązań w innych językach, znajdziesz w poście na blogu zespołu Selenium.

Flagi wiersza poleceń specyficzne dla interfejsu bez interfejsu graficznego

W nowym trybie bez interfejsu graficznego dostępne są poniższe flagi wiersza poleceń.

--dump-dom

Flaga --dump-dom wyświetla zserializowany DOM strony docelowej w standardowy sposób. Oto przykład:

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

Różni się to od zwykłego drukowania kodu źródłowego HTML (możesz to zrobić za pomocą funkcji curl). Aby wyświetlić dane wyjściowe z --dump-dom, Chrome najpierw analizuje kod HTML w elemencie DOM, wykonuje wszystkie elementy <script>, które mogą zmienić DOM, a następnie zamienia ten DOM z powrotem w zserializowany ciąg kodu HTML.

--screenshot

Flaga --screenshot tworzy zrzut ekranu strony docelowej i zapisuje ją jako screenshot.png w bieżącym katalogu roboczym. Jest to szczególnie przydatne w połączeniu z flagą --window-size. Oto przykład:

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

--print-to-pdf

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

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

Opcjonalnie możesz dodać flagę --no-pdf-header-footer, aby pominąć nagłówek (z aktualną 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/

--timeout

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

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

Flaga --timeout=5000 informuje Chrome, że przed wydrukowaniem pliku PDF może minąć do 5 sekund. Z tego względu proces ten trwa nie dłużej niż 5 sekund.

--virtual-time-budget

--virtual-time-budget umożliwia podróżowanie w czasie Cóż, w pewnym stopniu. Czas wirtualny działa jak „przewinięcie do przodu” w przypadku każdego kodu zależnego od czasu (np. setTimeout/setInterval). Powoduje, że przeglądarka wymusza na przeglądarce jak najszybsze wykonywanie kodu strony, a jednocześnie powoduje przekonanie, że czas rzeczywiście upływa.

Aby zilustrować jego zastosowanie, obejrzyj tę stronę demonstracyjną, która zwiększa, rejestruje 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 1 sekundzie na stronie pojawia się „1”, po dwóch sekundach „2” itd. Aby przechwycić stan strony po upływie 42 sekund i zapisać go 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 można było 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

Ponieważ w trybie bez interfejsu graficznego Chrome jest niewidoczny, określenie, co się dzieje w przypadku problemów, może wydawać się trudne. Na szczęście można debugować Chrome bez interfejsu graficznego w sposób bardzo podobny do tego w Chrome. Chodzi o to, aby uruchomić Chrome w trybie bez interfejsu graficznego z flagą --remote-debugging-port w wierszu poleceń.

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

Spowoduje to wydrukowanie niepowtarzalnego adresu URL WebSocket jako standardowego wyjścia, na przykład:

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

W zwykłej instancji Chrome z nagłówkiem możemy użyć zdalnego debugowania z Chrome DevTools, aby połączyć się z celem bez interfejsu graficznego i go sprawdzić. Aby to zrobić, przejdź do chrome://inspect, kliknij przycisk Konfiguruj... i wpisz adres IP oraz numer portu z adresu URL WebSocket. W powyższym przykładzie jest to 127.0.0.1:60926. Kliknij Gotowe. Powinien wyświetlić się cel zdalny ze wszystkimi kartami i innymi elementami docelowymi wymienionymi poniżej. Kliknij inspect, aby uzyskać dostęp do Narzędzi deweloperskich w Chrome i sprawdzić zdalny cel bez interfejsu graficznego, inspect.

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

Prześlij opinię

Chętnie poznamy Twoją opinię o nowym trybie bez interfejsu graficznego. Jeśli napotkasz jakieś problemy, zgłoś je.