最近碰到这样一些需求,后端需要对某个图表页面进行动态截图,将截图通过邮件发送到指定邮箱进行每日提醒。
这就需要用到无界浏览器进行此类操作。常见的无界浏览器有以下几种,知识来源于chatgpt3.5:
Headless Chrome - Google Chrome 浏览器的一个无界面版本,支持大部分 Chrome 浏览器的特性和 API。
Puppeteer - 使用 Node.js 调用 Headless Chrome 进行自动化测试的高级库,提供了便捷的 API,可以方便地控制 Chrome 浏览器的各种行为。
SlimerJS - 基于 Gecko 引擎的无头浏览器,可以用来模拟用户行为,渲染 Javascript 应用。
Splash - 一款基于 Python 的,专门用于爬虫和自动化测试的浏览器。它使用 WebKit 渲染引擎,并且有一个强大的 Lua API,可以很方便地控制浏览器的行为。
HtmlUnit - 一款 Java 的 Open-Source 的无界面浏览器,以模拟浏览器的方式来执行 HTML、CSS、JavaScript 代码,适用于自动化测试。
PhantomJS - 一个基于 WebKit 渲染引擎的无界面、使用 JavaScript 脚本编写的脚本able浏览器。它支持大部分的 Web 标准,包括 CSS, DOM, SVG, Canvas 和 XMLHttpRequest 等,能够在不需要 GUI 界面的情况下进行页面渲染和脚本执行。
本文基于PhantomJS ,介绍如何使用后台截图功能。PS:PhantomJS 的开发由 PhantomJS 社区组织负责,采用了 BSD 许可证。因为其长期未更新,而且有一些安全漏洞,官方已经于 2020 年停止了对 PhantomJS 的开发和维护,并建议用户转移到其他无头浏览器或使用 Pupeteer 来代替之。
一、下载安装phantomjs
Download PhantomJS
选择适用的执行环境,下载二进制包。
二、编写截图脚本
function screenshot(url, save_name) {
var page = require('webpage').create();
page.viewportSize = {width: 1280, height: 1024};
page.onAlert = page.onPrompt = page.onConfirm = page.onError = function () {
};
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36';
page.settings.resourceTimeout = 1000*15;
var cnt = 0;
page.onNavigationRequested = function (url2, type, willNavigate, main) {
cnt += 1;
if (main && url2 !== url && cnt < 7) {
page.close();
setTimeout(function () {
screenshot(url2, save_name)
}, 100);
}
};
page.open(url, function (status) {
//console.debug(status);
if (status === "success") {
return window.setTimeout(pageRender, 100);
} else {
return window.setTimeout(pageRender, 100);
}
});
window.setTimeout(pageRender, 60*1.2*1000);
function pageRender() {
page.evaluate(function () {
document.body.bgColor = 'white';
});
page.clipRect = {
top: 0,
left: 0,
width: 1280,
height: 1024
};
page.render(save_name, {format: 'jpeg', quality: '100'});
phantom.exit(0);
}
}
function main() {
var system = require('system');
var p_url = new RegExp('-u=(.*)');
var p_save_name = new RegExp('-s=(.*)');
for (var i = 0; i < system.args.length; i++) {
if (p_url.test(system.args[i]) === true) {
var url = p_url.exec(system.args[i])[1];
}
if (p_save_name.test(system.args[i]) === true) {
var save_name = p_save_name.exec(system.args[i])[1];
}
}
if (typeof(url) === 'undefined' || url.length == 0 || typeof(save_name) === 'undefined' || save_name.length == 0) {
console.log("Usage: phantomjs screenshot.js -u=http://swww.baidu.com/ -s=baidu.jpg ");
phantom.exit(1);
}
screenshot(url, save_name)
}
main();
需要注意的是,截图如需要截完整的话,有两种方式:
1.设置哟个固定的大的viewPortSize值:page.viewportSize = {width: 1280, height: 1024};
2.通过BOM方法操作滚动条,可以把滚动条滚动到一个很大的值:window.scrollTo(0,10000);
笔记中使用第一个方式进行操作。
三、执行命令行截图
phantomjs --ignore-ssl-errors true --ssl-protocol any --ssl-ciphers ALL screenshot.js -u=https://www.baidu.com -s=1.png
phantomjs会自动截图,并保存文件: