Gözetimsiz Chrome'u Kullanmaya Başlama

Eric Bidelman

.

Özet

Gözetimsiz Chrome, Chrome 59 sürümünde kullanıma sunuluyor. Bu, Chrome tarayıcıyı gözetimsiz bir ortamda çalıştırmanın bir yoludur. Temelde, Chrome'u Chrome olmadan çalıştırmak! Chromium ve Blink oluşturma motorunun sağladığı tüm modern web platformu özelliklerini komut satırına taşır.

Neden faydalı oldu?

Gözetimsiz tarayıcı, görünür bir kullanıcı arayüzü kabuğuna ihtiyaç duymadığınız otomatik test ve sunucu ortamları için harika bir araçtır. Örneğin, gerçek bir web sayfası üzerinde bazı testler yapmak, bunun bir PDF dosyasını oluşturmak veya sadece tarayıcının bir URL'yi nasıl oluşturduğunu incelemek isteyebilirsiniz.

Gözetimsiz (CLI) başlatılıyor

Gözetimsiz modu kullanmaya başlamanın en kolay yolu, Chrome ikili programını 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üklemenize işaret etmelidir. Kesin konum, platformdan platforma değişiklik gösterecektir. Mac'te olduğumdan, yüklediğim her Chrome sürümü için pratik takma adlar oluşturdum.

Chrome'un mevcut ürün kanalını kullanıyor ve Beta sürümünü alamıyorsanız chrome-canary 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, gözetimsiz Chrome'u programatik şekilde kodlamanız gerekmeyebilir. Yaygın görevleri gerçekleştirmek için bazı kullanışlı komut satırı işaretleri vardır.

DOM'yi 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 arıyorsanız işler biraz daha karmaşıktır. David Schnurr'dan harika bir blog yayını var. Gözetimsiz Chrome'u otomatik ekran görüntüsü aracı olarak kullanma konusuna göz atın.

REPL modu (oku-eval-yazdırma döngüsü)

--repl işareti, JS ifadelerini doğrudan komut satırından tarayıcıda değerlendirebileceğiniz bir modda çalışı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ıklanıyor mu?

Chrome'u --remote-debugging-port=9222 ile çalıştırdığınızda, DevTools protokolü etkinleştirilmiş bir örnek başlatır. Protokol, Chrome ile iletişim kurmak ve gözetimsiz tarayıcı örneğini çalıştırmak için kullanılır. Ayrıca Sublime, VS Code ve Node gibi araçların uygulamalarda uzaktan hata ayıklaması için de kullandığı araçlardır. #synergy

Sayfayı görmek için tarayıcı kullanıcı arayüzünüz olmadığından, her şeyin çalışıp çalışmadığını kontrol etmek için başka bir tarayıcıda http://localhost:9222 adresine gidin. İncelenebilir sayfaların bir listesini burada tıklayarak ilgili sayfaları tıklayıp Gözetimsiz'in ne oluşturduğunu görebilirsiniz:

Geliştirici Araçları Uzaktan Kumandası
Geliştirici Araçları uzaktan hata ayıklama kullanıcı arayüzü

Buradan, sayfayı her zamanki gibi denetlemek, hata ayıklamak ve ince ayar yapmak için bilindik Geliştirici Araçları özelliklerini kullanabilirsiniz. Headless'i programatik olarak kullanıyorsanız bu sayfa, tüm ham DevTools protokol komutlarını kablodan geçerek tarayıcıyla iletişim kurmak için de kullanabileceğiniz güçlü bir hata ayıklama aracıdır.

Programlı olarak kullanma (Düğüm)

Kuklacı

Puppeteer, Chrome ekibi tarafından geliştirilen bir Düğüm kitaplığıdır. Gözetimsiz (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ümleriyle çalışır.

Puppeteer, başka işlevlerinin yanı sıra kolayca ekran görüntüsü almak, PDF oluşturmak, sayfalarda gezinmek ve bu sayfalar hakkında bilgi getirmek için kullanılabilir. Tarayıcı testini hızlı bir şekilde otomatikleştirmek istiyorsanız kitaplığı kullanmanızı öneririz. DevTools protokolünün karmaşıklığını ortadan kaldırır ve Chrome'un hata ayıklama örneğini başlatmak gibi gereksiz görevleri yerine getirir.

Yükleyin:

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

Tam API 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üzeyde bir kitaplıktır. Metal kullanmaya yakın olmak ve doğrudan DevTools protokolünü kullanmak istiyorsanız bu seçeneği öneririz.

Chrome başlatılıyor

chrome-remote-interface Chrome'u sizin için başlatmaz, dolayısıyla bununla sizin ilgilenmeniz gerekir.

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

Bunun bir yolu child_process kullanmaktır:

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 çok platformda çalışan taşınabilir bir çözüm istediğinizde işler zorlaşabilir. Chrome'un kodu içeren bu yola bakın :(

ChromeLauncher'ı kullanma

Lighthouse, web uygulamalarınızın kalitesini test etmek için harika bir araçtır. Lighthouse'da Chrome'u başlatmak için sağlam bir modül 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 sonlandırır. En iyi yanı da Node sayesinde farklı platformlarda çalışmasıdır.

Varsayılan olarak, chrome-launcher, Chrome Canary'yi başlatmayı dener (yüklüyse) ancak bunu değiştirerek hangi Chrome'un kullanılacağını manuel olarak seçebilirsiniz. Kullanmak için önce npm'den yükleyin:

npm i --save chrome-launcher

Örnek - Headless'i başlatmak için chrome-launcher kullanma

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ırmak pek işe yaramaz ancak about:blank uygulamasını yükleyen görev yöneticisinde Chrome'un bir örneğinin etkinleştiğini göreceksiniz. Unutmayın, herhangi bir tarayıcı arayüzü olmaz. Gözetimimiz yok.

Tarayıcıyı kontrol etmek için Geliştirici Araçları protokolüne ihtiyacımız vardır.

Sayfa hakkında bilgi alma

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']);
});

Şuna benzer bir sonuçla sonuçlanır: HeadlessChrome/60.0.3082.0

Örnek - Sitenin 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 çıkarı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

Şu anda Selenium, Chrome'un tam örneğini açıyor. Başka bir deyişle, bu otomatik bir çözümdür, ancak tamamen gözetimsiz değildir. Ancak Selenium, gözetimsiz Chrome'u biraz çalışarak çalıştıracak şekilde yapılandırılabilir. Ayarları kendi başınıza nasıl yapacağınızla ilgili tüm talimatları görmek isterseniz Selenium'u gözetimsiz Chrome ile çalıştırmayı öneririz. Ancak başlamanıza yardımcı olmak için aşağıya bazı örnekler ekledik.

ChromeDriver'ı kullanma

ChromeDriver 2.32, Chrome 61 sürümünü kullanır ve gözetimsiz Chrome ile iyi bir şekilde ç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 üzerine yer alan daha yüksek düzey bir API'dir.

Yükleme:

npm i --save-dev webdriverio chromedriver

Örnek: chromestatus.com adresindeki 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şlamanıza yardımcı olacak bazı yararlı kaynakları aşağıda bulabilirsiniz:

Belgeler

Araçlar

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

Demolar

  • "The Headless Web" - Paul Kinlan'ın Headless'i api.ai ile kullanma hakkındaki harika blog yayını.

SSS

--disable-gpu işaretini kullanmam gerekir mi?

Yalnızca Windows'da. Diğer platformlar için artık gerekli değil. --disable-gpu işareti, birkaç hatayla ilgili geçici bir çözümdür. Chrome'un gelecekteki sürümlerinde bu işarete ihtiyacınız olmayacaktır. Daha fazla bilgi için crbug.com/737678 adresini inceleyin.

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

Hayır. Gözetimsiz Chrome'da pencere kullanılmadığı için Xvfb gibi bir görüntülü reklam sunucusuna ihtiyaç yoktur. Bu olmadan da otomatik testlerinizi yapabilirsiniz.

Xvfb nedir? Xvfb, fiziksel bir ekran olmadan grafik uygulamaları (Chrome gibi) çalıştırabilmenizi sağlayan, Unix benzeri sistemler için kullanılan bir bellek içi görüntüleme sunucusudur. Birçok kişi "gözetimsiz" testler gerçekleştirmek üzere Chrome'un önceki sürümlerini çalıştırmak için Xvfb'yi kullanır.

Gözetimsiz Chrome çalıştıran Docker container'ını nasıl oluşturabilirim?

window-ci'ye göz atın. Temel görüntü olarak node:8-slim kullanan örnek bir Dockerfile vardır ve App Engine Flex'te Lighthouse'u ve Lighthouse'u çalıştırır.

Bunu Selenium / WebDriver / ChromeDriver ile kullanabilir miyim?

Evet. Selenium, WebDriver ve ChromeDriver'ı kullanma başlıklı makaleye bakın.

Bunun PhantomJS ile ne ilgisi var?

Gözetimsiz Chrome, PhantomJS gibi araçlara benzer. Her ikisi de gözetimsiz bir 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ü kullanırken, Headless Chrome'un Blink'in en son sürümünü kullanmasıdır.

Phantom şu anda DevTools protokolü'nden daha yüksek düzeyde bir API sunuyor.

Hataları nereye bildirebilirim?

Headless Chrome ile ilgili hataları crbug.com adresinden kaydedin.

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