TL;DR
Chrome แบบไม่มีส่วนหัว จัดส่งใน Chrome 59 นะ ซึ่งเป็นวิธีเรียกใช้เบราว์เซอร์ Chrome ในสภาพแวดล้อมที่ไม่มีส่วนหัว โดยพื้นฐานแล้ว การวิ่ง Chrome ที่ไม่มี Chrome! มีฟีเจอร์แพลตฟอร์มเว็บสมัยใหม่ทั้งหมดที่ให้บริการ โดย Chromium และเครื่องมือแสดงผล Blink ไปยังบรรทัดคำสั่ง
มีประโยชน์อย่างไร
เบราว์เซอร์แบบไม่มีส่วนหัวเป็นเครื่องมือที่ยอดเยี่ยมสำหรับการทดสอบอัตโนมัติและสภาพแวดล้อมของเซิร์ฟเวอร์ที่คุณ ไม่จำเป็นต้องมีเชลล์ UI ที่มองเห็นได้ ตัวอย่างเช่น คุณอาจต้องการดำเนินการทดสอบกับ หน้าเว็บจริง สร้างไฟล์ PDF หรือแค่ตรวจสอบการแสดงผล URL ของเบราว์เซอร์
การเริ่มแบบไม่มีส่วนหัว (CLI)
วิธีที่ง่ายที่สุดในการเริ่มต้นใช้งานโหมดไม่มีส่วนหัวคือการเปิดไบนารีของ Chrome
จากบรรทัดคำสั่ง หากคุณติดตั้ง Chrome 59 ขึ้นไปไว้แล้ว ให้เริ่ม Chrome ด้วยแฟล็ก --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
ควรชี้ไปยังการติดตั้ง Chrome ของคุณ ตำแหน่งที่แน่นอนจะ
แตกต่างกันไปตามแพลตฟอร์ม เพราะฉันใช้ Mac เลยสร้างชื่อแทนเพื่อความสะดวก
สำหรับ Chrome แต่ละเวอร์ชันที่ฉันติดตั้ง
หากคุณใช้เวอร์ชันเสถียรของ 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
ไปยัง Stout:
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 (วนซ้ำแบบอ่าน-ประเมิน-พิมพ์)
แฟล็ก --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
$
ต้องการแก้ไขข้อบกพร่องของ Chrome โดยไม่ใช้ UI ของเบราว์เซอร์ใช่ไหม
เมื่อคุณเรียกใช้ Chrome ด้วย --remote-debugging-port=9222
จะเป็นการเริ่มต้นอินสแตนซ์
เปิดใช้โปรโตคอลเครื่องมือสำหรับนักพัฒนาเว็บไว้
จะใช้โปรโตคอลในการสื่อสารกับ Chrome และขับเคลื่อน
อินสแตนซ์ของเบราว์เซอร์ และยังเป็นเครื่องมืออย่าง Sublime, VS Code และโหนด เพื่อ
การแก้ไขข้อบกพร่องของแอปพลิเคชันจากระยะไกล #synergy
เนื่องจากคุณไม่มี UI ของเบราว์เซอร์ที่จะแสดงหน้า ให้ไปที่ http://localhost:9222
ในเบราว์เซอร์อื่นเพื่อตรวจสอบว่าทุกอย่างทำงานได้ตามปกติ คุณจะเห็นรายการ
หน้าเว็บที่ตรวจสอบได้ซึ่งสามารถคลิกผ่านและดูการแสดงผลแบบไม่มีส่วนหัว
จากตรงนี้ คุณจะสามารถใช้ฟีเจอร์เครื่องมือสำหรับนักพัฒนาเว็บที่คุ้นเคยเพื่อตรวจสอบ แก้ไขข้อบกพร่อง และปรับแต่ง หน้าเว็บตามปกติ หากคุณใช้โปรแกรม Headless แบบเป็นโปรแกรม เป็นเครื่องมือดีบักที่มีประสิทธิภาพด้วยการดูโปรโตคอลเครื่องมือสำหรับนักพัฒนาเว็บที่เป็นข้อมูลดิบทั้งหมด ไปจนถึงการสื่อสารกับเบราว์เซอร์
การใช้แบบเป็นโปรแกรม (โหนด)
การเชิดหุ่น
Puppeteer เป็นไลบรารีโหนด ที่พัฒนาโดยทีม Chrome มี API ระดับสูงสำหรับควบคุมแบบไม่มีส่วนหัว (หรือเต็มรูปแบบ) Chrome คล้ายกับไลบรารีการทดสอบอัตโนมัติอื่นๆ เช่น Phantom และ NightmareJS แต่ก็ใช้ได้กับ Chrome เวอร์ชันล่าสุดเท่านั้น
นอกจากนี้คุณยังสามารถใช้ Puppeteer เพื่อถ่ายภาพหน้าจอ สร้าง PDF ไปยังหน้าต่างๆ และดึงข้อมูลเกี่ยวกับหน้าเหล่านั้น ฉันขอแนะนำห้องสมุด ถ้าต้องการทดสอบเบราว์เซอร์โดยอัตโนมัติอย่างรวดเร็ว ช่วยซ่อนความซับซ้อน โปรโตคอลเครื่องมือสำหรับนักพัฒนาเว็บและดูแลงานที่ซ้ำซ้อน เช่น การเปิดตัว ดีบักอินสแตนซ์ของ Chrome
ติดตั้ง ดังนี้
npm i --save puppeteer
ตัวอย่าง - พิมพ์ User Agent
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 เป็นไลบรารีระดับต่ำกว่า API ของ Puppeteer ฉันแนะนำหากคุณอยากเป็น ใกล้โลหะและใช้โปรโตคอลเครื่องมือสำหรับนักพัฒนาเว็บโดยตรง
กำลังเปิด 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 ที่จะใช้ด้วยตนเองได้ ถึง
ใช้งานอยู่ ให้ติดตั้งจาก NPM ก่อน:
npm i --save chrome-launcher
ตัวอย่าง - ใช้ chrome-launcher
เพื่อเปิดใช้ 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();
});
การเรียกใช้สคริปต์นี้จะไม่มีประโยชน์มากนัก แต่คุณจะเห็นตัวอย่าง
Chrome เริ่มทำงานในตัวจัดการงานที่โหลด about:blank
จำไว้ว่า
จะไม่มี UI ใดๆ ของเบราว์เซอร์ เราไม่ได้ใช้ส่วนหัว
เราต้องใช้โปรโตคอลเครื่องมือสำหรับนักพัฒนาเว็บในการควบคุมเบราว์เซอร์
กำลังดึงข้อมูลเกี่ยวกับหน้าเว็บ
มาติดตั้งไลบรารีกันเลย
npm i --save chrome-remote-interface
ตัวอย่าง
ตัวอย่าง - พิมพ์ User Agent
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
ตัวอย่าง - ตรวจสอบว่าเว็บไซต์มีไฟล์ Manifest ของเว็บแอปหรือไม่
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.
});
})();
ตัวอย่าง - ดึงข้อมูล <title>
ของหน้าเว็บโดยใช้ 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.
});
})();
การใช้ Selenium, WebDriver และ ChromeDriver
ตอนนี้ Selenium ได้เปิด Chrome อินสแตนซ์ทั้งหมด กล่าวอีกนัยหนึ่งคือ ให้เป็นระบบอัตโนมัติ แต่ก็ไม่มีส่วนหัว แต่ซีลีเนียมอาจ ได้รับการกำหนดค่าให้เรียกใช้ Chrome แบบไม่มีส่วนหัวด้วยการทำงานเพียงเล็กน้อย ฉันขอแนะนำ ใช้ Selenium กับ Chrome แบบไม่มีส่วนหัว หากคุณต้องการ วิธีการตั้งค่าด้วยตัวเองทั้งหมด แต่มีบางส่วนที่ข้ามไป ด้านล่างนี้จะช่วยคุณเริ่มต้นใช้งาน
การใช้ 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 เป็น API ระดับที่สูงกว่านอกเหนือจาก Selenium WebDriver
ติดตั้ง:
npm i --save-dev webdriverio chromedriver
ตัวอย่าง: กรองฟีเจอร์ CSS ใน 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();
})();
แหล่งข้อมูลเพิ่มเติม
ต่อไปนี้เป็นแหล่งข้อมูลบางส่วนที่เป็นประโยชน์ในการเริ่มต้นใช้งาน
เอกสาร
- ผู้ดูโปรโตคอลเครื่องมือสำหรับนักพัฒนาเว็บ - เอกสารอ้างอิง API
เครื่องมือ
- chrome-remote-interface - โหนด ที่รวมโปรโตคอลเครื่องมือสำหรับนักพัฒนาเว็บ
- Lighthouse - เครื่องมืออัตโนมัติสำหรับการทดสอบ คุณภาพของเว็บแอป มีการใช้โปรโตคอลมาก
- chrome-launcher โมดูลโหนดสำหรับการเปิดตัว Chrome พร้อมสำหรับการทำงานอัตโนมัติ
เดโม
- "The Headless Web" - บล็อกที่ยอดเยี่ยมของ Paul Kinlan โพสต์เกี่ยวกับการใช้ Headless กับ api.ai
คำถามที่พบบ่อย
ฉันต้องแฟล็ก --disable-gpu
ไหม
เฉพาะบน Windows เท่านั้น แพลตฟอร์มอื่นๆ ไม่จำเป็นต้องใช้ฟีเจอร์นี้แล้ว แฟล็ก --disable-gpu
คือ
เป็นการชั่วคราวสำหรับข้อบกพร่อง 2-3 อย่าง คุณจะไม่ต้องติดธงนี้ในเวอร์ชันต่อๆ ไปของ
Chrome โปรดดูที่ crbug.com/737678
เพื่อดูข้อมูลเพิ่มเติม
ฉันยังต้องการ Xvfb อยู่ไหม
ไม่ Chrome แบบไม่มีส่วนหัวไม่ได้ใช้หน้าต่าง ดังนั้นเซิร์ฟเวอร์การแสดงผลอย่าง Xvfb ที่ไม่จำเป็นอีกต่อไป คุณสามารถทำการทดสอบอัตโนมัติได้อย่างมีความสุขหากไม่มีการทดสอบ
Xvfb คืออะไร Xvfb เป็นเซิร์ฟเวอร์การแสดงผลแบบในหน่วยความจำสำหรับระบบที่คล้ายกับ Unix ซึ่งทำให้คุณสามารถ เพื่อเรียกใช้แอปพลิเคชันแบบกราฟิก (เช่น Chrome) โดยไม่ต้องแนบจอแสดงผลจริง หลายคนใช้ Xvfb เพื่อเรียกใช้ Chrome เวอร์ชันก่อนหน้าเพื่อทำ "ไม่มีส่วนหัว" การทดสอบ
ฉันจะสร้างคอนเทนเนอร์ Docker ที่เรียกใช้ Chrome แบบ Headless ได้อย่างไร
ลองไปที่ lighthouse-ci มี
ตัวอย่าง Dockerfile
ที่ใช้ node:8-slim
เป็นอิมเมจฐาน การติดตั้ง +
ใช้ Lighthouse
ใน App Engine Flex
ฉันจะใช้สิ่งนี้กับ Selenium / WebDriver / ChromeDriver ได้ไหม
ได้ โปรดดูการใช้ Selenium, WebDriver และ ChromeDriver
ฟีเจอร์นี้เกี่ยวข้องกับ PhantomJS อย่างไร
Chrome แบบไม่มีส่วนหัวจะคล้ายกับเครื่องมืออย่าง PhantomJS ทั้ง 2 อย่าง สามารถใช้สำหรับการทดสอบอัตโนมัติในสภาพแวดล้อมที่ไม่มีส่วนหัว ความแตกต่างที่สำคัญ ระหว่าง 2 ก็คือ Phantom ใช้ WebKit เวอร์ชันเก่าเป็นการแสดงผล ในขณะที่ Chrome แบบ Headless จะใช้ Blink เวอร์ชันล่าสุด
ในขณะนี้ Phantom ยังมี API ระดับสูงกว่าโปรโตคอลเครื่องมือสำหรับนักพัฒนาเว็บด้วย
ฉันจะรายงานข้อบกพร่องได้ที่ใด
สำหรับข้อบกพร่องของ Chrome แบบไม่มีส่วนหัว โปรดส่งไปที่ crbug.com
สำหรับข้อบกพร่องในโปรโตคอลเครื่องมือสำหรับนักพัฒนาเว็บ โปรดส่งข้อมูลที่ github.com/ChromeDevTools/devtools-protocol