前言
不知不觉距离上次研究已经快三年利用puppeteer破解极验的滑动验证,最近用puppeteer在做一些爬虫的工作,遇到了需要滑动验证的校验,于是毫不犹豫想起以前破解的经验,通过对比,emmm...跟之前的有些差别,下面我们来分析一下。
分析
这个滑动验证只存在两张图(如下图)
1. 背景图(包含缺口)
2. 滑块图
对比极验的滑动验证,缺少完整背景图(不含缺口),这样我们就无法去通过对比背景图来获取滑动的距离了。
认真观察一下背景图,我们能不能从中获取到什么有用的信息来计算滑动距离呢?
于是,我发现背景图缺口周围的白边。分析一下
1.白边没有透明度。(这个很重要,确保不会受到背景图的颜色影响)
2.每次都是白边,颜色不会变,白边颜色值几乎相同。
3.通过白边计算滑动距离。
实现
- 这里只说明一下核心代码,完整代码就不放出了,毕竟最重要的只是计算滑动距离,有兴趣可以自己尝试。
原理:横坐标相同的情况下,记录纵坐标颜色值出现与白边颜色相同的次数,次数出现最多的横坐标就是滑动距离
// 计算滑动距离
calculateDistance = async (page) => {
const distance = await page.evaluate(() => {
// 1.背景图转canvas
const bgImg = document.getElementsByClassName('validate-main')[0].getElementsByTagName('img')[0]
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
context.drawImage(bgImg, 0, 0, bgImg.naturalWidth, bgImg.naturalHeight)
// 2.保存横坐标和重复颜色出现次数
// 这个横坐标就是相当于滑动距离,通过比较次数就可以获取正确的滑动距离
const xAxis = {}
// 3.允许存在误差比较
// 因为我使用拾色器获取颜色值的,可以会存在小小误差,所以我们允许存在误差,这个不影响正确判断
allowDeviation = (num1, num2) => {
const offset = 25
return -offset <= num1 - num2 && num1 - num2 <= offset
}
// 对比rgb数值
for (let i = 1; i < bgImg.naturalWidth; i++) {
let times = 0
// 因为缺口只会出现在中间位置,所以不用对比整个纵坐标,只需要对比中间位置即可
// 这里我们从上面45像素开始到下面55像素结束
for (let j = 45; j < bgImg.naturalHeight - 55; j++) {
const imgData = context.getImageData(1 * i, 1 * j, 1, 1).data
const r = imgData[0]
const g = imgData[1]
const b = imgData[2]
// 因为白色是255,可能存在误差,所以这里我们取稍低一点
// 基于230允许+-25误差来比较
if (allowDeviation(r, 230) && allowDeviation(g, 230) && allowDeviation(b, 230)) {
// 记录符合条件出现的次数
times++
xAxis[i] = times
}
}
// 去掉重复像素出现小于20的
if (xAxis[i] < 20) {
delete xAxis[i]
}
}
// 经过测试通过上面过滤后就只剩下一个了,所以我直接取了
// 这里其实不严谨的,你可以通过对比出现最多次数来获取
return Object.keys(xAxis)[0]
})
return distance
}
最后
其实市面上验证方式层出不穷,诸如点击出现文字、找到人物相同的图片等等,对于这些puppeteer基本束手无策(有知道怎么破解的可以分享下哈)。这篇文章更多出于学习分享,大家遇到什么验证问题可以来互相讨论学习一下或评论区留言。