Maison  >  Article  >  interface Web  >  Implémenter un service de comparaison de pixels basé sur casperjs et similar.js

Implémenter un service de comparaison de pixels basé sur casperjs et similar.js

不言
不言original
2018-06-29 15:45:272724parcourir

Cet article vous présente principalement les informations pertinentes sur la mise en œuvre d'un service de comparaison de pixels basé sur casperjs et similar.js. L'article le présente en détail à travers un exemple de code. Il a une certaine valeur d'apprentissage de référence pour l'étude ou le travail de chacun. a besoin d'amis, venez étudier ensemble.

Avant-propos

Cette fois, je partage un service de nœud qui fournit une comparaison de pixels entre les brouillons de conception et les pages frontales, dans le but de fournir des tests ou Le personnel frontal effectue lui-même un test auxiliaire. Croyez-moi, lors de la comparaison au niveau des pixels, le degré de restauration du projet de conception sur la page Web deviendra immédiatement apparent. Pas grand chose à dire ci-dessous, jetons un œil à l’introduction détaillée.

Aperçu de l'effet


Connaissances préalables

Les deux bibliothèques suivantes sont utilisées cette fois comme outils auxiliaires :

  • casperjs : écrit sur la base de PhantomJS. Il fournit un navigateur sans interface en interne. En termes simples, vous pouvez l'utiliser pour compléter l'opération de simulation d'un humain pour faire fonctionner le navigateur sous forme de code, ce qui implique divers événements de souris et de nombreuses autres fonctions. Cette fois, il est principalement utilisé. est livré avec une fonction de capture d'écran.

  • resemble.js : outil de comparaison de pixels d'image. La simple compréhension de la méthode appelante est que deux images sont transmises et qu'une image composite est renvoyée avec des paramètres de comparaison tels que la différence, etc. L'idée de base de la mise en œuvre peut être comprise comme la conversion de l'image en toile, l'obtention de ses pixels d'image, puis la comparaison de chaque pixel.

Nous devrions donc déjà avoir une grande idée pour l'ensemble du service, qui consiste à utiliser casperjs pour accéder à un site Web afin d'intercepter une page, puis à la comparer avec le dessin de conception pour obtenir le résultat.

Idée générale

À partir de l'image ci-dessus, nous devrions être en mesure de trier un processus approximatif :

  • Recevoir le brouillon de l'image de conception ainsi que l'adresse du site Web et les informations sur le nœud qui doivent être interceptées depuis le page frontale

  • Enregistrez le brouillon de conception dans le dossier images

  • Ouvrez le sous-processus, démarrez casperjs et terminez l'interception de le site Web cible

  • Après l'interception, demandez au form.html de remplir les informations d'adresse de l'image et de les retransmettre au serveur

  • Le serveur obtient les informations sur l'image et compare l'image interceptée avec le brouillon de conception via similarjs

  • Les résultats sont renvoyés à la page frontale

L'un des problèmes que certaines personnes peuvent remarquer est le suivant : pourquoi les informations ne peuvent-elles pas être directement récupérées lors de la prise d'une capture d'écran du site Web cible dans casperjs ? via le formulaire ?

R : Tout d'abord, je ne connais pas grand-chose à Casperjs et à Node. Ce que je comprends, c'est que tout d'abord, Casperjs n'est pas un module de noeud, il s'exécute dans le système d'exploitation que je n'ai pas encore. J'ai découvert comment créer un lien avec Casperjs dans Casperjs. S'il existe un moyen de communiquer avec le service de nœud, dites-le-moi, car je ne connais vraiment pas grand-chose à Casper ! Deuxièmement, comme la communication ne peut pas être établie, je ne peux que recourir à la meilleure solution, ouvrir rapidement une page de formulaire que j'ai écrite via Casper, remplir les informations de l'image et la renvoyer au serveur. Cela peut compléter la demande initiale. Il y a donc l’opération ci-dessus from.html.

Détails d'implémentation

Implémentation d'un serveur statique simple

Parce que cela implique index.html et Pour renvoyer la page form.html, un serveur statique super simple doit être implémenté. Le code est le suivant :

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) {
 fs.open(filePath, '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/plain" //匹配文件类型
   fs.readFile(filePath,function(err,data){
    if(err){
     send500(res)
    }else{
     res.writeHead(200,{'content-type':contentType})
     res.end(data)
    }
   })
  }
 })
}

Analyser le formulaire et stocker les images dans le dossier images

const multiparty = require('multiparty') //解析表单
let 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))
   ...
  } 
 })

Lisez le contenu du fichier en créant un flux lisible, puis écrivez-le dans le chemin spécifié via un tube pour enregistrer l'image téléchargée.

Exécuter casperjs

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

Vous pouvez créer un processus enfant pour démarrer casperjs via spawn, et aussi Vous pouvez utiliser exec etc.

Prenez une capture d'écran et soumettez les données à form.html

const system = require('system')
const host = 'http://10.2.45.110:3033'
const casper = require('casper').create({
 // 浏览器窗口大小
 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 = new Date().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()

Le code est relativement simple. Le processus principal consiste à ouvrir une page, puis à y transmettre votre opération et enfin à exécuter run. Au cours de ce processus, je ne savais pas trop comment communiquer avec le service de nœud, j'ai donc choisi d'ouvrir une autre page. . Si vous souhaitez étudier en profondeur, vous pouvez consulter le site officiel de casperjs qui est très détaillé !

Effectuez une comparaison de pixels et renvoyez des données via similar.js

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 = {
   ...
  }
  let resEnd = resObj[id] // 找回最开始的res返回给页面数据
  resEnd.writeHead(200, {'Content-type':'application/json'})
  resEnd.end(JSON.stringify(imgObj))
 }
let result = resemble(diff).compareTo(point).ignoreColors().onComplete(complete)

这其中涉及到了一个点,即我现在所得到的结果要返回给最初的请求里,而从一开始的请求到现在我已经中转了多次,导致我现在找不到我最初的返回体res了。想了很久只能暂时采用了设定全局对象,在接收最初的请求后将请求者的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 文件中添加

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

terminal输入:phantomjs --version

能看到版本号即安装成功

安装casperjs

brew update && brew install casperjs

安装resemble.js

cnpm i resemblejs //已写进packjson可不用安装
brew install pkg-config cairo libpng jpeg giflib
cnpm i canvas //node内运行canvas

node服务

git clone https://github.com/Aaaaaaaty/gui-auto-test.git
cd gui-auto-test
cnpm i
cd pxdiff
nodemon server.js

打开http://localhost:3033/index.html

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

关于原生js实现类似fullpage的单页/全屏滚动的方法

如何利用JS实现仿微信支付弹窗功能

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn