使用 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 相关文章推荐
JavaScript列表框listbox全选和反选的实现方法
Mar 18 Javascript
谈谈我对JavaScript中typeof和instanceof的深入理解
Dec 25 Javascript
JS检测移动端横竖屏的代码
May 30 Javascript
利用AngularJs实现京东首页轮播图效果
Sep 08 Javascript
JS实现仿PS的调色板效果完整实例
Dec 21 Javascript
微信小程序之picker日期和时间选择器
Feb 09 Javascript
JS实现动态添加DOM节点和事件的方法示例
Apr 28 Javascript
jQuery日期范围选择器附源码下载
May 23 jQuery
Bootstrap 模态框多次显示后台提交多次BUG的解决方法
Dec 26 Javascript
node删除、复制文件或文件夹示例代码
Aug 13 Javascript
在Vue mounted方法中使用data变量详解
Nov 05 Javascript
Vue之封装公用变量以及实现方式
Jul 31 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
暴雪前总裁遗憾:没尽早追赶Dota 取消星际争霸幽灵
2020/03/08 星际争霸
亲密接触PHP之PHP语法学习笔记1
2006/12/17 PHP
php创建基本身份认证站点的方法详解
2013/06/08 PHP
php中数字、字符与对象判断函数用法实例
2014/11/26 PHP
详解PHP中cookie和session的区别及cookie和session用法小结
2016/06/12 PHP
javascript中字符串拼接需注意的问题
2010/07/13 Javascript
jQuery中绑定事件的命名空间详解
2011/04/05 Javascript
JS无法捕获滚动条上的mouse up事件的原因猜想
2012/03/21 Javascript
理解javascript回调函数
2014/12/28 Javascript
跟我学习javascript的执行上下文
2015/11/18 Javascript
jQuery EasyUI 右键菜单--关闭标签/选项卡的简单实例
2016/10/10 Javascript
jQuery插件DataTable使用方法详解(.Net平台)
2016/12/22 Javascript
老生常谈combobox和combotree模糊查询
2017/04/17 Javascript
vue-自定义组件传值的实例讲解
2018/09/18 Javascript
JS实现盒子跟着鼠标移动及键盘方向键控制盒子移动效果示例
2019/01/29 Javascript
vue组件定义,全局、局部组件,配合模板及动态组件功能示例
2019/03/19 Javascript
微信小程序 下拉刷新及上拉加载原理解析
2019/11/06 Javascript
原生js实现俄罗斯方块
2020/10/20 Javascript
[01:38]DOTA2第二届亚洲邀请赛中国区预选赛出线战队晋级之路
2017/01/17 DOTA
[01:18:33]Secret vs VGJ.S Supermajor小组赛C组 BO3 第一场 6.3
2018/06/04 DOTA
python和shell变量互相传递的几种方法
2013/11/20 Python
python处理圆角图片、圆形图片的例子
2014/04/25 Python
django基础之数据库操作方法(详解)
2017/05/24 Python
Python利用QQ邮箱发送邮件的实现方法(分享)
2017/06/09 Python
python的mysqldb安装步骤详解
2017/08/14 Python
PyCharm设置SSH远程调试的方法
2018/07/17 Python
Python 实现的 Google 批量翻译功能
2019/08/26 Python
python爬虫 Pyppeteer使用方法解析
2019/09/28 Python
jupyter实现重新加载模块
2020/04/16 Python
python2.7使用scapy发送syn实例
2020/05/05 Python
Joules美国官网:出色的英国风格
2017/10/30 全球购物
理肤泉俄罗斯官网:La Roche-Posay俄罗斯
2018/07/24 全球购物
应届生妇产科护士求职信
2013/10/27 职场文书
春节请假条
2014/04/11 职场文书
2014年五一劳动节社区活动总结
2014/04/14 职场文书
同学聚会通知短信
2015/04/20 职场文书