casperjs、resembleに基づく.jsは画素対比サービスを実現する
7000 ワード
いちばん前に書く
今回は、設計原稿とフロントエンドページをピクセル対比するnodeサービスを提供し、テストまたはフロントエンド担当者自身のために補助的なテストを完了することを目的としています.私を信じて、ピクセルレベルの対比の下で、ホームページの設計原稿に対する復元の程度は一気に明らかになります.もしどの子供靴がこの機能である前端のお兄さんのページを測って問題を発見したら、私が提供したこのツール=.=
効果のプレビュー
先行知識
今回は、次の2つのライブラリを補助ツールとして使用しました.
だから、サービス全体にはcasperjsを通じてあるサイトに入ってあるページを切り取って、設計図と比較して結果を出すという大きな問題があるはずです.
全体的な考え方.
image
上の図では、大まかな流れを整理することができます.
この問題の1つは、casperjsでターゲットサイトをスクリーンショットしてサーバに直接情報を返すのではなく、フォームページを開いてフォームの形式で情報を提出することを選択した理由に気づくかもしれません.
答え:まず私はcasperjsとnodeについてそんなに深く理解していません.私が理解しているのは、まずcasperjsはnodeモジュールではありません.それはオペレーティングシステムの中で走っています.私はまだcasperjsの中でnodeサービスとの通信を確立する方法を発見していません.もし方法があれば、私に教えてください.私は本当にcasperをよく知らないからです.次に通信が確立できないため、私は退くしかありません.次に、casperを通じて私が書いたフォームページをすばやく開き、画像情報を記入してサーバーに返信することで、最初の訴えを完成することができます.だから上にあるんだhtmlの部分の操作.
実装の詳細
簡易静的サーバの実装
indexにかかわるからです.htmlとform.htmlページの戻りは、超簡易な静的サーバを実現する必要があります.コードは次のとおりです.
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)
}
})
}
})
}
フォームを解析し、イメージフォルダに画像を格納
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))
...
}
})
読み取り可能なストリームを作成してファイル内容を読み出し、pipeを介して所定のパスに書き込むことでアップロードされたピクチャを保存します.
casperjsの実行
const { spawn } = require('child_process')
spawn('casperjs', ['casper.js', filename, captureUrl, selector, id])
casperjs.stdout.on('data', (data) => {
...
})
spawnではサブプロセスを作成してcasperjsを起動し、execなども使用できます.
図面を切り取って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()
コードは簡単ですが、主なプロセスはページを開き、thenで操作を入力し、runを実行することです.この過程でnodeサービスとの通信方法がよく分からないので、もう一つのページを開くことを選びました.深く研究したいのはcasperjsの公式サイトを見てとても詳しいです!
resemble.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
参考文献
最後に
恒例po作者のブログ、不定期更新中--issuesでの交流を歓迎します.