使用 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 类网页微信二维码图块滚动效果具体实现
Oct 14 Javascript
JavaScript实现网页加载进度条代码超简单
Sep 21 Javascript
js实现分割上传大文件
Mar 09 Javascript
JS事件添加和移出的兼容写法示例
Jun 20 Javascript
基于bootstrap的文件上传控件bootstrap fileinput
Dec 23 Javascript
微信小程序 switch组件详解及简单实例
Jan 10 Javascript
微信小程序 引入es6 promise
Apr 12 Javascript
angular4 共享服务在多个组件中数据通信的示例
Mar 30 Javascript
vue addRoutes实现动态权限路由菜单的示例
May 15 Javascript
微信小程序动态生成二维码的实现代码
Jul 25 Javascript
回顾Javascript React基础
Jun 15 Javascript
node删除、复制文件或文件夹示例代码
Aug 13 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的ajax框架xajax入门与试用介绍
2010/12/19 PHP
PHP魔术引号所带来的安全问题分析
2014/07/15 PHP
Laravel Intervention/image图片处理扩展包的安装、使用与可能遇到的坑详解
2017/11/14 PHP
js各种验证文本框输入格式(正则表达式)
2010/10/22 Javascript
Js与下拉列表处理问题解决
2014/02/13 Javascript
JavaScript中如何通过arguments对象实现对象的重载
2014/05/12 Javascript
网页收藏夹显示ICO图标(代码少)
2015/08/04 Javascript
一道常被人轻视的web前端常见面试题(JS)
2016/02/15 Javascript
原生JS和jQuery操作DOM对比总结
2017/01/19 Javascript
vuex学习之Actions的用法详解
2017/08/29 Javascript
VueJS事件处理器v-on的使用方法
2017/09/27 Javascript
使用DataTable插件实现异步加载数据
2017/11/19 Javascript
Vue项目安装插件并保存
2019/01/28 Javascript
微信小程序实现定位及到指定位置导航的示例代码
2019/08/20 Javascript
vue相关配置文件详解及多环境配置详细步骤
2020/05/19 Javascript
[03:42]2018完美盛典-《加冕》
2018/12/16 DOTA
Python监控主机是否存活并以邮件报警
2015/09/22 Python
Windows下安装python MySQLdb遇到的问题及解决方法
2017/03/16 Python
python定时复制远程文件夹中所有文件
2019/04/30 Python
Python 图像处理: 生成二维高斯分布蒙版的实例
2019/07/04 Python
python线程安全及多进程多线程实现方法详解
2019/09/27 Python
tensorboard实现同时显示训练曲线和测试曲线
2020/01/21 Python
Python Dataframe常见索引方式详解
2020/05/27 Python
Html5无刷新修改browser Url的方法
2014/01/15 HTML / CSS
美国老牌主机服务商:iPage
2016/07/22 全球购物
YOINS官网:时尚女装网上购物
2017/03/17 全球购物
Sephora丝芙兰泰国官方网站:国际知名化妆品购物
2017/11/15 全球购物
美国在线自行车商店:Jenson USA
2018/05/22 全球购物
关于幼儿的自我评价
2013/12/18 职场文书
技术负责人岗位职责
2015/02/10 职场文书
小学中队委竞选稿
2015/11/20 职场文书
人事行政部各岗位职责说明书!
2019/07/15 职场文书
读《瓦尔登湖》有感:每个人都需要一个瓦尔登湖
2019/10/17 职场文书
关于JavaScript回调函数的深入理解
2021/06/27 Javascript
Redis 彻底禁用RDB持久化操作
2021/07/09 Redis
Java使用jmeter进行压力测试
2021/07/09 Java/Android