报表开发神器:phantomjs生成PDF ,Echarts图片,自动生成word文档实战

报表开发神器:phantomjs生成网页PDF ,Echarts报表实战

一. 关于phantomjs

1.1 什么是phantomjs?

(1)一个基于webkit内核的无头浏览器,即没有UI界面,即它就是一个浏览器,只是其内的点击、翻页等人为相关操作需要程序设计实现。
(2)提供javascript API接口,即通过编写js程序可以直接与webkit内核交互,在此之上可以结合java语言等,通过java调用js等相关操作,从而解决了以前c/c++才能比较好的基于webkit开发优质采集器的限制。
(3)提供windows、linux、mac等不同os的安装使用包,也就是说可以在不同平台上二次开发采集项目或是自动项目测试等工作。

1.2 phantomjs常用API介绍

  1. 常用内置几大对象

    • var system=require(‘system’); //获得系统操作对象,包括命令行参数、phantomjs系统设置等信息
    • var page = require(‘webpage’); //获取操作dom或web网页的对象,通过它可以打开网页、接收网页内容、request、response参数,其为最核心对象。
    • var fs = require(‘fs’); //获取文件系统对象,通过它可以操作操作系统的文件操作,包括read、write、move、copy、delete等。
  2. 常用API

    • page.onLoadStarted = function() {}//当page.open调用时,回首先执行该函数,在此可以预置一些参数或函数,用于后边的回调函数中
    • page.onResourceError = function(resourceError) {} //page的所要加载的资源在加载过程中,出现了各种失败,则在此回调处理
    • page.onResourceRequested = function(requestData, networkRequest) {} //page的所要加载的资源在发起请求时,都可以回调该函数
    • page.onResourceReceived = function(response) {} //page的所要加载的资源在加载过程中,每加载一个相关资源,都会在此先做出响应,它相当于http头部分, 其核心回调对象为response,可以在此获取本次请求的cookies、userAgent等
    • page.onConsoleMessage = function (msg) {}//欲在执行web网页时,打印一些输出信息到控制台,则可以在此回调显示。
    • page.onAlert = function(msg) {} //phantomjs是没有界面的,所以对alert也是无法直接弹出的,故phantomjs以该函数回调在page在执行过程中的alert事件
    • page.onError = function(msg, trace) {} //当page.open中的url,它自己(不包括所引起的其它的加载资源)出现了异常,如404、no route to web site等,都会在此回调显示。
    • page.onUrlChanged = function(targetUrl) {} // 当page.open打开的url或是该url在打开过程中基于该URL进行了跳转,则可在此函数中回调。
    • page.onLoadFinished = function(status){} // 当page.open的目标URL被真正打开后,会在调用open的回调函数前调用该函数,在此可以进行内部的翻页等操作
    • page.evaluate(function(){});// 在所加载的web page内部执行该函数,像翻页、点击、滑动等,均可在此中执行
    • page.render("");//将当前page的现状渲染成图片,输出到指定的文件中去。
  3. 注意事项

    • 区分phantomjs的对象和打开的web page的对象,如document、window等,两者都有,在调用page.evaluate和不调用的时候,注意区分二者的范围,容易在调试时出现很多的问题,且不好发现。

    • page.injectJs和page.includeJs的区别,前者侧重本地的js文件,与libraryPath挂购,后者侧重网络js文件,尤其在引入jquery等第三方库时,会经常遇到。

    • 编码问题,两个重要参数,–output-encoding,–script-encoding,前者为输出编码,后者为所使用js、参数配置文件的编码,为方便起鉴,建议均采用utf-8编码,并注所应用到的目标文件的编码,以免引起很不可思议的异常,又无从查起。

  4. 使用总结 : 主要是java se+js+phantomjs的应用,

    • 编写好js脚文程序,预留出所有可配置参数,并提供json文件传输相关参数。

    • 通过java程序,定义相关参数并生成对应的json文件。

    • 通过java命令行调用API,调用phantomjs命令,并传入js、配置文件路径,从而开启爬虫。

    • 首先采集关键词的搜索页的链接集合,最后统一去遍历采集具体的对象网页。

1.3 使用phantomjs 能做什么?

  • 能够通过网页url,获取到此网页的数据,进行数据采集,网站爬取;
  • 在本人实战中,通过 phantomjs 和数据 生成图表,如下:
    在这里插入图片描述
  • 在本人实战中,可通过 phantomjs 截图网页页面,并且生成样式一模一样的PDF文件,如下:
    在这里插入图片描述

生成的PDF基本还原了其原来的样式,图片和文字分开了,并非直接截图;有生成PDF相关需求的,可以思考生成使用phantomjs 如何实现功能;本人有通过Html模板,生成Html页面,然后将此页面上传至FastDfs服务器,然后通过返回的url直接生成此pdf,即完成了html页面一致的pdf生成功能;

  • 在接下来的文档中,本人将会详细介绍如何使用 phantomjs 生成pdf 以及报表相关的图片功能;

二. Windows下安装 phantomjs

2.1 概述

  • Windows下安装phantomjs比较简单。(目前官方支持三种操作系统,包括Windows\Mac OS\Linux这三大主流的环境,根据自己的运行环境选择要下载的包进行下载)
  • 总结来讲就是 下载后解压phantomjs配置环境变量

2.1 下载并安装phantomjs

  • 进入官网,选择自身电脑系统对应版本下载 官网地址
  • 下载好后,进入文件的bin 目录,复制文件路径,开始准备配置环境变量
  • 鼠标右击__我的电脑__选择 高级系统设置__然后点击环境变量,再然后选择__系统变量,点击Path,将phantomjs的bin文件夹所在路径添加至环境变量;如图所示:
    • 在这里插入图片描述
  • 测试是否安装成功:
    • 打开cmd 输入phantomjs -v 显示当前版本号,若显示版本号则表示安装成功!
    • 如图所示:
      • 在这里插入图片描述

三. Linux下 安装 phantomjs

3.1 概述

  • Linux下安装有三个过程:1. 安装 2.配置环境变量 3. 解决中文乱码(生成图片时可能会图片内的中文乱码)

3.2 安装过程如下:

  • 依次执行以下命令:

       wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
    
       yum install bzip2 # 安装bzip2
    
       tar -jxvf phantomjs-2.1.1-linux-x86_64.tar.bz2
    
       mv phantomjs-2.1.1-linux-x86_64 /usr/local/src/phantomjs
    
       ln -sf /usr/local/src/phantomjs/bin/phantomjs /usr/local/bin/phantomjs
    
       yum install fontconfig freetype2
    
       phantomjs -v # 测试版本号
    

    当执行完此命令时,phantomjs已安装成功。可以开始配置环境变量了。

  • 配置环境变量
    1. 连接至Linux服务器,进入profile文件
      vim /etc/profile
      
    2. 在profile文件的最后一行中,添加安装路径path语句(注意路径是phantomjs的安装路径)
      export PATH=${PATH}:/usr/local/src/phantomjs/bin/
      
    3. 如果是超级用户,则配置:
      export PATH=$PATH:/root/phantomjs/bin
      
    4. 在Linux服务器的任意文件目录中输入命令: phantomjs
      • 如果能成功进入phantomjs的界面,则表示配置环境变量成功。成功如图所示:
        在这里插入图片描述

      进入里面后可执行js命令,如果需要退出,则按 Ctrl+C 强制退出

  • 解决中文乱码(可选,可遇到此问题再行解决)
    1. 正常示例:(Windows上显示正常如图:)
      • 在这里插入图片描述
    2. 错误示例:(Linux上显示中文乱码如图:)
      • 在这里插入图片描述
    3. 解决办法:
      1. 在Linux中执行命令:
        yum install bitmap-fonts bitmap-fonts-cjk
        

        执行此命令后,可能只是中文显示出来了,数字还是会显示空格,如果出现数字显示空格,则把windows所有字体导入Linux中,见下面。

      2. 导入字体:
        • 将Windows字体全部复制,导入到Linux中。
        • 在/usr/share/fonts/下新建micro文件夹。
        • 将字体全部放入micro中。

四. 利用Phantomjs生成Echarts图片

4.1 概述:

  • 实现原理:
    • 在Windows下:
      • 在本地电脑中,我们首先安装Phantomjs在本地电脑上,并配置好环境变量,可参照章节二教程;
      • 准备好 jquery.1.9.1.min.js,echarts-convert.js,echarts.min.js三个文件。
      • 编写Demo程序,运行主Main方法
    • 在Linux 下:
      • 在Linux系统汇总,我们首先安装Phantomjs在本地电脑上,并配置好环境变量,可参照章节三教程;
      • 其他操作与在Windows操作类似。

    WIndows与Linux环境下的区别:①配置好环境变量,因为phantomjs的启动方式,windows是执行exe文件,linux不是,所以配好环境变量后java在本机测试与在Linux下无需做任何修改;② Phantomjs执行生成Echarts图片时,需要引用到 jquery.1.9.1.min.js ,echarts-convert.js, echarts.min.js 以及生成Echarts的js文件。这些js需要引用到,而当部署在Linux中时,生成的js文件在jar包中,不一定能读取到,我们可以通过代码将js文件复制生成到jar包同级目录,然后通过路径加载。路径加载可以用如下代码读取并生成:
    ~~~java
    /* 将模板生成到指定的位置 判断文件是否存在,如果不存在则创建 */
    File echartsfile = new File(System.getProperty(“user.dir”) + “\echarts-all.js”);
    if (!echartsfile.exists()) {
    FileUtil.file2file(“js/echarts-all.js”, System.getProperty(“user.dir”) + “\echarts-all.js”);
    }
    ~~~

4.2 笔者实现思路:

  • 第一步:写出核心代码:
        public static void main(String[] args) throws Exception {
        Runtime rt = Runtime.getRuntime();
        //windows 本地地址
        Process p = rt.exec("phantomjs " +"C:\\Code\\Demo\\echarts-convert.js" + " -infile " + "C:\\Code\\Demo\\Demo1\\src\\main\\resources\\echarts\\optionsjs\\" + "1187559506027646976.js -outfile " + "C:\\Demo\\" + "123.png -scale 0.01 -width 1200");
        InputStream is = p.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        StringBuffer sbf = new StringBuffer();
        String tmp = "";
        while ((tmp = br.readLine()) != null) {
            sbf.append(tmp);
        }
        System.out.println(sbf);
    }
    
  • 相关js文件下载
    • 如图:
  • 第二步:整理思路:
  1. 生成需要生成的Echarts的js代码:
    1. 找到相关Echarts图片模板: Echarts官网
    2. 使用Framework以及其他技术:将模板+数据生成一个最终js文件;
      1. 使用Framework为例:
        • 导入xml依赖:
            <!-- framework-->
          <dependency>
              <groupId>org.freemarker</groupId>
              <artifactId>freemarker</artifactId>
              <version>2.3.26-incubating</version>
          </dependency>
          
        • 代码合成最终js文件示例:
          	    // 生成文件
          	    public  void createDocNew(Map<String,Object> map,String templatePath,String templateName,String outFilePath) throws Exception{
          	        try (Writer out=new FileWriter(outFilePath)){
          	            //创建一个配置对象,获取该对象的版本
          	            Configuration configuration=new Configuration(Configuration.getVersion());
          	            //获取模板所在目录
          	            configuration.setDirectoryForTemplateLoading(new File(templatePath));
          	            //设置编码集
          	            configuration.setDefaultEncoding("utf-8");
          	            //获取模板对象
          	            Template template=configuration.getTemplate(templateName);
          	            //输出文件至指定目录
          	            template.process(map,out);
          	            //关闭流
          	        } catch (Exception e) {
          	            e.printStackTrace();
          	        }
          	    }
          
            > 这里的代码就是将map里存储的值以及模板地址,和outFilePath的生成地址接收,然后生成出最终的js文件。关于Framework的语法,可以去具体学习,这里不做赘述;当然也可以使用别的方式或者别的模板生成方式;
          
  2. 将其他的三个js文件放到其他位置上,博主的做法是将这三个放到jar包目录内,但是会存在phantomjs无法读取和执行的情况(就是除开phantomjs的代码可以读取到内容,但phantomjs的执行无法引用读取)。所以博主采取的是先读取出来,再写到jar包外面进行引用;这样通过路径,在Linux下也可以读取了;读取代码示例:
                /*  将模板生成到指定的位置  判断文件是否存在,如果不存在则创建 */
           File echartsfile = new File(System.getProperty("user.dir") + "\\echarts-all.js");
           if (!echartsfile.exists()) {
               FileUtil.file2file("js/echarts-all.js", System.getProperty("user.dir") + "\\echarts-all.js");
           }
    
           File jsfile = new File(outPathAndName);
           if (!jsfile.exists()) {
               FileUtil.string2File(outPathAndName, echartTemplate.getFileContent());         //  将js文件生成到指定的位置
           }
           File convertfile = new File(System.getProperty("user.dir") + "\\echarts-convert.js");
           String echartsPath = System.getProperty("user.dir") + "\\echarts-convert.js";
           if (!convertfile.exists()) {
               FileUtil.file2file("js/echarts-convert.js", echartsPath);
           }
           File jqueryfile = new File(System.getProperty("user.dir") + "\\jquery.1.9.1.min.js");
           if (!jqueryfile.exists()) {
               FileUtil.file2file("js/jquery.1.9.1.min.js", System.getProperty("user.dir") + "\\jquery.1.9.1.min.js");
           }
    

    重点代码:System.getProperty(“user.dir”) 为 Windows下或者Linux下的当前路径 ,具体可百度其用法。

  3. 结合已经有的 echarts-convert.js 等文件+ 生成好的带数据的Echarts.js 文件 和 Demo示例代码可以生成出Echarts图片了;我们可以将Echart图片再上传至Fastdfs等图片服务器,就可以拿到网络图片url了;当然最后一步视业务需求而定;

五. 利用Phantomjs生成PDF文档(HTML转为PDF)

5.1 概述

  • 生成PDF文档的技术有很多种;使用Phantomjs生成PDF的优点在于:①操作简单方便 ②生成的PDF质量高,与原来的一致,所见即所得 ③. 免费,无任何隐形广告
  • 目前博主研究的的是HTML生成PDF,其他的还未研究,不知道是否可行,具体可百度。这里讲的也是将HTML转为PDF文档
  • 示例代码:
    • 核心示例demo:
          public static String parseHtml2Pdf2(String url) throws IOException {
          Runtime rt = Runtime.getRuntime();
          Process p = rt.exec("C:/App/phantomjs-2.1.1-windows/bin/phantomjs.exe "+  "C:\\Code\\demo\\parsers\\src\\main\\resources\\wordfiles\\js\\jstemplate\\1190147431954702336.js "+url);
          InputStream is = p.getInputStream();
          BufferedReader br = new BufferedReader(new InputStreamReader(is));
          StringBuffer sbf = new StringBuffer();
          String tmp = "";
          while ((tmp = br.readLine()) != null) {
              sbf.append(tmp);
          }
          String resultstr = sbf.toString();
          String[] arr = resultstr.split("\\$");
          String result = "";
          for(String s : arr){
              if(s.endsWith("pdf"))result = s;
          }
          return result;
      }
      
    • js模板(1190147431954702336.js):
      var page = require('webpage').create();
      var system = require('system');
      
      ////读取命令行参数,也就是js文件路径。
      if (system.args.length === 1) {
          console.log('Usage: loadspeed.js <some URL>');
      //这行代码很重要。凡是结束必须调用。否则phantomjs不会停止
          phantom.exit();
      }
      page.settings.loadImages = true;  //加载图片
      page.settings.resourceTimeout = 30000;//超过10秒放弃加载
      //截图设置,
      //page.viewportSize = {
      //  width: 1000,
      //  height: 3000
      //};
      var address = system.args[1];
      page.open(address, function(status) {
      
          function checkReadyState() {//等待加载完成将页面生成pdf
              setTimeout(function () {
                  var readyState = page.evaluate(function () {
                      return document.readyState;
                  });
      
                  if ("complete" === readyState) {
                      page.paperSize = { width:'297mm',height:'500mm',orientation: 'portrait',border: '1cm' };
                      var timestamp = Date.parse(new Date());
                      var outpathstr = 'C:/Demo/parsers/src/main/resources/wordfiles/pdf_file/1189813692544335872.pdf';
                      page.render(outpathstr);
                      //page.render("c://test.png");
                      //console.log就是传输回去的内容。
                      console.log("生成成功");
                      console.log("$"+outpathstr+"$");
                      phantom.exit();
                  } else {
                      checkReadyState();
                  }
              },1000);
          }
          checkReadyState();
      });
      

      这里的 var outpathstr = ‘C:/Demo/parsers/src/main/resources/wordfiles/pdf_file/1189813692544335872.pdf’;需要我们去修改为实际导出的地址,同时要注意在Linux下的路径问题;

5.2 生成原理

  • 通过示例demo传入的url (Html 页面) + 引入的js内的导出地址(pdf导出地址)+ 示例Demo代码,即可将html页面转换成PDF并保存在指定的地址上;
  • 这里的pdf是通过 phantomjs(无头浏览器) +加载Html页面+ 使用phantomjs的截图功能 然后生成PDF文件;生成的pdf文件无损 且与真实PDF一致,质量很高;

5.3 扩展思路

  • 虽然生成pdf是通过Html进行转换的;当我们只需要pdf,不需要html的时候,也可以通过这种简接的方式生成pdf,最后把html删掉就可以啦;
  • PDF=HTML模板页面+数据+模板化技术

六.利用Phantomjs+Poi.tl 生成Word文档

6.1 概述

  • 通过Phantomjs 我们可以生成出Echarts图片;
  • 通过Poi.tl我们可以生成出表格,文字,图片等内容;
  • 通过Phantomjs+Poi.tl,我们就可以生成出带Echarts图片的报表了~!!
  • poi-tl使用介绍及简单教程

6.2 思路

  • 通过Phantomjs生成Echarts图片,并上传至fastdfs服务器,我们就可以拿到图片的网络地址了;
  • 通过Pol.tl我们可以加载Echarts的网络图片,并且也可以使用表格,其他图片,文字等信息;
  • 执行步骤:
    1. 当我们点击生成报表的时候,就会先去请求相关的数据接口,拿到数据后,利用phantomjs生成Echarts图片,并上传至fastdfs服务器拿到图片地址url;
    2. 需要生成表格等的数据,就利用Poi.tl生成表格;
    3. 利用poi.tl将文字以及Echarts等数据融入word文档内;
    4. 利用poi.tl生成word文档,并上传至fastdfs,拿到下载url后返回给前端;
    5. 完成!
  • 生成界面如下:
    在这里插入图片描述
发布了127 篇原创文章 · 获赞 52 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_37128049/article/details/102805791
今日推荐