likes
comments
collection
share

今日头条 - 滑块登陆

作者站长头像
站长
· 阅读数 36

今日头条不管怎样都绕不开滑块验证。那就开干吧。

难点

滑块登陆具体如何实现,看了很多博客,其实最重要的就两点:

  1. 背景图片和缺口之间的距离
  2. 模拟人滑动

计算间距

能够获得完整图片

有关背景图片和缺口之间的距离计算,有些网页上能够获得完整的背景图,因此可以使用的方式是:找到完整背景图和缺口背景图,两图的像素进行对比,找到边缘与缺口最左侧的距离。具体可参考 夜斗小神社

无法获得完整图片

但有些网站是没有完整图片的。这个时候就只能通过缺口背景图和缺口图进行比对,找到两图之间的距离。常用方法是cv2.matchTemplate。因此要着重看一下cv2.matchTemplate是如何实现的。

cv2.matchTemplate

cv2.matchTemplate 的原理就是将缺口从上至下,从左至右的与模板图片进行比对,看重合的图片相似度有多高【以左上角像素点为单位,获取与缺口图相同大小的图像,进行像素比较】,返回结果矩阵。 然后通过cv2.minMaxLoc获取到矩阵中最大和最小值和对应坐标。 坐标的x轴就是我们要计算得到的距离。

计算间距的具体流程

  1. 读取当前灰度图片
  2. cv2.matchTemplate获取结果矩阵
  3. cv2.minMaxLoc获取最大值坐标
  4. 等比缩放

前三步最终结果返回是300,而自己手动测量是295,差别不大但有点好奇,就拿rectangle圈了一下测试的位置,结果!!!

今日头条 - 滑块登陆 哦豁,位置找错了,看来要提高结果的精度

消除图像噪声

cv2.GaussianBlur - 通过平均像素值和相邻像素的值来平滑图像,消除噪声。

"""读取图片"""
blockJpg = cv2.imread(blockJpg, 0)
templateJpg = cv2.imread(templateJpg, 0)

def _tran_canny(image):
    """消除噪声"""
    image = cv2.GaussianBlur(image, (3, 3), 0)
    return cv2.Canny(image, 50, 150)

"""模式匹配"""
res = cv2.matchTemplate(_tran_canny(blockJpg), _tran_canny(templateJpg), cv2.TM_CCOEFF_NORMED)

"""获取最大最小值"""
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

最终能够正常圈出结果

今日头条 - 滑块登陆

然后还剩最后一步:等比缩放。因为获取到的是原图,但实际上网页中的图片进行了等比缩放,如果按照原图距离移动肯定匹配不上

今日头条 - 滑块登陆

模拟滑动

模拟滑动其实就是模仿人的常识性动作。一般而言人在滑动过程中会经历 慢-快-慢 的过程 - 加速度。所以对整个路径分为5部分

  1. 首次点击 - 停顿一秒
  2. 前1/5的距离稍微慢点的加速滑动
  3. 中间3/5的距离快速滑动
  4. 最后1/5的距离减速滑动
  5. 校准时停顿0.7s再松开

路径计算

 def get_tracks(self, distance):
        # 初始速度
        v = 0
        # 单位时间 0.2s内 统计轨迹
        m = 0.3
        # 每0.2s的轨迹列表
        tracks = []
        # 当前位置
        current = 0
        # 从减速到加速的位置
        # font = distance * 1/5
        # 从加速到减速的位置
        mid = distance*4/5
        

        while current <= distance:
            if current < font:
            # 减速
                a = -1
            if current < mid:
            # 加速
                a = 2
            else:
            # 减速
                a = -3
                
            v0 = v 
            # x = v0*t + 1/2^2
            s = v0*m+0.5*a*(m**2) 
            current += s
            tracks.append(round(s))
            v = v0+a*m
            
        return tracks

滑动

  1. 点击不松开
  2. 滑动
  3. 松开
# 获取每隔0.2秒的位置        
        tracks = self.get_tracks(gap)
        print(gap)
        # 定位按钮滑块的位置
        element = wait.until(EC.presence_of_element_located((By.XPATH,'//div[@class="secsdk-captcha-drag-icon sc-kEYyzF fiQtnm"]')))
        ActionChains(browser).click_and_hold(on_element=element).perform()
        # 先停顿1s
        time.sleep(1)
        # 每0.3s改变一下当前需要移动的距离
        for track in tracks:
        # x拖动的位置,y拖动的位置
            ActionChains(browser).move_by_offset(xoffset=track, yoffset=0).perform()
        # 等一下再松开
        time.sleep(0.5)
        ActionChains(browser).release(on_element=element).perform()

然而还是被检测出来了

转载自:https://juejin.cn/post/7030821175429169189
评论
请登录