this time shared a node service that provides design comparison with pixel contrast of front page, aiming at completing a supplementary test for testing or front-end personnel themselves. Believe me, under the contrast of the pixel level, the degree to which the page is reduced to the design draft will be highlighted. The following words are not much said, come together to see the detailed introduction.

style= #ff0000" >

the pre knowledge used in the following two libraries as auxiliary tools:

  • casperjs: the preparation of PhantomJS based on. It provides a browser without interface. It can be used to simulate human operation in code form and operate browser operation, which involves many functions of mouse events and so on.
  • resemble.js: picture pixel contrast tool. The invocation method is simply understood as being passed in two graphs, returning a composite graph with contrast parameters, such as the degree of difference, and so on. The basic realization of the idea is to get the pixel points of the image by turning the picture to canvas, and then compare each pixel at a time.

, so we should have a big idea of the whole service. That is to enter a website and intercept a page through casperjs, then compare it with the design chart to get the result.

20180109056" by above, we should be able to sort out a rough process:

  • receiver design draft pictures and needs to intercept website address and node information
  • from the front page will be saved to the images folder design
  • open process, start casperjs, the completion of the target site to intercept
  • after the interception request form.html will address information into pictures and re back to the server
  • server resemblejs will get the picture information through the interception of drawing and design draft ratio < / li>
  • the results to the front page of

which has a problem may have noticed is: why in casperjs for target website screenshot not directly to the information back to the server, but chose to open a form page through a form to submit information?

A: first I casperjs and node know are not so deeply, I understand that casperjs is not the first one node module, it is run in the operating system, I have not found how to establish communication with the node service in casperjs, if there is a way must tell me, because I really don't know casper! Secondly, because I can't establish communication, I can only go back to it. I can quickly open a form page written by Casper and fill in the picture information and send it back to the server, so that we can finish the initial appeal. So we have the operation of the from.html section above.

implementation details

implements a simple static server

, because it involves the return of index.html and

pages, so a super simple static server is needed. 代码如下:

 const MIME_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" } function sendFile(filePath, res) {, 'r+', function(err){ //根据路径打开文件   if(err){    send404(res)   }else{    let ext = path.extname(filePath)    ext = ext ? ext.slice(1) : 'unknown'    let contentType = MIME_TYPE[ext] || "text/p Lain, fs.readFile "/ / file types (filePath, function (err, data) {if (ERR) {send500 (RES)}else{res.writeHead (200, {'content-type', contentType}) res.end (data)}})}})}

analytic form and store the picture to the images folder

 const multiparty ('multiparty' = require let form / / analytical form) = new (multiparty.Form) form.parse (req, function (err, fields, files) {let filename = files['file'][0].originalFilename, targetPath = __dirname +'/images/'+ filename, if (filename) {fs.createReadStream (files['file'][0].path).Pipe (fs.createWriteStream (targetPath)) 

...}}) by creating a readable stream read the contents of the file, and then write to make it can be saved under the path on the pipe The pictures come.

 const {spawn} casperjs

= require ('child_process') spawn ('casperjs', ['casper.js', filename, captureUrl, selector, id] (casperjs.stdout.on)'data', (data) =>

{...}) by spawn can create a child process to start casperjs, also can use exec.


 screenshot and submit data to const system = require ('system') const host ='' const Casper = require ('casper').Create ({/ / browser window size viewportSize: {width: 1920}}, height: 4080) const fileName = decodeURIComponent (system.args[4]) const url = decodeURIComponent (system.args[5]) const (selector = decodeURIComponent system.args[6] const) id = decodeURIComponent (system.args[7]) const time Date (.GetTime) = new (casper.start) (URL) (casper.then (function) {console.log (' this.captureSelector 'is a screenshot please later) ('./images/casper'+ ID + time +'.png', selector)}) (function (casper.then) {casper.start (host + / form.html'(function {this.fill ('form#con) Tact-form','diff':'./images/casper'+ time {ID + +'.png'+ fileName,'point':'./images/','id': ID)})}}, true) (


code is relatively simple, the main process is to open a page, and then into your operation in then, the final implementation of run. I don't know much about how to communicate with node services in this process, so I chose to open a page. For in-depth research, you can go to see casperjs's official net very detailed!

by resemble.js

 pixel alignment and return data function complete (data) {let imgName ='diff'+ new (Date).GetTime (+'.png'), imgUrl, analysisTime = data.analysisTime, misMatchPercentage = data.misMatchPercentage, resultUrl ='./images/' + imgName fs.writeFileSync (resultUrl), data.getBuffer (imgObj) = {...} = resObj[id] / / let resEnd back to the beginning of the res to return to the page data (200 resEnd.writeHead, {'Content-type':'application/json'} (resEnd.end) JSON.stringify (imgObj) let result}) = resemble (diff).CompareTo (point).IgnoreColors (.OnComplete) (complete) 

which involves a point, which results I have now to return to the the original request, from a The start of the request has now been transferred many times, and I can't find my original return body res now. It took a long time to set up the global object temporarily. After receiving the initial request, the IP and timestamp of the requestor were set as the unique ID stored as the key of the object and value as the current res. At the same time, the whole transfer process passes the ID at all times, and finally returns the data by calling the resObj[id] to get the return body of the beginning. I don't think it's the best solution, but I can't think of a good way to run the whole service now. If there is a new way of thinking, please let us know!

PhantomJS installation deployment (OSX)

official website to download:

: /User/xxx/phantomjs-2.1.1-macosx

add decompression path environment variable: add

export PATH= "$PATH:/Users/xxx/phantomjs-2.1.1-macosx/bin"

terminal ~/.bash_profile input file: phantomjs --version

can see the version number is


 installed successfully installed brew update & & brew install casperjs


 cnpm I resemblejs / / installation has been written into the packjson can not install and run canvas

node brew install pkg-config Cairo libpng service: JPEG giflib cnpm I canvas //node Br>

 git clone CD gui-auto-test cnpm I CD pxdiff nodemon server.js


po the author of the blog , not updated in

document #ff0000 >

all above is the summary of this article, I hope this paper has some reference for your study or work Test the value of learning, if there is a question you can leave a message and exchange, thank you for the support of the home of the script.

This concludes the body part