这是上半年遇到的一个小需求,想实现网页的抓取,并保存为图片。研究了不少工具,效果都不理想,不是显示太差了(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",都是可以的。

二、服务器代码

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

 package lekkoli.test;

 import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.log4j.Logger; /**
* 网页转图片处理类,使用外部CMD
* @author lekkoli
*/
public class PhantomTools { private static final Logger _logger = Logger.getLogger(PhantomTools.class); // private static final String _tempPath = "/data/temp/phantom_";
// private static final String _shellCommand = "/usr/local/xxx/phantomjs /usr/local/xxx/rasterize.js "; Linux下的命令
private static final String _tempPath = "D:/data/temp/phantom_";
private static final String _shellCommand = "D:/xxx/phantomjs-2.0.0-windows/bin/phantomjs D:/xxx/phantomjs-2.0.0-windows/bin/rasterize.js "; private String _file;
private String _size; /**
* 构造截图类
* @parm hash 用于临时文件的目录唯一化
*/
public PhantomTools(int hash) {
_file = _tempPath + hash + ".png";
} /**
* 构造截图类
* @parm hash 用于临时文件的目录唯一化
* @param size 图片的大小,如800px*600px(此时高度会裁切),或800px(此时 高度最少=宽度*9/16,高度不裁切)
*/
public PhantomTools(int hash, String size) {
this(hash);
if (size != null)
_size = " " + size;
} /**
* 将目标网页转为图片字节流
* @param url 目标网页地址
* @return 字节流
*/
public byte[] getByteImg(String url) throws IOException {
BufferedInputStream in = null;
ByteArrayOutputStream out = null;
File file = null;
byte[] ret = null;
try {
if (exeCmd(_shellCommand + url + " " + _file + (_size != null ? _size : ""))) {
file = new File(_file);
if (file.exists()) {
out = new ByteArrayOutputStream();
byte[] b = new byte[5120];
in = new BufferedInputStream(new FileInputStream(file));
int n;
while ((n = in.read(b, 0, 5120)) != -1) {
out.write(b, 0, n);
}
file.delete();
ret = out.toByteArray();
}
} else {
ret = new byte[] {};
}
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
_logger.error(e);
}
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
_logger.error(e);
}
if (file != null && file.exists()) {
file.delete();
}
}
return ret;
} /**
* 执行CMD命令
*/
private static boolean exeCmd(String commandStr) {
BufferedReader br = null;
try {
Process p = Runtime.getRuntime().exec(commandStr);
if (p.waitFor() != 0 && p.exitValue() == 1) {
return false;
}
} catch (Exception e) {
_logger.error(e);
} finally {
if (br != null) {
try {
br.close();
} catch (Exception e) {
_logger.error(e);
}
}
}
return true;
}
}

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

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

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

使用PhantomJS实现网页截图服务的更多相关文章

  1. 有了 serverless,前端也可以快速开发一个 Puppeteer 网页截图服务

    更多云原生技术资讯可关注阿里巴巴云原生技术圈. Puppeteer 是什么? puppeteer 官网的介绍如下: Puppeteer is a Node library which provides ...

  2. selenium网页截图和截图定位(无界面)phantomjs

    phantomjs是一款软件,需要重新安装. 参考: https://blog.csdn.net/liyahui_3163/article/details/79064108 案例代码: from se ...

  3. 利用PhantomJS进行网页截屏

    利用PhantomJS进行网页截屏 关于PhantomJS PhantomJS 是一个基于WebKit的服务器端 JavaScript API.它全面支持web而不需浏览器支持,其快速,原生支持各种W ...

  4. php结合phantomjs实现网页截屏、抓取js渲染的页面

    首先PhantomJS快速入门 PhantomJS是一个基于 WebKit 的服务器端 JavaScript API.它全面支持web而不需浏览器支持,其快速,原生支持各种Web标准: DOM 处理, ...

  5. 通过phantomjs 进行页面截图

    本文章参考了使用phantomjs操作DOM并对页面进行截图需要注意的几个问题 及phantomjs使用说明 这两篇文章,初次接触phantomjs的童鞋可以去看下这两篇原文 在学习中可以看下 pha ...

  6. java实现网页截图

    使用工具 java+selenium+phantomjs /chromedriver /firefox 1.分别是 phantomjs插件 google截图插件 和 firefox火狐浏览器截图插件2 ...

  7. C#使用phantomjs 进行网页整页截屏

    C#使用phantomjs 进行网页整页截屏 hantomjs 是一个基于js的webkit内核无头浏览器 也就是没有显示界面的浏览器,这样访问网页就省去了浏览器的界面绘制所消耗的系统资源,比较适合用 ...

  8. 如何将phantomjs单独部署在服务端

    如何将phantomjs单独部署在服务端 文章目录 一. 容我分析(lao dao)几句 二. 服务端 Look here 服务端phantomjs搭建 web端搭建及如何调用phantomjs 三. ...

  9. 利用PhantomJS搭建Highcharts export服务

    利用PhantomJS搭建Highcharts export服务 一直在使用Highcharts做web图表的展示, 但是当发送定时的报表邮件的遇到了这个问题. 为了保证邮件图表和web页图表样式一致 ...

随机推荐

  1. C#异步编程

    什么是异步编程 什么是异步编程呢?举个简单的例子: using System.Net.Http; using System.Threading.Tasks; using static System.C ...

  2. fir.im Weekly - 关于 iOS10 适配、开发、推送的一切

    "小程序"来了,微信变成名副其实的 Web OS,新一轮的Web App 与Native App争论四起.程序员对新技术永远保持灵敏的嗅觉和旺盛的好奇心,@李锦发整理了微信小程序资 ...

  3. 嵌入式C语言代码的调试技巧

    在项目开发的过程中,不可避免的会遇到调试代码的情况. 刚开始写代码时,我们想看具体执行到哪儿时,往往这么写: printf("***** Code is here! *****\n" ...

  4. 【流量劫持】SSLStrip 的未来 —— HTTPS 前端劫持

    前言 在之前介绍的流量劫持文章里,曾提到一种『HTTPS 向下降级』的方案 -- 将页面中的 HTTPS 超链接全都替换成 HTTP 版本,让用户始终以明文的形式进行通信. 看到这,也许大家都会想到一 ...

  5. 使用C# 和Consul进行分布式系统协调

    随着大数据时代的到来,分布式是解决大数据问题的一个主要手段,随着越来越多的分布式的服务,如何在分布式的系统中对这些服务做协调变成了一个很棘手的问题.今天我们就来看看如何使用C# ,利用开源对分布式服务 ...

  6. Membership三步曲之入门篇 - Membership基础示例

    Membership 三步曲之入门篇 - Membership基础示例 Membership三步曲之入门篇 -  Membership基础示例 Membership三步曲之进阶篇 -  深入剖析Pro ...

  7. Backbone源码解析(六):观察者模式应用

    卤煮在大概一年前写过backbone的源码分析,里面讲的是对一些backbone框架的方法的讲解.这几天重新看了几遍backbone的源码,才发现之前对于它的理解不够深入,只关注了它的一些部分的细节和 ...

  8. Hadoop2 自己动手编译Hadoop的eclipse插件

    前言:       毕业两年了,之前的工作一直没有接触过大数据的东西,对hadoop等比较陌生,所以最近开始学习了.对于我这样第一次学的人,过程还是充满了很多疑惑和不解的,不过我采取的策略是还是先让环 ...

  9. Eclipse常用设置

    用惯了VS,再回过去用Eclipse真是一件痛苦的事.so,在这里记录下使用过程中的一些设置以做备忘. 1.代码自动提示 在我们忘记方法名或者想偷懒时,代码自动提示很管用.不过Eclipse默认是输入 ...

  10. 自用的基于Emit的C#下DataTable转实体类方法

    之前一直在做WebForm的开发,数据绑定时直接DataTable绑定Gridview很方便,但是最近开始往MVC转,数据列表的传递和页面展示基本上是以List为主,像下面这样,遍历实体类的各个字段去 ...