使用 Node.js 模拟滑动拼图验证码操作的示例代码


Posted in Javascript onNovember 02, 2017

近几年,网页上各种新型验证码层出不穷,其中一种比较常见的是滑动验证码,比如下图这种。

使用 Node.js 模拟滑动拼图验证码操作的示例代码

本文介绍了一种使用纯前端方法寻找滑动终点并模拟滑动的方法。

我们需要三个依赖库: puppeteer 、 Resemble.js 以及canvas 。其中 puppeteer 用于打开并操作页面, Resemble.jscanvas 用于寻找滑动验证码的终点位置。相关依赖如下:

"dependencies": {
 "canvas": "^1.6.7",
 "puppeteer": "^0.12.0",
 "resemblejs": "^2.2.6"
}

接下来是实现要点。首先,引入所需的库,定义一些常量。

const fs = require('fs')
const puppeteer = require('puppeteer')
const resemble = require('resemblejs')
const Canvas = require('canvas')

const URL = 'xxx' // 验证码页面访问地址
const width = 600
const height = 400
const slider_width = 44

const sleep = duration => {
 return new Promise(resolve => {
 setTimeout(resolve, duration)
 })
}

接下来,使用 puppeteer 打开验证码页面:

const browser = await puppeteer.launch()
const page = await browser.newPage()
page.setViewport({width, height})

await page.goto(URL, {
 waitUntil: 'networkidle'
})

然后往页面上注入一段 JS ,获取验证码滑块的位置。这一段代码可能需要你根据自己页面的实际情况进行调整。

const offset = await page.evaluate(() => {
 let offset_ifr = $('iframe').offset()

 return {
 top: offset_ifr.top + 222,
 left: offset_ifr.left + 10
 }
})

接下来,模拟按下鼠标左键,再放开,并分别截图。

await page.mouse.move(offset.left + 10, offset.top + 10)
// 按下鼠标
await page.mouse.down({
 button: 'left'
})
// 等待图片出现
await sleep(500)
// 截图
await page.screenshot({path: 'screenshot2.png'})

await page.mouse.up({
 button: 'left'
})
// 等待图片出现
await sleep(500)
// 截图
await page.screenshot({path: 'screenshot3.png'})

此时可以得到两个图片:

使用 Node.js 模拟滑动拼图验证码操作的示例代码

以及:

使用 Node.js 模拟滑动拼图验证码操作的示例代码

可以看到,两个图其余部分都相同,区别在于是否显示验证码滑块以及目标位置。

接下来,就轮到 Resemble.js 出场了,可以使用它获得两个图片的 diff 结果。

await new Promise(resolve => {
 resemble.outputSettings({
 transparency: 0
 })
 resemble('screenshot2.png')
 .compareTo('screenshot3.png')
 .ignoreColors()
 .onComplete(data => {
  fs.writeFileSync('diff.png', data.getBuffer())
  resolve()
 })
})

结果如下:

使用 Node.js 模拟滑动拼图验证码操作的示例代码

接下来,再使用 canvas 库,将这个 diff 图片读入内存,从右上角开始查找,很容易即可找到最右侧色块的位置,也即滑块终点的位置。

const getDestinationX = min_x => {
 const canvas = new Canvas(width, height)
 const ctx = canvas.getContext('2d')
 const buf = fs.readFileSync('diff.png')
 const img = new Canvas.Image()
 img.src = buf
 ctx.drawImage(img, 0, 0, width, height)
 const img_data = ctx.getImageData(0, 0, width, height).data

 let destination_x = -1

 for (let y = 0; y < height; y++) {
 for (let x = width; x >= min_x; x--) {
  let p = width * y + x
  p = p << 2
  if (img_data[p + 3] === 255 && img_data[p - 10 * 4 + 3] === 255) {
  destination_x = x
  break
  }
 }
 if (destination_x > -1) break
 }

 return destination_x - slider_width
}

这样,便获得了滑块的起始位置以及终点位置,再使用 puppeteerpage.mouse.move 方法模拟拖动,将滑块拖到终点位置即可。

使用 Node.js 模拟滑动拼图验证码操作的示例代码

当然,找到滑块终点并把滑块拖到正确的终点位置只是第一步,完善的滑动验证码并不会只判断有没有滑到正确的位置,还会分析你的拖动轨迹。要知道,人滑动的轨迹和机器滑动的轨迹是有很大不同的,至于具体如何区分就是另一个复杂的话题了。

最后,本文仅供研究参考,不要问我要详细代码。以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery 数据缓存data(name, value)详解及实现
Jan 04 Javascript
javascript preload&amp;lazy load
May 13 Javascript
html+css+js实现xp window界面及有关功能
Mar 26 Javascript
JScript中的条件注释详解
Apr 24 Javascript
微信小程序 教程之wxapp视图容器 scroll-view
Oct 19 Javascript
JS中如何实现Laravel的route函数详解
Feb 12 Javascript
基于JavaScript实现图片连播和联级菜单实例代码
Jul 28 Javascript
webpack开发跨域问题解决办法
Aug 03 Javascript
微信小程序实现换肤功能
Mar 14 Javascript
微信小程序实现订单倒计时
Nov 01 Javascript
Vue通过getAction的finally来最大程度避免影响主数据呈现问题
Apr 24 Javascript
js实现简单选项卡制作
Aug 05 Javascript
基于JavaScript+HTML5 实现打地鼠小游戏逻辑流程图文详解(附完整代码)
Nov 02 #Javascript
vue-resource + json-server模拟数据的方法
Nov 02 #Javascript
详解vue-cli项目中用json-sever搭建mock服务器
Nov 02 #Javascript
Vue-cli 使用json server在本地模拟请求数据的示例代码
Nov 02 #Javascript
vue项目中使用axios上传图片等文件操作
Nov 02 #Javascript
JavaScript登录验证基础教程
Nov 01 #Javascript
vue打包后显示空白正确处理方法
Nov 01 #Javascript
You might like
php中过滤非法字符的具体实现
2013/10/29 PHP
centos下file_put_contents()无法写入文件的原因及解决方法
2017/04/01 PHP
PHP实现的简单在线计算器功能示例
2017/08/02 PHP
PHP实现的一致性Hash算法详解【分布式算法】
2018/03/31 PHP
phpinfo无法显示的原因及解决办法
2019/02/15 PHP
Laravel 中创建 Zip 压缩文件并提供下载的实现方法
2019/04/02 PHP
Javascript 键盘keyCode键码值表
2009/12/24 Javascript
JQuery 获取和设置Select选项的代码
2010/02/07 Javascript
IE6不能修改NAME问题的解决方法
2010/09/03 Javascript
关于jquery的多个选择器的使用示例
2013/10/18 Javascript
fixedBox固定div漂浮代码支持ie6以上大部分主流浏览器
2014/06/26 Javascript
javascript中的this详解
2014/12/08 Javascript
JS实现网页标题栏显示当前时间和日期的完整代码
2015/11/02 Javascript
jQuery+css实现的时钟效果(兼容各浏览器)
2016/01/27 Javascript
JS动态给对象添加事件的简单方法
2016/07/19 Javascript
基于原生JS实现图片裁剪
2016/08/01 Javascript
JS简单设置下拉选择框默认值的方法
2016/08/20 Javascript
浅谈javascript控制HTML5的全屏操控,浏览器兼容的问题
2016/10/10 Javascript
jQuery实现jQuery-form.js实现异步上传文件
2017/04/28 jQuery
详解Vue 方法与事件处理器
2017/06/20 Javascript
JS+Canvas绘制动态时钟效果
2017/11/10 Javascript
js判断输入框不能为空格或null值的实现方法
2018/03/02 Javascript
javascript获取元素的计算样式
2019/05/24 Javascript
Python SqlAlchemy动态添加数据表字段实例解析
2018/02/07 Python
Django中的CBV和FBV示例介绍
2018/02/25 Python
python如何修改装饰器中参数
2018/03/20 Python
详解python和matlab的优势与区别
2019/06/28 Python
Python HTMLTestRunner如何下载生成报告
2020/09/04 Python
网易微博Web App用HTML5开发的过程介绍
2012/06/13 HTML / CSS
加拿大知名的国际儿童品牌:Hatley
2016/11/09 全球购物
乌克兰网上服装店:Bolf.ua
2018/10/30 全球购物
自考自我鉴定范文
2013/10/30 职场文书
行政管理毕业生自荐信
2014/02/24 职场文书
少先队学雷锋活动总结范文
2014/03/09 职场文书
关于调整工作时间的通知
2015/04/24 职场文书
幼儿园新学期开学寄语
2015/05/27 职场文书