无原图滑动验证码2
import xlwings as xw import pandas as pd import datetime import re import base64 import cv2 import pathlib import zipfile import shutil def down_pic(data,data_type,path_dic): data = data.split(',')[1] image_data = base64.b64decode(data) file_path=rf"{path_dic['验证码存放路径']}\{data_type}.png" with open(file_path, 'wb') as f: f.write(image_data) class SlideCrack(object): def __init__(self, gap, bg): """ init code :param gap: 缺口图片 :param bg: 背景图片 """ self.gap = gap self.bg = bg @staticmethod def clear_white(img): # 清除图片的空白区域,这里主要清除滑块的空白 img = cv2.imread(img) rows, cols, channel = img.shape min_x = 255 min_y = 255 max_x = 0 max_y = 0 for x in range(1, rows): for y in range(1, cols): t = set(img[x, y]) if len(t) >= 2: if x <= min_x: min_x = x elif x >= max_x: max_x = x if y <= min_y: min_y = y elif y >= max_y: max_y = y img1 = img[min_x:max_x, min_y: max_y] return img1 def template_match(self, tpl, target): th, tw = tpl.shape[:2] result = cv2.matchTemplate(target, tpl, cv2.TM_CCOEFF_NORMED) # 寻找矩阵(一维数组当作向量,用Mat定义) 中最小值和最大值的位置 min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) tl = max_loc br = (tl[0] + tw, tl[1] + th) # 绘制矩形边框,将匹配区域标注出来 # target:目标图像 # tl:矩形定点 # br:矩形的宽高 # (0,0,255):矩形边框颜色 # 1:矩形边框大小 cv2.rectangle(target, tl, br, (0, 0, 255), 2) # 暂不输出 # cv2.imwrite(self.out, target) return tl[0] @staticmethod def image_edge_detection(img): edges = cv2.Canny(img, 100, 200) return edges def discern(self): img1 = self.clear_white(self.gap) img1 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY) slide = self.image_edge_detection(img1) back = cv2.imread(self.bg, 0) back = self.image_edge_detection(back) slide_pic = cv2.cvtColor(slide, cv2.COLOR_GRAY2RGB) back_pic = cv2.cvtColor(back, cv2.COLOR_GRAY2RGB) x = self.template_match(slide_pic, back_pic) # 输出横坐标, 即 滑块在图片上的位置 return x # 获取滑动距离 def get_px(path_dic): # 滑块图片 image1 = rf"{path_dic['验证码存放路径']}\small.png" # 背景图片 image2 = rf"{path_dic['验证码存放路径']}\big.png" sc = SlideCrack(image1, image2) a = sc.discern() return a # 获取位移距离 def get_tracks(distance): #distance为上一步得出的总距离。20是等会要回退的像素 distance+=20 #初速度为0,s是已经走的路程,t是时间 v0=2 s=0 t=0.4 #mid是进行减速的路程 mid=distance*3/5 #存放走的距离 forward_tracks=[] while s<distance: if s<mid: a=2 else: a=-3 #高中物理,匀加速路程的计算 v=v0 tance=v*t+0.5*a*(t**2) tance=round(tance) s+=tance v0=v+a*t forward_tracks.append(tance) #因为回退20像素,所以可以手动打出,只要和为20即可 back_tracks = [-1, -1, -1, -2, -2, -2, -3, -3, -2, -2, -1] # 20 return {"forward_tracks": forward_tracks, 'back_tracks': back_tracks} if __name__ == '__main__': # 只能是英文路径 path_dic={} path_dic['验证码存放路径']=r"D:\tem" # 下载滑块图片.我的案例是base64的数据,获取数据之后,直接保存就行,要是url,用requests取一下 down_pic(data, "small", path_dic) # 下载缺口图片 down_pic(data, "big", path_dic) # 获取滑动距离(总距离) distance=get_px(path_dic) # 获取每次移动的距离和回退的距离,防反爬 dic=get_tracks(distance) """根据实际测试,在distance-7px较为准确,可以根据个人电脑的分辨率来调整"""