使用 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的类型转换(字符转数字 数字转字符)
Aug 30 Javascript
关于jquery ajax 调用带参数的webservice返回XML数据一个小细节
Jul 31 Javascript
你必须知道的Javascript知识点之&quot;字面量和对应类型&quot;说明介绍
Apr 23 Javascript
用于deeplink的js方法(判断手机是否安装app)
Apr 02 Javascript
[原创]推荐10款最热门jQuery UI框架
Aug 19 Javascript
JavaScript中的toLocaleLowerCase()方法使用详解
Jun 06 Javascript
jQuery通过ajax快速批量提交表单数据
Oct 25 Javascript
js实现省份下拉菜单效果
Feb 15 Javascript
微信小程序实现点赞、取消点赞功能
Nov 02 Javascript
微信小程序获取用户openid的实现
Dec 24 Javascript
vue.js购物车添加商品组件的方法
Sep 17 Javascript
layui复选框限制选择个数的方法
Sep 18 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 版本]
2007/03/20 PHP
PHP实现MySQL更新记录的代码
2008/06/07 PHP
PHP实现文件上传下载实例
2016/10/18 PHP
php实现分页功能的详细实例方法
2019/09/29 PHP
GreyBox技术总结(转)
2010/11/23 Javascript
jQuery判断checkbox是否选中的小例子
2013/12/02 Javascript
JS往数组中添加项性能分析
2015/02/25 Javascript
JavaScript对象数组排序函数及六个用法
2015/12/23 Javascript
DOM操作原生js 的bug,使用jQuery 可以消除的解决方法
2016/09/04 Javascript
Vue.js每天必学之数据双向绑定
2016/09/05 Javascript
jquery Banner轮播选项卡
2016/12/26 Javascript
vue.js事件处理器是什么
2017/03/20 Javascript
mpvue+vuex搭建小程序详细教程(完整步骤)
2018/09/30 Javascript
使用React手写一个对话框或模态框的方法示例
2019/04/25 Javascript
微信小程序实现弹框效果
2020/05/26 Javascript
javascript解析json格式的数据方法详解
2020/08/07 Javascript
NodeJS模块Buffer原理及使用方法解析
2020/11/11 NodeJs
[06:40]2014DOTA2西雅图国际邀请赛 DK战队巡礼
2014/07/07 DOTA
Python urllib、urllib2、httplib抓取网页代码实例
2015/05/09 Python
Python3非对称加密算法RSA实例详解
2018/12/06 Python
python 图片二值化处理(处理后为纯黑白的图片)
2019/11/01 Python
python进程间通信Queue工作过程详解
2019/11/01 Python
基于keras 模型、结构、权重保存的实现
2020/01/24 Python
用Python做一个久坐提醒小助手的示例代码
2020/02/10 Python
PyTorch中torch.tensor与torch.Tensor的区别详解
2020/05/18 Python
属性与 @property 方法让你的python更高效
2020/09/21 Python
html5弹跳球示例代码
2013/07/23 HTML / CSS
西班牙最大的在线滑板和街头服饰商店:Fillow.net
2019/04/15 全球购物
经典演讲稿汇总
2014/05/19 职场文书
超市创业计划书
2014/09/15 职场文书
2015年英语教研组工作总结
2015/05/23 职场文书
职工食堂管理制度
2015/08/06 职场文书
2019事业单位个人工作总结范文
2019/08/26 职场文书
Golang流模式之grpc的四种数据流
2022/04/13 Golang
使用Python通过企业微信应用给企业成员发消息
2022/04/18 Python