使用 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入门教程(7) History历史对象
Jan 31 Javascript
Jquery利用mouseenter和mouseleave实现鼠标经过弹出层且可以点击
Feb 12 Javascript
javaScript语法总结
Nov 25 Javascript
AngularJS的脏检查深入分析
Apr 22 Javascript
Node.js 异步异常的处理与domain模块解析
May 10 Javascript
浅谈JS中的常用选择器及属性、方法的调用
Jul 28 Javascript
微信小程序收藏功能的实现代码
Jun 12 Javascript
js中int和string数据类型互相转化实例
Jan 16 Javascript
VUE v-model表单数据双向绑定完整示例
Jan 21 Javascript
vue实现条件叠加搜索的解决方法
May 28 Javascript
简述pm2常用命令集合及配置文件说明
May 30 Javascript
JavaScript控制台的更多功能
Apr 28 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和XSL stylesheets转换XML文档
2006/10/09 PHP
建立文件交换功能的脚本(一)
2006/10/09 PHP
TMDPHP 模板引擎使用教程
2012/03/13 PHP
PHP针对JSON操作实例分析
2015/01/12 PHP
php获取微信共享收货地址的方法
2017/12/21 PHP
实现laravel 插入操作日志到数据库的方法
2019/10/11 PHP
Centos7安装swoole扩展操作示例
2020/03/26 PHP
Jquery中children与find之间的区别详细解析
2013/11/29 Javascript
jQery使网页在显示器上居中显示适用于任何分辨率
2014/06/09 Javascript
DOM 事件流详解
2015/01/20 Javascript
javascript实现uploadify上传格式以及个数限制
2015/11/23 Javascript
JS获取及验证开始结束日期的方法
2016/08/20 Javascript
JQuery实现DIV其他动画效果的简单实例
2016/09/18 Javascript
Es6 写的文件import 起来解决方案详解
2016/12/13 Javascript
JS实现中国公民身份证号码有效性验证
2017/02/20 Javascript
jQuery dateRangePicker插件使用方法详解
2017/07/28 jQuery
vue-cli项目如何使用vue-resource获取本地的json数据(模拟服务端返回数据)
2017/08/04 Javascript
Vue.js 踩坑记之双向绑定
2018/05/03 Javascript
基于Vue2实现简易的省市区县三级联动组件效果
2018/11/05 Javascript
node.js学习笔记之koa框架和简单爬虫练习
2018/12/13 Javascript
全网小程序接口请求封装实例代码
2020/11/06 Javascript
利用python写个下载teahour音频的小脚本
2017/05/08 Python
浅谈Python中range和xrange的区别
2017/12/20 Python
对Python中Iterator和Iterable的区别详解
2018/10/18 Python
python 把列表转化为字符串的方法
2018/10/23 Python
Python3爬虫学习入门教程
2018/12/11 Python
对python实现合并两个排序链表的方法详解
2019/01/23 Python
python批量下载抖音视频
2019/06/17 Python
Python +Selenium解决图片验证码登录或注册问题(推荐)
2020/02/09 Python
python 使用递归回溯完美解决八皇后的问题
2020/02/26 Python
配置管理计划的主要内容有哪些
2014/06/20 面试题
学校法制宣传月活动总结
2014/07/03 职场文书
优秀教师单行材料
2014/12/16 职场文书
分家协议书范本
2016/03/22 职场文书
基于CSS制作创意端午节专属加载特效
2022/06/01 HTML / CSS
MySQL控制流函数(-if ,elseif,else,case...when)
2022/07/07 MySQL