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較爲準確,可以根據個人電腦的分辨率來調整"""