使用 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 相关文章推荐
ExtJS 2.0实用简明教程之应用ExtJS
Apr 29 Javascript
jquery右下角弹出提示框示例代码
Oct 08 Javascript
关于js内存泄露的一个好例子
Dec 09 Javascript
jquery 判断滚动条到达了底部和顶端的方法
Apr 02 Javascript
jquery动画效果学习笔记(8种效果)
Nov 13 Javascript
微信小程序中顶部导航栏的实现代码
Mar 30 Javascript
关于JavaScript语句后面的分号问题
Dec 07 Javascript
详解Angular5/Angular6项目如何添加热更新(HMR)功能
Oct 10 Javascript
微信小程序实现签到功能
Oct 31 Javascript
微信小程序实现列表页的点赞和取消点赞功能
Nov 02 Javascript
详解Vue组件之作用域插槽
Nov 22 Javascript
浅谈TypeScript 索引签名的理解
Oct 16 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(2)
2006/10/09 PHP
THINKPHP+JS实现缩放图片式截图的实现
2010/03/07 PHP
基于python发送邮件的乱码问题的解决办法
2013/04/25 PHP
PHP实现的比较完善的购物车类
2014/12/02 PHP
PHP弹出对话框技巧详细解读
2015/09/26 PHP
PHP分页显示的方法分析【附PHP通用分页类】
2018/05/10 PHP
php curl获取https页面内容,不直接输出返回结果的设置方法
2019/01/15 PHP
面向对象的Javascript之二(接口实现介绍)
2012/01/27 Javascript
img onload事件绑定各浏览器均可执行
2012/12/19 Javascript
jquery easyui中treegrid用法的简单实例
2014/02/18 Javascript
js propertychange和oninput事件
2014/09/28 Javascript
Node.js和MongoDB实现简单日志分析系统
2015/04/25 Javascript
Bootstrap创建可折叠的组件
2016/02/23 Javascript
一款简单的jQuery图片标注效果附源码下载
2016/03/22 Javascript
js选择器全面解析
2016/06/27 Javascript
浅谈js中startsWith 函数不能在任何浏览器兼容的问题
2017/03/01 Javascript
Ajax验证用户名或昵称是否已被注册
2017/04/05 Javascript
如何写好一个vue组件,老夫的一年经验全在这了(推荐)
2019/05/18 Javascript
vue+springboot图片上传和显示的示例代码
2020/02/14 Javascript
[17:00]DOTA2 HEROS教学视频教你分分钟做大人-帕克
2014/06/10 DOTA
python写入xml文件的方法
2015/05/08 Python
python使用reportlab实现图片转换成pdf的方法
2015/05/22 Python
Python实现的knn算法示例
2018/06/14 Python
Python中dict和set的用法讲解
2019/03/28 Python
Python时间序列缺失值的处理方法(日期缺失填充)
2019/08/11 Python
python语言线程标准库threading.local解读总结
2019/11/10 Python
对Python中 \r, \n, \r\n的彻底理解
2020/03/06 Python
使用pyecharts1.7进行简单的可视化大全
2020/05/17 Python
keras和tensorflow使用fit_generator 批次训练操作
2020/07/03 Python
Ubuntu权限不足无法创建文件夹解决方案
2020/11/14 Python
html5的input的required使用中遇到的问题及解决方法
2018/04/24 HTML / CSS
调研座谈会发言材料
2014/08/23 职场文书
开会通知
2015/04/20 职场文书
地道战观后感300字
2015/06/04 职场文书
《平移和旋转》教学反思
2016/02/19 职场文书
撤回我也能看到!教你用Python制作微信防撤回脚本
2021/06/11 Python