记一次"截图"功能的项目调研过程!
项目需求
最近,项目接到了一个新需求,要求对指定URL进行后端模拟前端请求,对页面进行截图,具体要求如下:
纯后端模拟,不打开前端页面
截全屏,也就是不管页面有多长,都要截取到一张图片上
只要求截取浏览器DOM以内的部分,DOM以外不要截取
保证页面不失真,页面渲染与实际一直
确保图片清晰度
能够支持多并发请求
功能调研
接到项目需求后,我就对Java实现的截图功能进行了一些前期调研,调研过程如下:
AWT
首先想到的是比较简单的Root
,它应用简单,完全自动化,Java自带功能,包名java.awt
。于是编写上手实验:
截图效果:
优势:简单易用,不需要任何第三方插件。
缺点:不能同时处理大量数据,技术含量过低,属于应急型技巧。
Swing
与AWT
相比,Swing
是基于awt的Java程序,包名javax.swing
。它不仅提供了AWT的所有功能,还用纯粹的Java代码对AWT的功能进行了大幅度的扩充。它是为解决AWT存在的问题而新开发的图形界面包。
对Swing的测试,我们采用DJNativeSwing-SWT
,它是java内嵌浏览器API,需要用到的依赖包有:
测试代码:
截图效果:
Swing控件是改善为了AWT控件而发展出来的轻量级GUI控件,采用的是Composite设计模式,然而,由于没有清楚的分隔组件(Component)和容器(Container)的边界,就造成了Swing的几乎每个单独的组件都是一个容器,能够添加其他容器或者组件,其功能非常强大,但也存在以下一些的问题:
与直觉不太一致:Swing的GUI上的各种组件如果添加的面板过多的话,就造成各个组件的层次很深,处理类似focus管理这样的问题就很麻烦,坐标的转换也很复杂,由于父子关系过多,您不看代码只看GUI,凭直觉难以区分组件的父子关系。
布局上的困难:使用Swing开发界面的程序员会发现,即使Swing提供了这么多布局管理器,然而您想通过这些布局管理器做出很专业的界面却非常难,因为布局管理器非常依赖父容器和子组件的各种状态,尽管Swing最新的版本提供了类似组件和容器间隔的方法,然而还没有被大部分布局管理器采用,其实并不是布局管理器不够强大的问题,事实上,很多专业的界面需要从组件级别做出良好的定义,另外,不少Swing组件会根据容器的大小进行绘制,这也造成了很多不确定性,很多人喜欢使用NullLayout,可能就是这个原因,客户需要的是一个稳定的,可预知的界面,如果使用了布局管理器,会发现界面在不同的系统下展示的不同
使用上的困扰:Swing组件本身由于不能分清是组件还是容器,很多容器方法比如setEnabled就没有效果,需要写代码遍历所有子组件,调用所 有的子组件相同的方法,而类似设置透明的方法也有这个问题,如果设置某个容器透明,也需要设置所有的子组件的透明属性,组件和容器的很多方法没有很好的定 义,这对了解Swing结构的人不是问题,但是对于熟悉别的GUI类库的人就产生了很大的困惑,因为不少容器上的方法调用后是没有效果的。
总得来说,对Composite设计模式应该慎用,如果一定要用,一定要良好的定义组件(Component)和容器(Container)的边界,避免很多功能陷入没有意义的父子遍历例程,增加了复杂性。
Html2Image
Html2Image是一个将html转成图片的工具,它在html转图片的领域使用率是不低的。引入依赖:
测试代码:
测试代码比较简单,手绘了一个Table,放入两行图片,看一下效果:
所以,Html2Image的缺点也很明显:
当你的html页面引入外部的CSS文件以及JS文件,生成的图片是无法带有这些动态效果的。也就是说,它不支持复杂的动态特性,只能支持写在html代码里的css效果。
当html代码里带有图片时,生成的程序必须有一定的等待时间,否则生成的图片会有空白,所以需要设法在代码生成图片前让程序等待一会,比如
Thread.sleep(8000)
。调试不易,很容易出现图不清楚、有边框、字体被洗白等等情况。
...
PhantomJS
PhantomJS
是一个可编程的无头浏览器。适用于页面自动化,网页监控,网络爬虫等:
页面自动化测试:希望自动的登陆网站并做一些操作然后检查结果是否正常。
网页监控:希望定期打开页面,检查网站是否能正常加载,加载结果是否符合预期。加载速度如何等。
网络爬虫:获取页面中使用js来下载和渲染信息,或者是获取链接处使用js来跳转后的真实地址。
PhantomJS官网下载地址:http://phantomjs.org/,下载后可以直接解压使用!
测试代码:
截图效果:
关于PhantomJS的具体使用,可以参考:Phantomjs实现后端将URL转换为图片
PhantomJS作为一款强大的命令行工具,可以胜任多种自动化测试、监控等工作,但很可惜,随着Google在Chrome 59版本放出了headless模式,Ariya Hidayat决定放弃对Phantom.js的维护,这也标示着Phantom.js 统治fully functional headless browser的时代将被chrome-headless代替了。
PhantomJS缺点:
将近2k的issue,仍然需要人去修复。
Javascript天生单线程的弱点,需要用异步方式来模拟多线程,随之而来的callback地狱,对于新手而言非常痛苦,不过随着es6的广泛应用,我们可以用promise来解决多重嵌套回调函数的问题。
虽然webdriver支持htmlunit与phantomjs,但由于没有任何界面,当我们需要进行调试或复现问题时,就非常麻烦。
Headless Chrome
Headless Browser
意思是没有页面的浏览器,多用于测试web、截图、图像对比、测试前端代码、爬虫(虽然很慢)、监控网站性能等。其优点如下:
对于UI自动化测试,少了真实浏览器加载css,js以及渲染页面的工作。无头测试要比真实浏览器快的多。
可以在无界面的服务器或CI上运行测试,减少了外界的干扰,使自动化测试更稳定。
在一台机器上可以模拟运行多个无头浏览器,方便进行并发测试。
PhantomJS
曾经就是一款优秀的Headless浏览器,但由于其多项缺点,在Headless Browser领域正在逐渐被chrome-headless取替。
Headless Chrome
是Chrome浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有Chrome支持的特性,在命令行中运行你的脚本。相比于其他浏览器,Headless Chrome能够更加便捷的运行web自动化测试、编写爬虫、截取图等功能。它的出现就是来代替PhantomJS
的。
Headless Chrome
优点:
比phantomjs有更快更好的性能。
Headless Chrome要比现phantomjs更加快速的完成任务,且占用内存更少。
有谷歌平台维护,不会出现2k的issue情况。
支持ECMAScript 2017 (ES8),我们也可以使用最新的js语法来编写的脚本,例如async,await等。
完全真实的浏览器操作,chrome headless支持所有chrome特性。
调试便利。我们只需要在命令行中加入
–remote-debugging-port=9222
,再打开浏览器输入ip:9222
就能进入调试界面。
我们采用selenium + headless chrome来做个代码测试:
Chrome浏览器与驱动需要相对应,对应关系可以查找:ChromeDriver与Chrome版本对应参照表及ChromeDriver下载链接
Chrome浏览器下载地址:Chrome Download
实现方案
针对本期需求功能点做对比,以上几种方案中,只有Chrome Headless模式可以满足要求,既能保证截图功能的实现,又适合以后项目的扩展!
针对Chrome Headless的选用方案,我们采用Selenium Server服务,服务端基于Selenium的Grid组件来搭建截图功能。
Selenium Server目前采用2.42版本,图片服务器为5台Windows系统虚机,项目架构图如下:
项目结构有5台Node节点,1台Hub,Hub与其中一台Node共享虚机。启动模式采用standalone模式,启动文件:selenium-server-standalone-2.42.0.jar。
Node节点安装的Web服务均采用Chrome浏览器实现,浏览器版本71.0.3557.0(开发者内部版本)(64 位),浏览器驱动版本2.46。
通过以上配置,完全可以满足本次项目开发需求,实现了完整的功能特点!
结论
Selenium + Chrome Headless
是浏览器操作的最便捷方式,完全兼容Chrome浏览器所有功能特点,是今后设计浏览器开发工作中的必备手段!
关于Selenium想了解的同学,可以参考官方文档,这里不做具体介绍!
来自:https://www.cnblogs.com/ason-wxs/p/13717875.html
评论 (1 条评论)