헤드리스 Chrome 시작하기

요약

헤드리스 Chrome Chrome 59에서 출시됩니다. 헤드리스 환경에서 Chrome 브라우저를 실행하는 방법입니다. 기본적으로 Chrome이 없어도 Chrome을 사용할 수 있습니다. 모든 최신 웹 플랫폼 기능을 제공합니다. Chromium과 Blink 렌더링 엔진이 명령줄에 전송합니다.

왜 유용한가요?

헤드리스 브라우저는 자동화된 테스트 및 서버 환경을 위한 훌륭한 도구입니다. 가시적 UI 셸이 필요하지 않습니다. 예를 들어, nginx 웹 서버의 PDF를 만들거나, 브라우저가 URL을 렌더링하는 방법을 검사할 수 있습니다.

헤드리스 (CLI) 시작

헤드리스 모드를 시작하는 가장 쉬운 방법은 Chrome 바이너리를 여는 것입니다. gcloud 명령어입니다 Chrome 59 이상이 설치되어 있다면 --headless 플래그로 Chrome을 시작합니다.

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을 가리켜야 합니다. 정확한 위치는 플랫폼마다 다릅니다 Mac을 사용 중이므로 편리한 별칭을 만들어 두었습니다. 설치할 수 있습니다.

Chrome의 공개 버전 채널을 사용 중이며 베타 버전을 다운로드할 수 없는 경우 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"

여기에서 Chrome Canary를 다운로드합니다.

명령줄 기능

경우에 따라 헤드리스 Chrome을 프로그래매틱 방식으로 스크립팅할 필요가 없을 수도 있습니다. 몇 가지 유용한 명령줄 플래그가 있습니다. 일반적인 작업을 수행할 수 있습니다

DOM 인쇄

--dump-dom 플래그는 document.body.innerHTML를 stdout에 출력합니다.

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

PDF 만들기

--print-to-pdf 플래그는 페이지의 PDF를 만듭니다.

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

스크린샷 촬영

페이지 스크린샷을 캡처하려면 --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/

--screenshot로 실행하면 screenshot.png라는 파일이 현재 작업 디렉터리에 있습니다 전체 페이지 스크린샷을 찾는 경우 조금 더 관여할 수 있습니다 멋진 블로그가 있습니다. David Schnurr의 게시물입니다. 결제 헤드리스 Chrome을 자동 스크린샷 도구로 사용

REPL 모드 (read-eval-print 루프)

--repl 플래그는 JS 표현식을 평가할 수 있는 모드에서 헤드리스를 실행합니다. 를 입력합니다.

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

브라우저 UI 없이 Chrome을 디버깅하시나요?

--remote-debugging-port=9222로 Chrome을 실행하면 인스턴스가 시작됩니다. DevTools 프로토콜을 활성화해야 합니다. 이 프로토콜은 Chrome과 통신하고 헤드리스 브라우저 인스턴스 또한 Sublime, VS Code 및 Node와 같은 도구는 디버깅할 수 있습니다. #synergy

페이지를 볼 수 있는 브라우저 UI가 없으므로 http://localhost:9222로 이동합니다. 다른 브라우저에서 모든 것이 제대로 작동하는지 확인합니다. 이 페이지에서 검사 가능한 페이지가 있습니다. 이 페이지를 클릭하면 헤드리스가 렌더링하는 것을 확인할 수 있습니다.

<ph type="x-smartling-placeholder">
</ph> DevTools 리모컨 <ph type="x-smartling-placeholder">
</ph> DevTools 원격 디버깅 UI

여기에서 익숙한 DevTools 기능을 사용하여 검사, 디버그, 조정을 수행할 수 있습니다. 페이지가 표시됩니다. 프로그래매틱 방식으로 헤드리스를 사용하는 경우 페이지는 모든 원시 DevTools 프로토콜을 볼 수 있는 강력한 디버깅 도구이기도 합니다. 브라우저와 통신합니다.

프로그래매틱 방식으로 사용 (노드)

인형 조종자

Puppeteer는 노드 라이브러리입니다. Chrome팀에서 개발한 것입니다. 헤드리스를 제어하는 상위 수준 API를 제공합니다. (또는 전체) Chrome. 이는 Phantom과 같은 다른 자동화된 테스트 라이브러리와 유사합니다. 및 NightmareJS, 최신 버전의 Chrome에서만 작동합니다.

무엇보다도 Puppeteer를 사용하면 쉽게 스크린샷을 찍고, PDF를 만들고, 페이지를 탐색하고 해당 페이지에 관한 정보를 가져올 수 있습니다. 도서관 추천 브라우저 테스트를 신속하게 자동화하려는 경우 복잡한 부분을 가립니다. DevTools 프로토콜의 기능을 확인하고, 도구 실행과 같은 디버그 인스턴스입니다.

설치합니다.

npm i --save puppeteer

- 사용자 에이전트 출력

const puppeteer = require('puppeteer');

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

- 페이지 스크린샷 찍기

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

Puppeteer 문서 확인 전체 API에 대해 자세히 알아보세요.

CRI 라이브러리

chrome-remote-interface Puppeteer API보다 하위 수준 라이브러리입니다. 당신이 되고 싶으시다면 DevTools 프로토콜을 직접 사용할 수도 있습니다.

Chrome 실행하기

chrome-remote-interface는 Chrome을 실행하지 않으므로 직접 돌볼 수도 있습니다.

CLI 섹션에서 다음을 사용하여 Chrome을 수동으로 시작했습니다. --headless --remote-debugging-port=9222입니다. 그러나 테스트를 완전히 자동화하려면 애플리케이션 에서 Chrome을 실행하려고 합니다.

한 가지 방법은 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) => {
  ...
});

하지만 여러 기기에서 작동하는 포팅 가능한 솔루션을 원한다면 지원합니다 하드 코딩된 Chrome 경로를 살펴보세요.

ChromeLauncher 사용

Lighthouse는 놀랍습니다 웹 앱의 품질을 테스트하는 도구입니다. 출시를 위한 강력한 모듈 Chrome은 Lighthouse 내에서 개발되었으며 이제 독립형으로 사용할 수 있도록 추출되었습니다. chrome-launcher NPM 모듈 는 Chrome이 설치되고, 디버그 인스턴스를 설정하고, 브라우저를 실행한 후 종료됩니다. 표시됩니다. 가장 큰 장점은 노드!

기본적으로 chrome-launcher에서 Chrome Canary를 시작하려고 시도합니다 (Chrome Canary가 사용할 Chrome을 수동으로 선택하도록 변경할 수 있습니다. 받는사람 사용하려면 먼저 npm에서 설치합니다.

npm i --save chrome-launcher

- chrome-launcher를 사용하여 헤드리스 실행

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

이 스크립트를 실행해도 별다른 문제는 없지만 about:blank를 로드한 작업 관리자에서 Chrome이 실행됩니다. 기억하세요, 브라우저 UI가 없습니다. 우리는 머리가 없습니다.

브라우저를 제어하려면 DevTools 프로토콜이 필요합니다.

페이지에 대한 정보 검색

라이브러리를 설치해 보겠습니다.

npm i --save chrome-remote-interface

- 사용자 에이전트 출력

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

...

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

다음과 유사한 결과가 표시됩니다. HeadlessChrome/60.0.3082.0

- 사이트에 웹 앱 매니페스트가 있는지 확인

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

})();

- DOM API를 사용하여 페이지의 <title>를 추출합니다.

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, ChromeDriver 사용

현재 Selenium은 Chrome 전체 인스턴스를 엽니다. 다시 말해 완전한 헤드리스는 아닙니다. 하지만 Selenium은 헤드리스 Chrome을 실행하도록 구성되어 있습니다. 추천 헤드리스 Chrome으로 Selenium 실행하기 원하는 경우 설정하는 방법에 대한 전체 안내문을 일부 추가했습니다. 아래의 예를 참조하세요.

ChromeDriver 사용

ChromeDriver 2.32 Chrome 61을 사용하며 헤드리스 Chrome과 잘 호환됩니다.

설치합니다.

npm i --save-dev selenium-webdriver chromedriver

예:

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 사용

WebDriverIO는 Selenium WebDriver를 기반으로 하는 상위 수준 API입니다.

설치합니다.

npm i --save-dev webdriverio chromedriver

예: chromestatus.com에서 CSS 기능 필터링

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

})();

추가 자료

다음은 시작하는 데 도움이 되는 몇 가지 유용한 리소스입니다.

문서

도구

  • chrome-remote-interface - 노드 DevTools 프로토콜을 래핑하는 모듈
  • Lighthouse - 테스트용 자동화된 도구 웹 앱 품질 프로토콜을 많이 사용함
  • chrome-launcher 자동화 준비가 완료된 Chrome 실행을 위한 노드 모듈

데모

  • '헤드리스 웹' - Paul Kinlan의 블로그 api.ai와 함께 헤드리스 사용에 관한 게시물을 참고하세요.

FAQ

--disable-gpu 플래그가 필요한가요?

Windows에서만 사용 가능합니다. 다른 플랫폼에서는 더 이상 이 권한이 필요하지 않습니다. --disable-gpu 플래그는 임시적인 해결 방법을 찾을 수 있습니다. 향후 버전에서는 이 플래그가 필요하지 않습니다. Chrome으로 이동합니다. crbug.com/737678을 참조하세요. 를 참조하세요.

그래도 Xvfb가 필요한가요?

아니요. 헤드리스 Chrome은 창을 사용하지 않으므로 Xvfb와 같은 디스플레이 서버는 더 이상 필요하지 않습니다 이 도구 없이도 자동화된 테스트를 실행할 수 있습니다.

Xvfb란 무엇인가요? Xvfb는 Unix와 유사한 시스템 용 인메모리 디스플레이 서버로 연결된 물리적 디스플레이 없이 Chrome과 같은 그래픽 애플리케이션을 실행할 수 있습니다. 많은 사람들이 Xvfb를 사용하여 이전 버전의 Chrome을 실행하여 '헤드리스' 작업을 수행합니다. 있습니다.

헤드리스 Chrome을 실행하는 Docker 컨테이너를 만들려면 어떻게 해야 하나요?

lighthouse-ci를 확인합니다. 여기에는 Dockerfile 예시 node:8-slim를 기본 이미지로 사용하고 + Lighthouse 실행 살펴봤습니다

Slenium / WebDriver / ChromeDriver와 함께 사용할 수 있나요?

예. Slenium, WebDriver, ChromeDriver 사용을 참고하세요.

PantomJS와 어떤 관련이 있나요?

헤드리스 Chrome은 PhantomJS와 같은 도구와 유사합니다. 모두 헤드리스 환경에서 자동화된 테스트에 사용할 수 있습니다. 주요 차이점 Phantom은 WebKit의 렌더링으로 이전 버전의 WebKit을 사용한다는 것입니다. Headless Chrome은 최신 버전의 Blink를 사용합니다.

현재 Phantom은 DevTools 프로토콜보다 높은 수준의 API도 제공합니다.

버그는 어디에 신고해야 하나요?

헤드리스 Chrome 관련 버그는 crbug.com에서 신고하세요.

DevTools 프로토콜 관련 버그는 github.com/ChromeDevTools/devtools-protocol에서 신고하세요.