使用Phantomjs和Node完成网页的截屏快照的方法


Posted in Javascript onJuly 16, 2019

由于甲方爸爸的需要,最近使用phantomjs和Node写了一个对网页内容截屏的功能,为了避免忘记,现在将代码内容及配置流程大概描述一下.

1.首先Node是必须安装的,而且网上安装教程一大堆,在此不再赘述,Nodejs官网链接

2.然后,第二个主人公是phantomjs,官网下载地址,选择对应的系统下载对应的安装包

3.将phantomjs配置为系统变量,下面是Windows配置为环境变量:

使用Phantomjs和Node完成网页的截屏快照的方法

配置完成之后,在cmd命令行中输入 phantomjs -v 检验是否配置成功,配置成功之后,如下图所示:

使用Phantomjs和Node完成网页的截屏快照的方法

4.撸代码,通过查阅phantomjs入门代码之后,了解到使用phantomjs可以预览一个网页生成图片,PDF,base64格式等等,而我们的项目需要的并不是一个完整的网页,而是网页中的一部分内容,所以在此基础之上要改造部门内容,现在讲解一下代码:

4.1)首先是express的一些设置,由于需要执行phantomjs的命令,所以需要引入child_process模块,具体代码如下:

var process = require('child_process');//执行命令行所需
var express = require('express');//express
var bodyParser = require('body-parser');
var fs = require("fs");//文件操作
var app = express();
 
app.use('/pages',express.static('pdfs'));//设置静态资源目录
app.use(bodyParser.json({limit:'50mb'}));//请求内容大小限制
app.use(bodyParser.urlencoded({limit:'50mb',extended:false})); 
 
//设置允许跨域访问
var allowCrossDomain = function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.header('Access-Control-Allow-Credentials','true');
  next();
};
 
app.use(allowCrossDomain);

4.2)然后就是生成页面的base64接口的方法,如下:

app.get('/getBase64',function(req,res){
	var url=req.query.url;//读取请求中的url参数,然后访问这个url
  url=url.replace(/&/g,'%26');//将请求中的&转换 
	var resp={
	  "status":'200'
	}
	res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});//设置响应头
	if(url==''){
    resp.msg='url参数不能为空';
    res.end(JSON.stringify(resp));  
	}
	else{
    //phantomjs执行的命令行 index.js在后文中给出
		var strShell='phantomjs --disk-cache=true --disk-cache-path=. index.js '+url;
    process.exec(strShell,{
    	maxBuffer:5000*1024,
    },function(error,stdout,strerr){
    	if(error!==null){
        console.log(error);
    		resp.msg='转换失败,稍后重试';
    		res.end(JSON.stringify(resp));
    	}else{
        //执行成功则返回base64的数据
    		resp.data=stdout;
    		res.end(JSON.stringify(resp));
    	}
    })
	}
 
})

4.3)phantomjs执行的脚本,即index.js,如下:

var page = require('webpage').create();//获取webpage
var system = require('system'),
  address;
 
if (system.args.length === 1) {//执行的命令应该包括请求的URL,否则退出phantom
  console.log('Usage: URL error');
  phantom.exit();
}
address = system.args[1];//请求的地址
address = address.replace(/%26/g, '&');//phantom不能识别%26,所以转为&
page.viewportSize = {//设置viewport
  width: 1920,
  height: 1080,
}
page.open(address, function(status) {//打开页面
  setTimeout(function() {//2s之后获取base64结果,如果直接生成有可能页面还没有加载完成
    if (status == 'success') {
      var base64 = page.renderBase64('PNG');
      console.log(base64);//将base64结果输出之后,在上边的getBase64接口中获取
      phantom.exit();
    }
  }, 2000);
})

4.4)获取页面中部分内容的截图,可以将需要截图的DOM字符串,发送至后台,然后新建一个空的页面,使用phantom访问该空白页面,并将DOM字符串添加到预览的页面,然后生成截图,具体代码如下:

app.post('/getPartPage', function(req, res) {
  var xmlObj = req.body.xmlObj;//获取DOM字符串
  const reqUrl = 'http:example.com/tmp.html';//要访问的空页面
  var response = {
    "status": '200',
  };
  if (xmlObj == undefined || xmlObj == '' || xmlObj == null) {
    response.msg = 'DOM字符串内容未输入';
    res.end(JSON.stringify(response));
  }else {
    fs.writeFile('tmp.txt', xmlObj, function(err) { //由于dom字符串内容过多,所以写入txt文本
      if (err) {
        response.msg = '生成页面失败,请稍后重试';
        return res.end(JSON.stringify(response));
      }
 
      var strShell = 'phantomjs pages/index.js ' + reqUrl;//phantomjs执行的命令
      process.exec(strShell, {
        maxBuffer: 5000 * 1024,
      }, function(error, stdout, strerr) {
        if (error !== null) {
          response.msg = '脚本执行错误,请稍后重试';
          res.end(JSON.stringify(response));
        } else {
          response.data = stdout.replace("\r\n", "");
          res.end(JSON.stringify(response));//返回结果
        }
 
      })
 
    })
 
  }
 
})
 
var server = app.listen(8808,function(){ //接口监听,访问的端口
	var host = server.address().address
	var port = server.address().port
  console.log('http://%s:%s',host,port);
})

4.5)pages下的index.js内容如下所示:

var page = require('webpage').create();//获取webpage
var fs = require('fs');
var system = require('system'),
  address,filename;
 
if (system.args.length === 1) {
  console.log('Usage: URL error');
  phantom.exit();
}
address = system.args[1];//请求的路径
address = address.replace(/%26/g, '&');
filename = (new Data()).getTime();
page.viewportSize = {
  width: 750,
}
page.paperSize = { //生成A4大小的PDF文件
  format: 'A4',
  orientation: 'portrait',
  margin: '0.8cm'
}
page.open(address, function(status) {
  var info = fs.read('tmp.txt');//读取DOM字符串
  var result = page.evaluate(function(info) {
    try {
      document.querySelector('#dom').innerHTML = info;//将dom字符串拼接
    } catch (e) {
      console.log(e);
    }
 
    return document.querySelector('#dom').innerHTML;//返回页面
  }, info);
  setTimeout(function() {
    page.paperSize = {
      format: 'A4',
      orientation: 'portrait',
      margin: '0.8cm'
    };
    page.viewportSize = {
      width: 750,
    };
    //生成PDF文件 
    page.render('pages/' + filename + '.pdf', { format: 'pdf', quality: '100' });
    console.log('http://example.com/pages/' + filename + '.pdf');//返回PDF文件的访问路径
    phantom.exit();
  }, 500);
})

OK,以上就是全部接口的内容,全部的代码可以访问https://github.com/kim095/node-phantom进行下载.希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript解决常见浏览器兼容问题的12种方法
Jan 04 Javascript
基于jquery的获取mouse坐标插件的实现代码
Apr 01 Javascript
jQuery 和 CSS 的文本特效插件集锦
Dec 12 Javascript
基于jquery实现瀑布流布局
Jun 28 Javascript
从零学习node.js之express入门(六)
Feb 25 Javascript
node.js入门学习之url模块
Feb 25 Javascript
基于vue 动态加载图片src的解决方法
Feb 05 Javascript
全面解析vue router 基本使用(动态路由,嵌套路由)
Sep 02 Javascript
vue-cli3.0 环境变量与模式配置方法
Nov 08 Javascript
webpack中如何使用雪碧图的示例代码
Nov 11 Javascript
layui自定义ajax左侧三级菜单
Jul 26 Javascript
使用Vue实现一个树组件的示例
Nov 06 Javascript
详解微信小程序支付流程与梳理
Jul 16 #Javascript
如何在项目中使用log4.js的方法步骤
Jul 16 #Javascript
JAVA面试题 static关键字详解
Jul 16 #Javascript
微信小程序实现下拉框功能
Jul 16 #Javascript
javascript中的this作用域详解
Jul 15 #Javascript
微信小程序页面上下滚动效果
Nov 18 #Javascript
node.js实现上传文件功能
Jul 15 #Javascript
You might like
discuz authcode 经典php加密解密函数解析
2020/07/12 PHP
PHP6 中可能会出现的新特性预览
2014/04/04 PHP
php解决约瑟夫环示例
2014/04/09 PHP
php简单图像创建入门实例
2015/06/10 PHP
PHP实现C#山寨ArrayList的方法
2015/07/16 PHP
PHP比较运算符的详细介绍
2015/09/29 PHP
PHP数组的定义、初始化和数组元素的显示实现代码
2016/11/05 PHP
微信公众号开发之获取位置信息php代码
2018/06/13 PHP
JavaScript 继承详解(二)
2009/07/13 Javascript
js保存当前路径(cookies记录)
2010/12/14 Javascript
jquery.validate分组验证代码
2011/03/17 Javascript
jquery中交替点击事件的实现代码
2014/02/14 Javascript
javascript学习笔记(八)正则表达式
2014/10/08 Javascript
JavaScript实现在页面间传值的方法
2015/04/07 Javascript
jQuery实现的类似淘宝网站搜索框样式代码分享
2015/08/24 Javascript
JS实现的最简Table选项卡效果
2015/10/14 Javascript
Jquery Mobile 自定义按钮图标
2015/11/18 Javascript
JavaScript实现显示函数调用堆栈的方法
2016/04/21 Javascript
sso跨域写cookie的一段js脚本(推荐)
2016/05/25 Javascript
让浏览器崩溃的12行JS代码(DoS攻击分析及防御)
2016/10/10 Javascript
Vue axios 中提交表单数据(含上传文件)
2017/07/06 Javascript
一个简易时钟效果js实现代码
2020/03/25 Javascript
基于Vue+elementUI实现动态表单的校验功能(根据条件动态切换校验格式)
2019/04/04 Javascript
Nodejs 识别图片类型的方法
2019/08/15 NodeJs
解决React在安装antd之后出现的Can't resolve './locale'问题(推荐)
2020/05/03 Javascript
[52:22]EG vs VG Supermajor小组赛B组 BO3 第一场 6.2
2018/06/03 DOTA
使用简单工厂模式来进行Python的设计模式编程
2016/03/01 Python
Python数据类型详解(一)字符串
2016/05/08 Python
Python利用Scrapy框架爬取豆瓣电影示例
2020/01/17 Python
Python 常用日期处理 -- calendar 与 dateutil 模块的使用
2020/09/02 Python
精油和天然健康美容产品:Art Naturals
2018/01/27 全球购物
linux系统都有哪些运行级别
2012/04/15 面试题
如何掌握自荐信格式呢
2013/11/19 职场文书
我的求职计划书
2014/01/10 职场文书
安全先进个人材料
2014/12/29 职场文书
Android RecyclerView实现九宫格效果
2022/06/28 Java/Android