PhantomJS介绍
PhantomJS
是一个基于webkit
内核的无头浏览器,即没有UI界面的一个浏览器,只是其内的点击、翻页等人为相关操作需要程序设计实现。PhantomJS
提供JavaScript API接口,即通过编写js程序可以直接与webkit
内核交互,在此之上可以结合Java语言等,通过java调用js等相关操作,从而解决了以前c/c++
才能比较好的基于webkit
开发优质采集器的限制。
PhantomJS的安装配置
windows环境
如果是在windows环境下,则在官网下载解压到某个目录后,将其bin目录加入到path
变量中即可。
Linux环境
如果是在Linux
环境下,在官网下载解压后,同样需要将PhantomJS
的bin
目录加入到path
环境变量中,参考的命令和配置如下:
# 编辑配置文件.
vi ~/.bashrc
# 将PhantomJS的bin目录加入到PATH环境变量中.
export PHANTOMJS_HOME=/home/blinkfox/Documents/phantomjs-2.1.1-linux-x86_64
export PATH=${PHANTOMJS_HOME}/bin:$PATH
# 退出vi编辑器,使用source命令让刚才的配置即时生效.
source ~/.bashrc
# 测试PhantomJS是否安装成功,如果打出了版本信息,即安装成功.
phantomjs -v
demo示例
这个demo的需求是这样的,我们使用Java调用PhantomJS
的指令来在服务端加载含ECharts
统计的图jsp
文件,等待jsp页面渲染成功之后,利用PhantomJS浏览器的截图功能,截图后保存到指定目录
首先,制作ECharts
的jsp页面,示例页面如下代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试的ECharts数据统计图</title>
</head>
<body>
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="main" style="width:560px; height:270px;"></div>
<script type="text/javascript" src="/js/lib/jquery/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="/js/lib/echarts/v3/echarts.min.js"></script>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option = {
title: {
text: 'ECharts 入门示例'
},
animation: false, // 关闭动画效果
tooltip: {},
legend: {
data:['销量']
},
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>
然后,是书写PhantomJS脚本echarts_load.js
来加载和调用图片下载的代码:
ps:phantomjs 基础及实例可看此文章:https://blog.csdn.net/zhulin2609/article/details/49188851
var system = require('system');
var page = require('webpage').create();
// 如果是windows,设置编码为gbk,防止中文乱码,Linux本身是UTF-8
var osName = system.os.name;
console.log('os name:' + osName);
if ('windows' === osName.toLowerCase()) {
phantom.outputEncoding="gbk";
}
// 获取第二个参数(即请求地址url).
var url = system.args[1];
console.log('url:' + url);
// 显示控制台日志.
page.onConsoleMessage = function(msg, lineNum, sourceId) {
console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};
//打开给定url的页面.
var start = new Date().getTime();
page.open(url, function(status) {
if (status == 'success') {
console.log('echarts页面加载完成,加载耗时:' + (new Date().getTime() - start) + ' ms');
// 由于echarts动画效果,延迟500毫秒确保图片渲染完毕再调用下载图片方法.
setTimeout(function() {
page.evaluate(function() {
//name带上相对路径即可 比如“/aaa/bbb/aaa.png”
page.render(name);
console.log("调用了echarts的截图图片功能.");
});
}, 500);
} else {
console.log("页面加载失败 Page failed to load!");
}
// 3秒后再关闭浏览器.
setTimeout(function() {
phantom.exit();
}, 3000);
});
最后,是使用Java
来调用PhantomJS
的指令,代码如下:
public class HttpTest {
private static final Logger log = LoggerFactory.getLogger(HttpTest.class);
private static final String PHANTOM_PATH = "phantomjs";
//这里我的test.js是保存在G盘下面的phantomjs目录
private static final String TEST_JS = "G:/test/phantom/test.js ";
public void String downloadImage(String url) throws IOException {
String cmdStr = PHANTOM_PATH + TEST_JS + url;
log.info("命令行字符串:{}", cmdStr);
Runtime rt = Runtime.getRuntime();
try {
rt.exec(cmdStr);
} catch (IOException e) {
log.error("执行phantomjs的指令失败!请检查是否安装有PhantomJs的环境或配置path路径!PhantomJs详情参考这里:http://phantomjs.org", e);
}
}
/**
* main.
* @param args args
* @throws IOException IO异常
*/
public static void main(String[] args) throws IOException {
downloadImage("http://127.0.0.1:8080/test/echart_test/test_echarts.html");
}
/**
* @Title: MakeHtml
* @Description: 创建html
* @param head html 标题
* @param body 需要显示的内容
* @param disrPath 生成html的存放路径
* @return void 返回类型
* @throws
*/
public static void MakeHtml(String head,String body,String disrPath ){
try {
String templateContent="";
FileInputStream fileinputstream = new FileInputStream(REPORT_TEMPLATE);// 读取模板文件
log.info("模板路径:"+REPORT_TEMPLATE);
int lenght = fileinputstream.available();
byte bytes[] = new byte[lenght];
fileinputstream.read(bytes);
fileinputstream.close();
templateContent = new String(bytes);
templateContent = templateContent.replaceAll("###head###", head);
log.info("标题:"+head);
templateContent = templateContent.replaceAll("###body###", body);
log.info("图片:"+body);
log.info(templateContent);
String filename = PATH+disrPath;// 生成的html文件保存路径。
FileOutputStream fileoutputstream = new FileOutputStream(filename);// 建立文件输出流
log.info("文件输出路径:"+filename);
byte tag_bytes[] = templateContent.getBytes();
fileoutputstream.write(tag_bytes);
fileoutputstream.close();
} catch (Exception e) {
e.printStackTrace();
log.error("makeHtml error:"+e.getMessage(),e);
}
}
/**
* 文件夹打包
* @param srcDir 需打包的文件 f:/abc
* @param outFile 输出路径 f:/abc.zip
* 不会自动生成文件夹需自行判断
*/
public static void toZip(String srcDir, String outFile) {
FileOutputStream out;
//判断存储路径是否存在(只有一级)
String filePath=outFile.substring(0,outFile.lastIndexOf("/"));
File file=new File(PATH+filePath);
if(!file.exists()) {
file.mkdir();
}
try {
Thread.sleep(30000);
out = new FileOutputStream(new File(PATH+outFile));
ZipUtils.toZip(PATH+srcDir, out,true);
} catch (Exception e) {
log.error("客户月报截图打包打包失败:"+e.getMessage(),e);
log.error(e.getMessage(),e);
}
}
}