Created
July 11, 2017 13:44
-
-
Save ajxchapman/d328b9ad995d83c68040a2e6c967f83f to your computer and use it in GitHub Desktop.
Node script to screenshot web pages using chrome debugging protocol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// npm install chrome-remote-interface minimist | |
const CDP = require('chrome-remote-interface'); | |
const argv = require('minimist')(process.argv.slice(2)); | |
const file = require('fs'); | |
const spawn = require('child_process').spawn; | |
const net = require('net'); | |
const crypto = require('crypto'); | |
const url = argv.url || 'https://www.google.com'; | |
const id = argv.id || crypto.createHash('sha256').update(url).digest("hex"); | |
const viewportWidth = argv.viewportWidth || 1440; | |
const viewportHeight = argv.viewportHeight || 900; | |
const delay = argv.delay || 200; | |
const debugport = argv.port || 9222 | |
// Reference: https://www.npmjs.com/package/wait-for-port | |
function wait_for_port(host, port, cb) { | |
var retriesRemaining = 10; | |
var retryInterval = 200; | |
var timer = null, socket = null; | |
function clearTimerAndDestroySocket() { | |
clearTimeout(timer); | |
timer = null; | |
if (socket) socket.destroy(); | |
socket = null; | |
} | |
function tryToConnect() { | |
clearTimerAndDestroySocket(); | |
if (--retriesRemaining < 0) return cb(new Error('out of retries')); | |
socket = net.createConnection(port, host, function(err) { | |
clearTimerAndDestroySocket(); | |
if (retriesRemaining > 0) cb(null); | |
}); | |
timer = setTimeout(tryToConnect, retryInterval); | |
socket.on('error', function(err) { | |
clearTimerAndDestroySocket(); | |
setTimeout(tryToConnect, retryInterval); | |
}); | |
} | |
tryToConnect(); | |
}; | |
console.log("Launching chrome"); | |
// WARN: Using no-sandbox to run nicely inside docker for now | |
const chrome_args = ["--headless", "--hide-scrollbars", `--remote-debugging-port=${debugport}`, "--disable-gpu", "--no-sandbox"]; | |
console.log(chrome_args); | |
const proc = spawn("google-chrome", chrome_args); | |
console.log(`Connecting to debug port on 127.0.0.1:${debugport}`); | |
wait_for_port("127.0.0.1", debugport, (err) => { | |
if (err) { | |
console.log("Unable to connect to chrome debug port, exiting"); | |
process.exit(2); | |
} | |
// Reference: https://medium.com/@dschnr/using-headless-chrome-as-an-automated-screenshot-tool-4b07dffba79a | |
CDP(function(client) { | |
const {Emulation, Page, Security} = client; | |
Page.loadEventFired(() => { | |
console.log("Page loaded"); | |
setTimeout(() => { | |
console.log("Taking screenshot"); | |
Page.captureScreenshot({format : 'png'}, (err, screenshot) => { | |
if (!err) { | |
const buffer = new Buffer(screenshot.data, 'base64'); | |
file.writeFileSync(`${id}_screenshot.png`, buffer, 'base64'); | |
} | |
client.close(); | |
process.exit(0); | |
}); | |
}, delay); | |
}); | |
// Reference: https://github.com/cyrus-and/chrome-remote-interface/wiki/Bypass-certificate-errors-(%22Your-connection-is-not-private%22) | |
Security.certificateError(({eventId}) => { | |
Security.handleCertificateError({ | |
eventId, | |
action: 'continue' | |
}); | |
}); | |
const deviceMetrics = { | |
width: viewportWidth, | |
height: viewportHeight, | |
deviceScaleFactor: 0, | |
mobile: false, | |
fitWindow: false, | |
}; | |
Promise.all([ | |
Page.enable(), | |
]).then(() => { | |
console.log("Configuring browser"); | |
return Promise.all([ | |
Emulation.setDeviceMetricsOverride(deviceMetrics), | |
Emulation.setVisibleSize({width: viewportWidth, height: viewportHeight}), | |
Security.enable(), | |
Security.setOverrideCertificateErrors({override: true}) | |
]); | |
}).then(() => { | |
console.log("Navigating to page ", url); | |
return Page.navigate({url}); | |
}) | |
setTimeout(() => { | |
console.log("Timeout loading page, exiting"); | |
client.close(); | |
process.exit(3); | |
}, delay + 5000); | |
}).on('error', err => { | |
console.error('Cannot connect to browser:', err); | |
process.exit(4); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment