Gözetimsiz Chrome'u Kullanmaya Başlama

başlıklı makaleyi okuyarak daha fazla bilgi edinin.

Özet

Gözetimsiz Chrome, Chrome 59'da kullanıma sunulmuştur. Chrome Tarayıcı'yı başsız bir ortamda çalıştırmanın bir yoludur. Yani Chrome olmadan Chrome çalıştırıyorsunuz. Chromium ve Blink oluşturma motoru tarafından sağlanan tüm modern web platformu özelliklerini komut satırına getirir.

Bu neden yararlı?

Başsız tarayıcı, görünür bir kullanıcı arayüzü kabuğuna ihtiyaç duymadığınız otomatik test ve sunucu ortamları için mükemmel bir araçtır. Örneğin, gerçek bir web sayfasında bazı testler yapmak, sayfanın PDF'sini oluşturmak veya tarayıcının bir URL'yi nasıl oluşturduğunu incelemek isteyebilirsiniz.

Başlangıçsız (CLI)

Başsız modu kullanmaya başlamanın en kolay yolu, Chrome ikilisini komut satırından açmaktır. Chrome 59 veya sonraki bir sürümü yüklüyse Chrome'u --headless işaretiyle başlatın:

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, Chrome yüklemenizi gösterir. Tam konum, platformdan platforma değişiklik gösterir. Mac kullanıyorum. Bu nedenle, yüklediğim her Chrome sürümü için kullanışlı takma adlar oluşturdum.

Chrome'un kararlı kanalındaysanız ve Beta sürümünü kullanamıyorsanız chrome-canary'yi kullanmanızı öneririz:

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'yi buradan indirin.

Komut satırı özellikleri

Bazı durumlarda, Headless Chrome'u programlı olarak komut dosyası ile çalıştırmanız gerekmeyebilir. Yaygın görevleri gerçekleştirmek için bazı yararlı komut satırı işaretleri vardır.

DOM'u yazdırma

--dump-dom işareti, document.body.innerHTML değerini stdout'a yazdırır:

    chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/

PDF oluşturma

--print-to-pdf işareti, sayfanın PDF'sini oluşturur:

chrome --headless --disable-gpu --print-to-pdf https://www.chromestatus.com/

Ekran görüntüsü alma

Bir sayfanın ekran görüntüsünü almak için --screenshot işaretini kullanın:

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/

--screenshot ile çalıştırıldığında, mevcut çalışma dizininde screenshot.png adlı bir dosya oluşturulur. Tam sayfa ekran görüntüleri istiyorsanız biraz daha karmaşık bir işlem yapmanız gerekir. David Schnurr'un bu konuda yazdığı mükemmel bir blog yayını var. Gözetimsiz Chrome'u otomatik ekran görüntüsü aracı olarak kullanma başlıklı makaleyi inceleyin.

REPL modu (oku-değerlendir-yazdır döngüsü)

--repl işareti, Headless'i tarayıcıda JS ifadelerini doğrudan komut satırından değerlendirebileceğiniz bir modda çalıştırır:

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

Tarayıcı kullanıcı arayüzü olmadan Chrome'da hata ayıklama

Chrome'u --remote-debugging-port=9222 ile çalıştırdığınızda DevTools protokolü etkin bir örnek başlatılır. Bu protokol, Chrome ile iletişim kurmak ve gözetimsiz tarayıcı örneğini çalıştırmak için kullanılır. Sublime, VS Code ve Node gibi araçlar da bir uygulamada uzaktan hata ayıklama için bu protokolü kullanır. #synergy

Sayfayı görmek için tarayıcı kullanıcı arayüzünüz olmadığından, her şeyin çalıştığından emin olmak için başka bir tarayıcıda http://localhost:9222 bölümüne gidin. Tıklayıp Headless'ın neleri oluşturduğunu görebileceğiniz, incelenebilir sayfaların listesini görürsünüz:

DevTools Remote
DevTools uzaktan hata ayıklama kullanıcı arayüzü

Buradan, sayfayı normalde yaptığınız gibi incelemek, hata ayıklamak ve düzenlemek için bildiğiniz Geliştirici Araçları özelliklerini kullanabilirsiniz. Headless'ı programatik olarak kullanıyorsanız bu sayfa, tarayıcı ile iletişim kuran ve kablo üzerinden gönderilen tüm ham DevTools protokol komutlarını görmek için güçlü bir hata ayıklama aracıdır.

Programatik olarak kullanma (Node)

Kuklacı

Puppeteer, Chrome ekibi tarafından geliştirilmiş bir Node kitaplığıdır. Başsız (veya tam) Chrome'u kontrol etmek için üst düzey bir API sağlar. Phantom ve NightmareJS gibi diğer otomatik test kitaplıklarına benzer ancak yalnızca Chrome'un en son sürümlerinde çalışır.

Puppeteer, ekran görüntüsü almak, PDF oluşturmak, sayfalarda gezinmek ve bu sayfalarla ilgili bilgi almak için kullanılabilir. Tarayıcı testini hızlı bir şekilde otomatikleştirmek istiyorsanız kitaplığı kullanmanızı öneririm. DevTools protokolünün karmaşıklığını gizler ve Chrome'un hata ayıklama örneğini başlatma gibi gereksiz görevleri üstlenir.

Yükleme:

npm i --save puppeteer

Örnek: Kullanıcı aracısını yazdırma

const puppeteer = require('puppeteer');

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

Örnek: Sayfanın ekran görüntüsünü alma

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

API'nin tamamı hakkında daha fazla bilgi edinmek için Puppeteer belgelerine göz atın.

CRI kitaplığı

chrome-remote-interface, Puppeteer'ın API'sinden daha düşük düzey bir kitaplıktır. Metale yakın olmak ve doğrudan DevTools protokolünü kullanmak istiyorsanız bu yöntemi öneririz.

Chrome'u başlatma

chrome-remote-interface, Chrome'u sizin için başlatmaz. Bu nedenle, bu işlemi kendiniz yapmanız gerekir.

KSA bölümünde, --headless --remote-debugging-port=9222 kullanarak Chrome'u manuel olarak başlattık. Ancak testleri tamamen otomatikleştirmek için Chrome'u uygulamanızdan oluşturmak isteyebilirsiniz.

child_process kullanmak da bir yöntemdir:

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

Ancak birden fazla platformda çalışan taşınabilir bir çözüm istiyorsanız işler biraz zorlaşıyor. Chrome'un sabit kodlu yoluna bakın :(

ChromeLauncher'ı kullanma

Lighthouse, web uygulamalarınızın kalitesini test etmek için mükemmel bir araçtır. Chrome'u başlatmak için güçlü bir modül Lighthouse'ta geliştirildi ve artık bağımsız kullanım için ayıklandı. chrome-launcher NPM modülü, Chrome'un yüklü olduğu yeri bulur, bir hata ayıklama örneği oluşturur, tarayıcıyı başlatır ve programınız tamamlandığında tarayıcıyı kapatır. En iyi yanı, Node sayesinde platformlar arası olarak çalışmasıdır.

Varsayılan olarak chrome-launcher, Chrome Canary'ı (yüklüyse) başlatmaya çalışır ancak bu ayarı değiştirerek hangi Chrome sürümünün kullanılacağını manuel olarak seçebilirsiniz. Kullanmak için önce npm'den yükleyin:

npm i --save chrome-launcher

Örnek: Gözetimsiz modu başlatmak için chrome-launcher kullanılıyor

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

Bu komut dosyasını çalıştırmanın pek bir etkisi yoktur ancak görev yöneticisinde about:blank dosyasını yükleyen bir Chrome örneğinin başlatıldığını görürsünüz. Tarayıcı kullanıcı arayüzü olmayacağını unutmayın. Biz gözetimsiz bir ajansyız.

Tarayıcıyı kontrol etmek için DevTools protokolüne ihtiyacımız var.

Sayfa hakkında bilgi alma

gidin.

Kitaplığı yükleyelim:

npm i --save chrome-remote-interface
Örnekler

Örnek: Kullanıcı aracısını yazdırma

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

...

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

Sonuçlar şu şekilde görünür: HeadlessChrome/60.0.3082.0

Örnek: Sitede web uygulaması manifesti olup olmadığını kontrol edin.

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

})();

Örnek: DOM API'lerini kullanarak sayfanın <title> öğesini ayıklayın.

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

})();

Selenium, WebDriver ve ChromeDriver'ı kullanma

Selenium şu anda Chrome'un tam bir örneğini açıyor. Diğer bir deyişle, otomatik bir çözümdür ancak tamamen gözetimsiz değildir. Ancak Selenium, biraz çalışmayla gözetimsiz Chrome çalıştıracak şekilde yapılandırılabilir. Kurulumu kendiniz yapmayla ilgili tam talimatları görmek için Headless Chrome ile Selenium çalıştırma başlıklı makaleyi inceleyebilirsiniz. Başlamak için aşağıda bazı örnekler de verilmiştir.

ChromeDriver'ı kullanma

ChromeDriver 2.32, Chrome 61'i kullanır ve gözetimsiz Chrome ile iyi çalışır.

Yükleme:

npm i --save-dev selenium-webdriver chromedriver

Örnek:

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

WebDriverIO'yu kullanma

WebDriverIO, Selenium WebDriver'ın üzerinde daha üst düzey bir API'dir.

Yükleme:

npm i --save-dev webdriverio chromedriver

Örnek: chromestatus.com'da CSS özelliklerini filtreleme

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

})();

Diğer kaynaklar

Başlangıç için yararlı bazı kaynakları aşağıda bulabilirsiniz:

Belgeler

Araçlar

  • chrome-remote-interface: DevTools protokolünü sarmalayan Node modülü
  • Lighthouse: Web uygulaması kalitesini test etmek için kullanılan otomatik araç; protokolü yoğun şekilde kullanır
  • chrome-launcher: Chrome'u başlatmak için kullanılan, otomasyona hazır node modülü

Demolar

  • "Başsız Web": Paul Kinlan'ın api.ai ile Headless'i kullanmayla ilgili mükemmel blog yayını.

SSS

--disable-gpu işaretine ihtiyacım var mı?

Yalnızca Windows'ta. Diğer platformlar artık bu ek sürümlere ihtiyaç duymaz. --disable-gpu işareti, birkaç hatayla ilgili geçici bir çözümdür. Chrome'un gelecek sürümlerinde bu işarete ihtiyacınız olmayacak. Daha fazla bilgi için crbug.com/737678 adresine bakın.

Xvfb'ye hâlâ ihtiyacım var mı?

Hayır. Başsız Chrome pencere kullanmadığından Xvfb gibi bir görüntü sunucusu artık gerekli değildir. Otomatik testlerinizi bu olmadan da çalıştırabilirsiniz.

Xvfb nedir? Xvfb, Unix benzeri sistemler için bellek içi bir ekran sunucusudur. Bu sunucu, Chrome gibi grafik uygulamaları çalıştırmanıza fiziksel ekran olmadan olanak tanır. Birçok kullanıcı, "gözetimsiz" test yapmak için Chrome'un eski sürümlerini çalıştırmak üzere Xvfb'yi kullanır.

Headless Chrome çalıştıran bir Docker kapsayıcı nasıl oluşturabilirim?

lighthouse-ci'ye göz atın. Temel görüntü olarak node:8-slim kullanan, App Engine Flex'te Lighthouse'u çalıştıran ve yükleyen bir örnek Dockerfile içerir.

Bu aracı Selenium / WebDriver / ChromeDriver ile kullanabilir miyim?

Evet. Selenium, WebDriver ve ChromeDriver'ı kullanma başlıklı makaleyi inceleyin.

Bu, PhantomJS ile nasıl ilişkilidir?

Gözetimsiz Chrome, PhantomJS gibi araçlara benzer. Her ikisi de headless ortamda otomatik test için kullanılabilir. İkisi arasındaki temel fark, Phantom'un oluşturma motoru olarak WebKit'in eski bir sürümünü kullanması, Headless Chrome'un ise Blink'in en son sürümünü kullanmasıdır.

Phantom şu anda DevTools protokolünden daha yüksek düzeyde bir API de sağlıyor.

Hataları nereye bildirebilirim?

Gözetimsiz Chrome ile ilgili hataları crbug.com adresinden bildirebilirsiniz.

DevTools protokolündeki hataları github.com/ChromeDevTools/devtools-protocol adresinden bildirebilirsiniz.