滑块验证 - 亲测 (京东)

   在日常的 Web,或者 App 登录,有各式各样的验证机制,其中滑块验证,是最常见之一。 滑块验证主要分为两类,非拼图式的滑块和拼图式(缺口拼接)滑块。 在拼图式滑块中,主要有两 left 显式 和 Canvas绘制的背景图 (left 隐式)


   非拼图式的滑块主要是比较简单的一个滑轨移动,通常向右移动到末端。只要通过获取滑轨和滑块的长度,就可以计算出滑动的距离 = 滑轨长度 - 滑块长度


   拼图式(缺口拼接)滑块的 left 显式, 在移动前,通过下图1 得知滑块 left 为: 10, 缺口为:97.8, 滑轨为 0 ; 移动到缺口位置重合时,滑块left 为: 97, 缺口为:97.8, 滑轨为 87. 下图2

   滑距 = 滑块 left (移动重合时) - 滑块 left (移动前) = 滑轨

   因此,我们可以通过通过调用 Selector 获取 CSS 样式,然后用正则表达式结合 lambda 函数去 提取 left的值,就可以计算出缺口的位置。



mbk_style = sel.css('#missblock::attr("style")').get()
tbk_style = sel.css('#targetblock::attr("style")').get()
extract = lambda x: ''.join(re.findall('left: (\d+|\d+.\d+)px', x))
mbk_left = extract(mbk_style)
tbk_left = extract(tbk_style)
distance = float(tbk_left) - float(mbk_left)


   Canvas绘制的背景图 (left 隐式), 由于没有 left 的变化规律可视,以京东滑块验证为例,大概的思路如下 :

一、通过 request.urlretrieve()方法,分别获取小滑块和带缺口的背景图


二、通过 cv2.imread()方法 把获取的两个彩色图,进行二值灰度化, 下图3
三、通过 cv2.matchTemplate() 方法,计算大约的移动距离(经过测试多次,发现这个距离比实际还是有点位移偏移,但并不大) 可以稍微向左微调一下距离就可以了。

四、通过 ActionChains,移动滑块


   在测试过程中却发现,即使滑块和缺口 完全重合,但也不能成功地通过验证。这估计是机器学习的检测机制原因,因为 ActionChians 不能实现鼠标真正的移动,因此试改为 调用 pyautogui。


   虽然调用了pyautogui后,可用完全提供模拟鼠标的信号给 Web, 但首次测试后却发现同样的结果,不能通过验证。要解决这个问题,可用尝试在移动过程中,把 y 轴的值 由固定的 0 改为 由 random.randint()方法获取随机的数,参数的范围值,要看实际滑轨块的宽度,例如宽度为6,建议在 1 - 2.5之间。当然也可以在1内随机微调,用 random.random()方法获取随机值,目的就是为了尽量去模拟人的真实移动轨迹。

   通过调整 y 轴的变化,最终成功绕过机器学习的检测机制,通过验证。在测试中,我也试过如果不屏蔽 webdriver的属性,也可以的,也就证明这机制对 webdriver 的检测不存在。具体演示,可用看我微博的演示视频, 其中 user id / password 乱填的,只是演示验证这部分。

链接: https://weibo.com/u/2203755810


图1
滑块验证 - 亲测 (京东)_第1张图片

图2
滑块验证 - 亲测 (京东)_第2张图片


图3
在这里插入图片描述

你可能感兴趣的:(python,selenium)