使用Phantomjs和Node完成網(wǎng)頁的截屏快照的方法
由于甲方爸爸的需要,最近使用phantomjs和Node寫了一個(gè)對網(wǎng)頁內(nèi)容截屏的功能,為了避免忘記,現(xiàn)在將代碼內(nèi)容及配置流程大概描述一下.
1.首先Node是必須安裝的,而且網(wǎng)上安裝教程一大堆,在此不再贅述,Nodejs官網(wǎng)鏈接
2.然后,第二個(gè)主人公是phantomjs,官網(wǎng)下載地址,選擇對應(yīng)的系統(tǒng)下載對應(yīng)的安裝包
3.將phantomjs配置為系統(tǒng)變量,下面是Windows配置為環(huán)境變量:
配置完成之后,在cmd命令行中輸入 phantomjs -v 檢驗(yàn)是否配置成功,配置成功之后,如下圖所示:
4.擼代碼,通過查閱phantomjs入門代碼之后,了解到使用phantomjs可以預(yù)覽一個(gè)網(wǎng)頁生成圖片,PDF,base64格式等等,而我們的項(xiàng)目需要的并不是一個(gè)完整的網(wǎng)頁,而是網(wǎng)頁中的一部分內(nèi)容,所以在此基礎(chǔ)之上要改造部門內(nèi)容,現(xiàn)在講解一下代碼:
4.1)首先是express的一些設(shè)置,由于需要執(zhí)行phantomjs的命令,所以需要引入child_process模塊,具體代碼如下:
var process = require('child_process');//執(zhí)行命令行所需 var express = require('express');//express var bodyParser = require('body-parser'); var fs = require("fs");//文件操作 var app = express(); app.use('/pages',express.static('pdfs'));//設(shè)置靜態(tài)資源目錄 app.use(bodyParser.json({limit:'50mb'}));//請求內(nèi)容大小限制 app.use(bodyParser.urlencoded({limit:'50mb',extended:false})); //設(shè)置允許跨域訪問 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參數(shù),然后訪問這個(gè)url url=url.replace(/&/g,'%26');//將請求中的&轉(zhuǎn)換 var resp={ "status":'200' } res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});//設(shè)置響應(yīng)頭 if(url==''){ resp.msg='url參數(shù)不能為空'; res.end(JSON.stringify(resp)); } else{ //phantomjs執(zhí)行的命令行 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='轉(zhuǎn)換失敗,稍后重試'; res.end(JSON.stringify(resp)); }else{ //執(zhí)行成功則返回base64的數(shù)據(jù) resp.data=stdout; res.end(JSON.stringify(resp)); } }) } })
4.3)phantomjs執(zhí)行的腳本,即index.js,如下:
var page = require('webpage').create();//獲取webpage var system = require('system'), address; if (system.args.length === 1) {//執(zhí)行的命令應(yīng)該包括請求的URL,否則退出phantom console.log('Usage: URL error'); phantom.exit(); } address = system.args[1];//請求的地址 address = address.replace(/%26/g, '&');//phantom不能識別%26,所以轉(zhuǎn)為& page.viewportSize = {//設(shè)置viewport width: 1920, height: 1080, } page.open(address, function(status) {//打開頁面 setTimeout(function() {//2s之后獲取base64結(jié)果,如果直接生成有可能頁面還沒有加載完成 if (status == 'success') { var base64 = page.renderBase64('PNG'); console.log(base64);//將base64結(jié)果輸出之后,在上邊的getBase64接口中獲取 phantom.exit(); } }, 2000); })
4.4)獲取頁面中部分內(nèi)容的截圖,可以將需要截圖的DOM字符串,發(fā)送至后臺,然后新建一個(gè)空的頁面,使用phantom訪問該空白頁面,并將DOM字符串添加到預(yù)覽的頁面,然后生成截圖,具體代碼如下:
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字符串內(nèi)容未輸入'; res.end(JSON.stringify(response)); }else { fs.writeFile('tmp.txt', xmlObj, function(err) { //由于dom字符串內(nèi)容過多,所以寫入txt文本 if (err) { response.msg = '生成頁面失敗,請稍后重試'; return res.end(JSON.stringify(response)); } var strShell = 'phantomjs pages/index.js ' + reqUrl;//phantomjs執(zhí)行的命令 process.exec(strShell, { maxBuffer: 5000 * 1024, }, function(error, stdout, strerr) { if (error !== null) { response.msg = '腳本執(zhí)行錯(cuò)誤,請稍后重試'; res.end(JSON.stringify(response)); } else { response.data = stdout.replace("\r\n", ""); res.end(JSON.stringify(response));//返回結(jié)果 } }) }) } }) var server = app.listen(8808,function(){ //接口監(jiān)聽,訪問的端口 var host = server.address().address var port = server.address().port console.log('http://%s:%s',host,port); })
4.5)pages下的index.js內(nèi)容如下所示:
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,以上就是全部接口的內(nèi)容,全部的代碼可以訪問https://github.com/kim095/node-phantom進(jìn)行下載.希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
node.js連接mongoDB數(shù)據(jù)庫 快速搭建自己的web服務(wù)
這篇文章主要為大家詳細(xì)介紹了node.js連接mongoDB數(shù)據(jù)庫,如何快速搭建自己的web服務(wù),感興趣的小伙伴們可以參考一下2016-04-04node.js+postman+mongodb搭建測試注冊接口的實(shí)現(xiàn)
本文主要介紹了node.js+postman+mongodb搭建測試注冊接口的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Node.js事件循環(huán)(Event Loop)和線程池詳解
這篇文章主要介紹了Node.js事件循環(huán)(Event Loop)和線程池詳解,這篇文章比較淺顯地探討了有關(guān)事件循環(huán)的內(nèi)部運(yùn)作機(jī)制和技術(shù)細(xì)節(jié),都是經(jīng)過深思熟慮的,需要的朋友可以參考下2015-01-01iPhone手機(jī)上搭建nodejs服務(wù)器步驟方法
這篇文章主要介紹了iPhone手機(jī)上搭建nodejs服務(wù)器步驟方法,本文給出了詳細(xì)的操作步驟以及操作命令,需要的朋友可以參考下2015-07-07