我在我的 Macbook Pro 10.12.5 上遵循这里的教程:
https://medium.com/@dschnr/using-headless-chrome-as-an-automated-screenshot-tool-4b07dffba79a
下面是我的代码:
const CDP = require('chrome-remote-interface');
const argv = require('minimist')(process.argv.slice(2));
const file = require('fs');
// CLI Args
const url = argv.url || 'https://www.google.com';
const format = argv.format === 'jpeg' ? 'jpeg' : 'png';
const viewportWidth = argv.viewportWidth || 1440;
const viewportHeight = argv.viewportHeight || 900;
const delay = argv.delay || 0;
const userAgent = argv.userAgent;
const fullPage = argv.full;
// Start the Chrome Debugging Protocol
CDP(async function(client) {
// Extract used DevTools domains.
const {DOM, Emulation, Network, Page, Runtime} = client;
// Enable events on domains we are interested in.
await Page.enable();
await DOM.enable();
await Network.enable();
// If user agent override was specified, pass to Network domain
if (userAgent) {
await Network.setUserAgentOverride({userAgent});
}
// Set up viewport resolution, etc.
const deviceMetrics = {
width: viewportWidth,
height: viewportHeight,
deviceScaleFactor: 0,
mobile: false,
fitWindow: false,
};
await Emulation.setDeviceMetricsOverride(deviceMetrics);
await Emulation.setVisibleSize({width: viewportWidth, height: viewportHeight});
// Navigate to target page
await Page.navigate({url});
// Wait for page load event to take screenshot
Page.loadEventFired(async () => {
// If the `full` CLI option was passed, we need to measure the height of
// the rendered page and use Emulation.setVisibleSize
if (fullPage) {
const {root: {nodeId: documentNodeId}} = await DOM.getDocument();
const {nodeId: bodyNodeId} = await DOM.querySelector({
selector: 'body',
nodeId: documentNodeId,
});
const {model: {height}} = await DOM.getBoxModel({nodeId: bodyNodeId});
console.log(viewportWidth);
console.log(height);
await Emulation.setVisibleSize({width: viewportWidth, height: height});
// This forceViewport call ensures that content outside the viewport is
// rendered, otherwise it shows up as grey. Possibly a bug?
// await Emulation.forceViewport({x: 0, y: 0, scale: 1});
}
setTimeout(async function() {
const screenshot = await Page.captureScreenshot({format});
const buffer = new Buffer(screenshot.data, 'base64');
file.writeFile('output.png', buffer, 'base64', function(err) {
if (err) {
console.error(err);
} else {
console.log('Screenshot saved');
}
client.close();
});
}, delay);
});
}).on('error', err => {
console.error('Cannot connect to browser:', err);
});
这是我的所有版本:
“铬启动器”:“^0.4.0”
“铬远程接口”:“^0.24.3”
“极简主义”:“^1.2.0”
谷歌浏览器 62.0.3181.0 金丝雀
我的屏幕截图 output.png 是空白的(7KB),它似乎在几天前随机发生,但现在几乎一直是空白的。// await Emulation.forceViewport({x: 0, y: 0, scale: 1});
请注意,由于错误,我不得不注释掉(node:1304) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Emulation.forceViewport is not a function
这是我跑步时发生的事情:
$ node autoscreenshot.js --full
1440
900
Screenshot saved
所以它确实设置了屏幕和除空白屏幕截图之外的所有内容。
使屏幕截图始终如一地工作的唯一方法是使用以下代码:
const chromeLauncher = require('chrome-launcher');
const CDP = require('chrome-remote-interface');
const file = require('fs');
(async function() {
async function launchChrome() {
return await chromeLauncher.launch({
chromeFlags: [
'--disable-gpu'
// '--headless'
]
});
}
const chrome = await launchChrome();
const protocol = await CDP({
port: chrome.port
});
const {
DOM,
Network,
Page,
Emulation,
Runtime
} = protocol;
await Promise.all([Network.enable(), Page.enable(), Runtime.enable(), DOM.enable()]);
await Page.navigate({
url: 'https://www.yahoo.com/'
});
Page.loadEventFired(async() => {
console.log('Start Page.loadEventFired');
const {root: {nodeId: documentNodeId}} = await DOM.getDocument();
console.log('Start DOM.querySelector');
const {nodeId: bodyNodeId} = await DOM.querySelector({
selector: 'body',
nodeId: documentNodeId
});
console.log('Start DOM.getBoxModel');
const {model: {height}} = await DOM.getBoxModel({nodeId: bodyNodeId});
console.log('height=' + height);
console.log('Start Emulation.setVisibleSize');
await Emulation.setVisibleSize({width: 735, height: height});
console.log('Start Page.captureScreenshot');
const ss = await Page.captureScreenshot({format: 'png', fromSurface: true});
console.log('Start file.writeFile');
file.writeFile('output.png', ss.data, 'base64', function(err) {
if (err) {
console.log(err);
}
});
protocol.close();
chrome.kill();
});
})();
请注意,现在我正在使用chrome-launcher
但也删除headless
. 所以它会弹出浏览器窗口。但它有效并截取了屏幕截图。
所以我的问题:
这只是 Mac OSX Sierra 上 Canary 62 中的一个错误吗?
如果没有,如何解决这个无头方法适用于截图?
更新 1
我又尝试了两件事并取得了成功:
如果我在 Mac 上使用 Chrome 60(稳定版),它可以工作,我可以无头截屏。
如果我在 Ubuntu 上使用 Chrome 60(测试版),它也适用于无头。
因此,唯一不起作用的情况是Canary 62 无头,因为带有浏览器的 Canary 62 确实可以正常工作。确实很奇怪。