使用PhantomJS实现网页截图服务

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

这是上半年遇到的一个小需求,想实现网页的抓取,并保存为图片。研究了不少工具,效果都不理想,不是显示太差了(Canvas、Html2Image、Cobra),就是性能不怎么样(如SWT的Brower)。后发现无界面浏览器可以满足这个条件,大致研究了一下PhantomJS与CutyCapt,两者都是Webkit内核,其中PhantomJS使用上更方便一些,尤其在Windows平台上,如果在linux下,从2.0版本后需要自己去机器上编译了(大概要编译3个小时,不得不说,g++就是个渣渣,同样的项目,在vc下编译快得,不谈了,毕竟是免费开源的编译器)。下面介绍PhantomJS结合java代码实现的网页截图技术:

一、环境准备

1、PhantomJS脚本的目录:D:/xxx/phantomjs-2.0.0-windows/bin/phantomjs

2、截图脚本:D:/xxx/phantomjs-2.0.0-windows/bin/rasterize.js

截图的脚本在官网上有提供,但是我这里需要说明一下它的高宽度设计原理:

page.viewportSize = { width: 600, height: 600 };

这个是默认的高度,也就是600X600,我建议大家把height设置小一点,我这边设置的是width:800,height:200。因为实际上,在不同时设置高度与亮度的情况下,如果真实的网页的高度大于设置值时,图片会自动扩充高宽度的,直到整个页面显示完(当你想截取小的图片时,可能由于默认设置的太大,会使图片有很大一块空的)。如果同时设置了高宽度,下面的代码会被执行,就会对网页的部分进行截取了:

page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight };

3、先用命令行测试一下:

D:/xxx/phantomjs-2.0.0-windows/bin/phantomjs D:/xxx/phantomjs-2.0.0-windows/bin/rasterize.js http://www.QQ.com D:/test.png

如果配置好了,应该可以看到生成的图片了。当然还可以配置高宽度的参数,在上面的命令后加上:" 1000px"或" 1000px*400px",都是可以的。

二、服务器代码

作为一个网页截图服务,这部分代码片段应当被布署在服务器上,当然不必全照搬啦,根据自己的需求来用就好了:

1packagelekkoli.test;23importjava.io.BufferedInputStream;4importjava.io.BufferedReader;5importjava.io.ByteArrayOutputStream;6importjava.io.File;7importjava.io.FileInputStream;8importjava.io.IOException;9importorg.apache.log4j.Logger;1011/**12* 网页转图片处理类,使用外部CMD13*@authorlekkoli14*/15publicclassPhantomTools {1617PRivatestaticfinalLogger _logger = Logger.getLogger(PhantomTools.class);1819//private static final String _tempPath = "/data/temp/phantom_";20//private static final String _shellCommand = "/usr/local/xxx/phantomjs /usr/local/xxx/rasterize.js "; Linux下的命令21privatestaticfinalString _tempPath = "D:/data/temp/phantom_";22privatestaticfinalString _shellCommand = "D:/xxx/phantomjs-2.0.0-windows/bin/phantomjs D:/xxx/phantomjs-2.0.0-windows/bin/rasterize.js ";2324privateString _file;25privateString _size;2627/**28* 构造截图类29* @parm hash 用于临时文件的目录唯一化30*/31publicPhantomTools(inthash) {32_file = _tempPath + hash + ".png";33}3435/**36* 构造截图类37* @parm hash 用于临时文件的目录唯一化38*@paramsize 图片的大小,如800px*600px(此时高度会裁切),或800px(此时 高度最少=宽度*9/16,高度不裁切)39*/40publicPhantomTools(inthash, String size) {41this(hash);42if(size !=null)43_size = " " +size;44}4546/**47* 将目标网页转为图片字节流48*@paramurl 目标网页地址49*@return字节流50*/51publicbyte[] getByteImg(String url)throwsIOException {52BufferedInputStream in =null;53ByteArrayOutputStream out =null;54File file =null;55byte[] ret =null;56try{57if(exeCmd(_shellCommand + url + " " + _file + (_size !=null? _size : ""))) {58file =newFile(_file);59if(file.exists()) {60out =newByteArrayOutputStream();61byte[] b =newbyte[5120];62in =newBufferedInputStream(newFileInputStream(file));63intn;64while((n = in.read(b, 0, 5120)) != -1) {65out.write(b, 0, n);66}67file.delete();68ret =out.toByteArray();69}70}else{71ret =newbyte[] {};72}73}finally{74try{75if(out !=null) {76out.close();77}78}catch(IOException e) {79_logger.error(e);80}81try{82if(in !=null) {83in.close();84}85}catch(IOException e) {86_logger.error(e);87}88if(file !=null&&file.exists()) {89file.delete();90}91}92returnret;93}9495/**96* 执行CMD命令97*/98privatestaticbooleanexeCmd(String commandStr) {99BufferedReader br =null;100try{101Process p =Runtime.getRuntime().exec(commandStr);102if(p.waitFor() != 0 && p.exitValue() == 1) {103returnfalse;104}105}catch(Exception e) {106_logger.error(e);107}finally{108if(br !=null) {109try{110

br.close();111}catch(Exception e) {112_logger.error(e);113}114}115}116returntrue;117}118}

使用上面的PhantomTools类,可以很方便地调用getByteImg方法来生成并获取图片内容。

附上我的截图配置脚本:rasterize.js,至于PhantomJS,大家就自行去官网下载吧。

转载请注明原址:http://www.cnblogs.com/lekko/p/4796062.html

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航