使用 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 设计模式 富有表现力的Javascript(一)
May 26 Javascript
Jquery 插件开发笔记整理
Jan 17 Javascript
JavaScript高级程序设计 阅读笔记(四) ECMAScript中的类型转换
Feb 27 Javascript
javascript等号运算符使用详解
Apr 16 Javascript
JS组件Bootstrap ContextMenu右键菜单使用方法
Apr 17 Javascript
Bootstrap在线电子商务网站实战项目5
Oct 14 Javascript
详解vue模拟加载更多功能(数据追加)
Jun 23 Javascript
详解webpack 多页面/入口支持&amp;公共组件单独打包
Jun 29 Javascript
JS随机排序数组实现方法分析
Oct 11 Javascript
微信小程序scroll-view组件实现滚动动画
Jan 31 Javascript
深入剖析Node.js cluster模块
May 23 Javascript
Angular6笔记之封装http的示例代码
Jul 27 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程序效率优化的一些策略小结
2010/07/17 PHP
PHP中fwrite与file_put_contents性能测试代码
2013/08/02 PHP
php实现的Cookies操作类实例
2014/09/24 PHP
laravel容器延迟加载以及auth扩展详解
2015/03/02 PHP
php实现删除空目录的方法
2015/03/16 PHP
通过修改配置真正解决php文件上传大小限制问题(nginx+php)
2015/09/23 PHP
PHP验证码生成原理和实现
2016/01/24 PHP
简单解析PHP程序的运行流程
2016/06/23 PHP
javascript 框架小结 个人工作经验
2009/06/13 Javascript
仅用[]()+!等符号就足以实现几乎任意Javascript代码
2010/03/01 Javascript
jquery mobile页面跳转后样式丢失js失效的解决方法
2014/09/06 Javascript
JavaSacript中charCodeAt()方法的使用详解
2015/06/05 Javascript
jquery的幻灯片图片切换效果代码分享
2015/09/07 Javascript
JavaScript Math 对象常用方法总结
2016/04/28 Javascript
BootStrap 智能表单实战系列(二)BootStrap支持的类型简介
2016/06/13 Javascript
详解Vue中数组和对象更改后视图不刷新的问题
2018/09/21 Javascript
详解Python中time()方法的使用的教程
2015/05/22 Python
深入解析Python中的list列表及其切片和迭代操作
2016/03/13 Python
深入浅析python with语句简介
2018/04/11 Python
django 发送手机验证码的示例代码
2018/04/25 Python
Python读取YAML文件过程详解
2019/12/30 Python
Python中logging日志记录到文件及自动分割的操作代码
2020/08/05 Python
Python使用pycharm导入pymysql教程
2020/09/16 Python
Django如何使用asyncio协程和ThreadPoolExecutor多线程
2020/10/12 Python
移动端html5判断是否滚动到底部并且下拉加载
2019/11/19 HTML / CSS
英国领先的办公用品供应商:Viking
2016/08/01 全球购物
澳大利亚在线购买葡萄酒:The Wine Collective
2020/02/20 全球购物
模具设计与制造专业推荐信
2014/02/16 职场文书
酒店仓管员岗位职责
2014/04/28 职场文书
村道德模范事迹材料
2014/08/28 职场文书
党员教师四风问题对照检查材料
2014/09/26 职场文书
2014年后勤工作总结
2014/11/18 职场文书
离退休人员聘用协议书
2014/11/24 职场文书
民间借贷借条范本
2015/05/25 职场文书
创业计划书之熟食店
2019/10/16 职场文书
jquery插件实现搜索历史
2021/04/24 jQuery