最近碰到这样一些需求,后端需要对某个图表页面进行动态截图,将截图通过邮件发送到指定邮箱进行每日提醒。
这就需要用到无界浏览器进行此类操作。常见的无界浏览器有以下几种,知识来源于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会自动截图,并保存文件: