Shell Chrome Headless

Shell Headless Chrome dikirimkan di Chrome 59. Ini adalah cara untuk menjalankan browser Chrome di lingkungan headless. Pada dasarnya, menjalankan Chrome tanpa Chrome. Node.js menghadirkan semua fitur platform web modern yang disediakan oleh Chromium dan mesin rendering Blink ke command line.

Browser headless adalah alat yang sangat baik untuk pengujian otomatis dan lingkungan server yang tidak memerlukan shell UI yang terlihat. Misalnya, Anda mungkin ingin menjalankan beberapa pengujian terhadap halaman web asli, membuat PDF-nya, atau hanya memeriksa cara browser merender URL.

Memulai Headless (CLI)

Cara termudah untuk mulai menggunakan mode headless adalah dengan membuka biner Chrome dari command line. Jika Anda telah menginstal Chrome 59+, mulai Chrome dengan tanda --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 harus mengarah ke penginstalan Chrome Anda. Lokasi persis akan bervariasi dari platform ke platform. Karena saya menggunakan Mac, saya membuat alias yang mudah untuk setiap versi Chrome yang telah saya instal.

Jika Anda menggunakan Chrome versi stabil dan tidak bisa mendapatkan versi Beta, gunakan 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"

Download Chrome Canary.

Fitur command line

Dalam beberapa kasus, Anda mungkin tidak perlu membuat skrip secara terprogram Chrome Headless. Ada beberapa flag command line yang berguna untuk melakukan tugas umum.

Mencetak DOM

Flag --dump-dom mencetak document.body.innerHTML ke stdout:

    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/

Mengambil screenshot

Untuk mengambil screenshot halaman, gunakan tanda --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/

Menjalankan dengan --screenshot akan menghasilkan file bernama screenshot.png di direktori kerja saat ini. Jika Anda mencari screenshot halaman penuh, langkah-langkahnya sedikit lebih rumit. Ada postingan blog bagus dari David Schnurr yang membahasnya. Lihat Menggunakan Chrome headless sebagai alat screenshot otomatis .

Mode REPL (read-eval-print loop)

Tanda --repl menjalankan Headless dalam mode yang memungkinkan Anda mengevaluasi ekspresi JS di browser, langsung dari command line:

$ 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
$

Melakukan proses debug Chrome tanpa UI browser?

Saat Anda menjalankan Chrome dengan --remote-debugging-port=9222, Chrome akan memulai instance dengan DevTools protocol yang diaktifkan. Protokol digunakan untuk berkomunikasi dengan Chrome dan menjalankan instance browser tanpa tampilan. Ini juga yang digunakan alat seperti Sublime, VS Code, dan Node untuk men-debug aplikasi dari jarak jauh. #synergy

Karena Anda tidak memiliki UI browser untuk melihat halaman, buka http://localhost:9222 di browser lain untuk memeriksa apakah semuanya berfungsi. Anda akan melihat daftar halaman yang dapat diperiksa, tempat Anda dapat mengklik dan melihat apa yang dirender Headless:

Remote DevTools
UI debug jarak jauh DevTools

Dari sini, Anda dapat menggunakan fitur DevTools yang sudah dikenal untuk memeriksa, men-debug, dan menyesuaikan halaman seperti yang biasa Anda lakukan. Jika Anda menggunakan Headless secara terprogram, halaman ini juga merupakan alat proses debug yang efektif untuk melihat semua perintah protokol DevTools mentah yang dikirim melalui jaringan, yang berkomunikasi dengan browser.

Menggunakan secara terprogram (Node)

Puppeteer

Puppeteer adalah library Node yang dikembangkan oleh tim Chrome. Puppeteer menyediakan API tingkat tinggi untuk mengontrol Chrome headless (atau penuh). Fitur ini mirip dengan library pengujian otomatis lainnya seperti Phantom dan NightmareJS, tetapi hanya berfungsi dengan Chrome versi terbaru.

Selain hal lainnya, Puppeteer dapat digunakan untuk mengambil screenshot dengan mudah, membuat PDF, membuka halaman, dan mengambil informasi tentang halaman tersebut. Saya merekomendasikan library ini jika Anda ingin mengotomatiskan pengujian browser dengan cepat. Library ini menyembunyikan kompleksitas protokol DevTools dan menangani tugas-tugas yang berlebihan seperti meluncurkan instance debug Chrome.

Instal:

npm i --save puppeteer

Contoh - mencetak agen pengguna

const puppeteer = require('puppeteer');

(async() => {
  const browser = await puppeteer.launch();
  console.log(await browser.version());
  await browser.close();
})();

Contoh - mengambil screenshot halaman

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

Lihat dokumentasi Puppeteer untuk mempelajari lebih lanjut API lengkapnya.

Library CRI

chrome-remote-interface adalah library tingkat yang lebih rendah daripada API Puppeteer. Saya merekomendasikannya jika Anda ingin berinteraksi langsung dengan hardware dan menggunakan protokol DevTools secara langsung.

Meluncurkan Chrome

chrome-remote-interface tidak meluncurkan Chrome untuk Anda, jadi Anda harus menanganinya sendiri.

Di bagian CLI, kita memulai Chrome secara manual menggunakan --headless --remote-debugging-port=9222. Namun, untuk mengotomatiskan pengujian sepenuhnya, Anda mungkin ingin memunculkan Chrome dari aplikasi Anda.

Salah satu caranya adalah dengan menggunakan 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) => {
  ...
});

Namun, semuanya menjadi rumit jika Anda menginginkan solusi portabel yang berfungsi di beberapa platform. Lihat saja jalur hard-coded ke Chrome itu :(

Menggunakan ChromeLauncher

Lighthouse adalah alat yang luar biasa untuk menguji kualitas aplikasi web Anda. Modul yang andal untuk meluncurkan Chrome dikembangkan dalam Lighthouse dan kini diekstrak untuk penggunaan mandiri. Modul NPM chrome-launcher akan menemukan tempat Chrome diinstal, menyiapkan instance debug, meluncurkan browser, dan menghentikannya saat program Anda selesai. Bagian terbaiknya adalah aplikasi ini berfungsi lintas platform berkat Node.js.

Secara default, chrome-launcher akan mencoba meluncurkan Chrome Canary (jika diinstal), tetapi Anda dapat mengubahnya untuk memilih Chrome yang akan digunakan secara manual. Untuk menggunakannya, instal terlebih dahulu dari npm:

npm i --save chrome-launcher

Contoh - menggunakan chrome-launcher untuk meluncurkan Headless

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

Menjalankan skrip ini tidak akan melakukan banyak hal, tetapi Anda akan melihat instance Chrome terbuka di pengelola tugas yang memuat about:blank. Ingat, tidak akan ada UI browser. Kami headless.

Untuk mengontrol browser, kita memerlukan protokol DevTools.

Mengambil informasi tentang halaman

Untuk menginstal library:

npm i --save chrome-remote-interface
Contoh

Contoh - mencetak agen pengguna

const CDP = require('chrome-remote-interface');

...

launchChrome().then(async chrome => {
  const version = await CDP.Version({port: chrome.port});
  console.log(version['User-Agent']);
});

Hasilnya akan seperti: HeadlessChrome/60.0.3082.0

Contoh - periksa apakah situs memiliki manifes aplikasi web

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.
});

})();

Contoh - ekstrak <title> halaman menggunakan 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.
});

})();

Menggunakan Selenium, WebDriver, dan ChromeDriver

Saat ini, Selenium membuka instance Chrome lengkap. Dengan kata lain, ini adalah solusi otomatis, tetapi tidak sepenuhnya tanpa UI. Namun, Selenium dapat dikonfigurasi untuk menjalankan Chrome tanpa UI dengan sedikit upaya. Sebaiknya Jalankan Selenium dengan Chrome Headless jika Anda ingin petunjuk lengkap tentang cara menyiapkan semuanya sendiri, tetapi saya telah menyertakan beberapa contoh di bawah untuk membantu Anda memulai.

Menggunakan ChromeDriver

ChromeDriver 2.32 menggunakan Chrome 61 dan berfungsi dengan baik dengan Chrome headless.

Instal:

npm i --save-dev selenium-webdriver chromedriver

Contoh:

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

Menggunakan WebDriverIO

WebDriverIO adalah API tingkat yang lebih tinggi di atas Selenium WebDriver.

Instal:

npm i --save-dev webdriverio chromedriver

Contoh: memfilter fitur CSS di 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();

})();

Download Chrome Headless lama sebagai chrome-headless-shell

Mulai Chrome versi 112, mode Headless baru Chrome (--headless=new) tersedia. Mode ini memungkinkan developer menjalankan Chrome itu sendiri, bukan biner terpisah di lingkungan tanpa pengawasan tanpa UI yang terlihat—berguna untuk kasus penggunaan pengujian dan otomatisasi.

Ada kasus penggunaan yang berbeda untuk shell headless lama dan mode Headless baru:

  1. Shell Headless lama adalah wrapper ringan di sekitar modul //content Chromium, sehingga memiliki jauh lebih sedikit dependensi. Secara khusus, browser ini tidak memerlukan X11/Wayland, D-Bus, dan dalam beberapa hal lebih berperforma daripada browser Chrome yang lengkap. Hal ini membuatnya cocok untuk kasus penggunaan seperti pengambilan screenshot otomatis atau scraping web.
  2. Di sisi lain, mode Headless baru adalah browser Chrome yang sebenarnya, sehingga lebih autentik, andal, dan menawarkan lebih banyak fitur. Hal ini membuatnya lebih cocok untuk pengujian aplikasi web end-to-end atau pengujian ekstensi browser dengan akurasi tinggi.

Dengan kata lain, ada kompromi antara performa dan keaslian. Mode Headless mana yang paling sesuai untuk Anda? Hal ini bergantung pada kasus penggunaan Anda.

Diagram yang menggambarkan informasi yang diberikan dalam daftar sebelumnya.

Developer dan penguji yang tidak memerlukan fungsi Chrome lengkap untuk kasus penggunaan otomatisasi mereka mungkin ingin menggunakan Headless lama. Jika tidak, Headless baru kemungkinan adalah pilihan terbaik.

Untuk memastikan developer dan penguji terus memiliki pilihan antara dua opsi ini, dengan senang hati kami mengumumkan bahwa implementasi Headless lama kini tersedia sebagai biner chrome-headless-shell mandiri. Biner chrome-headless-shell baru ini dibuat untuk setiap rilis Chrome yang ditujukan bagi pengguna, dan tersedia untuk didownload melalui infrastruktur Chrome for Testing mulai dari Chrome 120.

Bagaimana cara mendapatkan biner chrome-headless-shell?

Seperti biner Chrome for Testing lainnya, cara termudah untuk mendownload chrome-headless-shell untuk platform Anda adalah dengan menggunakan utilitas command line @puppeteer/browsers kami, yang tersedia menggunakan npm. Berikut beberapa contohnya:

# 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

Jika Anda lebih suka membuat skrip otomatis sendiri untuk mendownload biner chrome-headless-shell, kami siap membantu. Chrome for Testing menawarkan endpoint JSON API dengan versi terbaru yang tersedia per saluran rilis Chrome (Stabil, Beta, Dev, dan Canary). Untuk mendapatkan ringkasan singkat tentang status terbaru, lihat dasbor ketersediaan Chrome for Testing.

Masukan

Kami menantikan masukan Anda tentang chrome-headless-shell. Jika Anda mengalami masalah, jangan ragu untuk melaporkannya.

Aset lainnya

Berikut beberapa referensi berguna untuk membantu Anda memulai:

Dokumen

Alat

  • chrome-remote-interface - modul node yang membungkus protokol DevTools
  • Lighthouse - alat otomatis untuk menguji kualitas aplikasi web; banyak menggunakan protokol
  • chrome-launcher - modul node untuk meluncurkan Chrome, siap untuk otomatisasi

Demo

  • "The Headless Web" - Postingan blog menarik dari Paul Kinlan tentang penggunaan Headless dengan api.ai.

FAQ

Apakah saya memerlukan flag --disable-gpu?

Hanya di Windows. Platform lain tidak lagi memerlukannya. Flag --disable-gpu adalah solusi sementara untuk beberapa bug. Anda tidak akan memerlukan tanda ini di Chrome versi mendatang. Lihat crbug.com/737678 untuk mengetahui informasi selengkapnya.

Jadi, saya masih memerlukan Xvfb?

Tidak. Chrome Headless tidak menggunakan jendela sehingga server tampilan seperti Xvfb tidak diperlukan lagi. Anda dapat menjalankan pengujian otomatis dengan lancar tanpa menggunakannya.

Apa itu Xvfb? Xvfb adalah server tampilan dalam memori untuk sistem mirip Unix yang memungkinkan Anda menjalankan aplikasi grafis (seperti Chrome) tanpa tampilan fisik yang terpasang. Banyak orang menggunakan Xvfb untuk menjalankan Chrome versi sebelumnya guna melakukan pengujian "headless".

Bagaimana cara membuat container Docker yang menjalankan Headless Chrome?

Lihat lighthouse-ci. Contoh ini memiliki Dockerfile contoh yang menggunakan node:8-slim sebagai image dasar, menginstal + menjalankan Lighthouse di App Engine Flex.

Dapatkah saya menggunakannya dengan Selenium / WebDriver / ChromeDriver?

Ya. Lihat Menggunakan Selenium, WebDriver, dan ChromeDriver.

Bagaimana kaitannya dengan PhantomJS?

Chrome Headless mirip dengan alat seperti PhantomJS. Keduanya dapat digunakan untuk pengujian otomatis di lingkungan tanpa antarmuka. Perbedaan utama antara keduanya adalah Phantom menggunakan WebKit versi lama sebagai mesin rendering-nya, sedangkan Chrome Headless menggunakan Blink versi terbaru.

Saat ini, Phantom juga menyediakan API tingkat yang lebih tinggi daripada protokol DevTools.

Di mana saya dapat melaporkan bug?

Untuk bug terhadap Headless Chrome, laporkan di crbug.com.

Untuk bug di protokol DevTools, laporkan di github.com/ChromeDevTools/devtools-protocol.