当前位置: 首页 > 后端技术 > Node.js

实现一个基于casperjs和resemble.js的像素比对服务

时间:2023-04-04 00:46:45 Node.js

写在最上面这次分享一个节点服务,提供设计稿和前端页面的像素比对,旨在完成一个测试或前端的辅助测试-结束人员自己。相信我,在像素级别的对比下,网页设计稿的还原度会一下子凸显出来。欢迎关注我的博客,不定时更新——效果预览前置知识这次使用了以下两个库作为辅助工具:casperjs:基于PhantomJS编写。它内部提供了一个无界面的浏览器。简单来说,你可以用它以代码的形式完成模拟浏览器的操作,其中涉及到鼠标的各种事件,还有很多其他的功能。这次主要是用到了它附带的截图功能。resemble.js:图像像素比较工具。调用方法简单理解为传入两张图片,返回一张合成图片,带有差异程度等比较参数。基本的实现思路可以理解为将图片转换成canvas,获取其图片像素,然后对每个像素进行比较。所以对于整个服务我们应该已经有了一个大的思路,就是通过casperjs进入某个网站截取某个页面,然后和设计图进行比对得到结果。整体思路通过上图,我们应该可以梳理出一个大概的流程:从前端页面接收设计稿图片和要截取的网站地址和节点信息,将设计稿保存到images文件夹,启动子进程,启动casperjs,完成对目标网站的拦截后,请求form.html填写图片地址信息回传给服务器获取图片信息。使用resemblejs将截取的图片与设计稿进行比对,并将结果传回前端页面。有一个问题可能会被注意到。即:为什么我在casperjs中截屏目标网站后不能直接将信息传回服务器,而是选择打开一个表单页面以表单的形式提交信息?答:首先,我对casperjs和node不是很了解。我的理解是,首先,casperjs不是节点模块。它在操作系统中运行。我还没有找到如何在casperjs中与节点服务建立通信。如果有办法一定要告诉我,因为我对casper真的了解不多!其次,因为无法建立沟通,只能退而求其次。我飞快的打开一个我通过casper写的表单页面,填好图片信息回传给服务器。这样就可以满足原来的要求了。于是就有了上面from.html段的操作。实现细节实现一个简单的静态服务器因为涉及到index.html和form.html页面的返回,所以需要实现一个超简单的静态服务器。代码如下:constMIME_TYPE={"css":"text/css","gif":"image/gif","html":"text/html","ico":"image/x-icon","jpeg":"image/jpeg","jpg":"image/jpg","js":"text/javascript","json":"application/json","pdf":"application/pdf","png":"image/png","svg":"image/svg+xml","swf":"application/x-shockwave-flash","tiff":"image/tiff","txt":"text/plain","wav":"audio/x-wav","wma":"audio/x-ms-wma","wmv":"video/x-ms-wmv","xml":"text/xml"}functionsendFile(filePath,res){fs.open(filePath,'r+',function(err){//根据路径打开文件if(err){send404(res)}else{letext=path.extname(filePath)ext=ext?ext.slice(1):'unknown'letcontentType=MIME_TYPE[ext]||"text/plain"//匹配文件类型fs.readFile(filePath,function(err,data){if(err){send500(res)}else{res.writeHead(200,{'content-type':contentType})res.end(data)}})}})}解析表单并将图片存入images文件夹constmultiparty=require('multiparty')//parse表单letform=newmultiparty.Form()form.parse(req,function(err,fields,files){letfilename=files['file'][0].originalFilename,targetPath=__dirname+'/images/'+filename,if(filename){fs.createReadStream(files['file'][0].path).pipe(fs.createWriteStream(targetPath))...}})通过创建可读流读出文件内容,然后通过Writethepipetothespecifiedpath保存上传的图片并运行)casperjs。stdout.on('data',(data)=>{...})可以通过spawn创建子进程来启动casperjs,也可以使用exec。截图并提交数据到form.htmlconstsystem=require('system')consthost='http://10.2.45.110:3033'constcasper=require('casper').create({//browser窗口大小viewportSize:{width:1920,height:4080}})constfileName=decodeURIComponent(system.args[4])consturl=decodeURIComponent(system.args[5])constselector=decodeURIComponent(system.args[6])constid=decodeURIComponent(system.args[7])consttime=newDate().getTime()casper.start(url)casper.then(function(){console.log('截图,请稍后')this.captureSelector('./images/casper'+id+time+'.png',selector)})casper.then(function(){casper.start(host+'/form.html',function(){this.fill('form#contact-form',{'diff':'./images/casper'+id+time+'.png','point':'./images/'+fileName,'id':id},true)})})casper.run()的代码比较简单。主要流程就是打开一个页面,然后在then中传入你的操作,最后执行run。在这个过程中,我不知道如何与节点服务通信,所以我选择了另开一个页面。.如果想深入研究,可以去casperjs官网,非常详细!通过resemble.jsfunctioncomplete(data)进行像素比对并返回数据misMatchPercentage,resultUrl='./images/'+imgNamefs.writeFileSync(resultUrl,data.getBuffer())imgObj={...}letresEnd=resObj[id]//检索初始res并返回页面数据resEnd.writeHead(200,{'Content-type':'application/json'})resEnd.end(JSON.stringify(imgObj))}letresult=resemble(diff).compareTo(point).ignoreColors().onComplete(complete)这涉及到一个点,就是我现在得到的结果应该返回到原来的请求中,而我从最初的请求到现在已经转了很多次,所以现在找不到我原来的返回体了。想了半天,只能暂时设置全局对象。收到初始请求后,将请求者的ip和时间戳设置为唯一id,作为对象的key存储,value为当前res。同时在整个转账过程中一直传递id,最终通过调用resObj[id]获取初始返回体和数据。我觉得这个方法不是最优方案,但是既然现在想不出好的方法,只好把整个服务跑一遍。.如果您有新的想法,请告诉我!!部署安装PhantomJS(osx)官网下载:phantomjs-2.1.1-macosx.zip解压路径:/User/xxx/phantomjs-2.1.1-macosx添加环境变量:~/.bash_profile添加exportPATH="$PATH到文件:/Users/xxx/phantomjs-2.1.1-macosx/bin”终端输入:phantomjs--version如果可以看到版本号,则安装成功。casperjsbrewupdate&&brewinstallcasperjsinstallresemble.jscnpmiresemblejs//写进packjson无需安装brewinstallpkg-configcairolibpngjpeggiflibcnpmicanvas//在node中运行canvasnode服务gitclonehttps://github.com/Aaaaaaaty/gui-auto-test.gitcdgui-auto-testcnpmicdpxdiffnodemonserver.js打开http://localhost:3033/index.html参考PhantomJS安装casperjs文件resemble.js文件最后一个自定义po作者的博客,正在更新中不时-如果您有任何问题,请在问题下进行交流。