Bläddra i källkod

feat: 优化获取滑动距离方法,刷新验证码处理

wuwenyi 4 månader sedan
förälder
incheckning
5ef7d1046e
1 ändrade filer med 64 tillägg och 18 borttagningar
  1. 64 18
      huitun/captcha_ident.py

+ 64 - 18
huitun/captcha_ident.py

@@ -1,6 +1,7 @@
 import random
 import re
 
+import cv2
 import requests
 
 import cv2 as cv
@@ -20,11 +21,11 @@ class CaptchaIdent:
         self.frame = self.page.frames[1]
 
     def start(self):
-        for i in range(5):
+        for i in range(10):
             self.page.wait_for_timeout(1000)
+            start_x, start_y = self.get_slide_block_img_and_start()
             self.get_slide_bg_img()
-            start_x = self.get_slide_block_img_and_start_x()
-            distance1, distance2 = self.get_slide_distance(start_x)
+            distance1, distance2 = self.get_slide_distance(start_x, start_y)
             slide_result = self.move_to_notch(distance1, distance2)
             if not slide_result:
                 self.refresh_captcha()
@@ -43,15 +44,21 @@ class CaptchaIdent:
             with open("./slide_bg.png", "wb") as f:
                 f.write(r.content)
 
+            # 调整图片大小,根据style内容将宽度调整为320,高度等比例调整
+            img = Image.open("./slide_bg.png")
+            bg_img = Image.open("./bg.png")
+            ratio = img.width / bg_img.width
+            img = img.resize(size=(bg_img.width, int(img.height / ratio)))
+            img.save("./slide_bg.png")
 
-    def get_slide_block_img_and_start_x(self):
+    def get_slide_block_img_and_start(self):
         """获取滑块图片以及初始x坐标"""
         print("正在获取滑块图片")
 
         # 首先保存整个登录背景截图
         self.page.wait_for_timeout(2000)
         slideBg = self.frame.query_selector('#slideBg')
-        slideBg.screenshot(path="slide_bg.png")
+        slideBg.screenshot(path="bg.png")
 
         # 获取滑动验证码所在的iframe
         captcha_frame = self.frame
@@ -77,35 +84,73 @@ class CaptchaIdent:
 
             # 通过滑块位置,从背景图中截取滑块图片  # cropped_image = image.crop((left, top, right, bottom))
             slide_block_rect = slide_block_ele.bounding_box()
-            bg = Image.open("slide_bg.png")
+            bg = Image.open("bg.png")
             # offset = slide_block_rect["width"] // 5  # 从背景图上截取会混入滑块周围的一些像素点,所以加一个偏移值,截取到滑块内部的图片。
-            slide_block_img = bg.crop((slide_block_x + 4, slide_block_y + 4,
-                                       slide_block_x + slide_block_rect["width"] - 4,
-                                       slide_block_y + slide_block_rect["height"] - 4))
+            offset = 5
+            slide_block_img = bg.crop((slide_block_x + offset, slide_block_y + offset,
+                                       slide_block_x + slide_block_rect["width"] - offset,
+                                       slide_block_y + slide_block_rect["height"] - offset))
             slide_block_img.save("slide_block.png")
-            return slide_block_x + 4
+            return slide_block_x + offset, slide_block_y + offset
 
-    def get_slide_distance(self, start_x):
+    def get_slide_distance(self, start_x, slide_bg_y):
         """获取滑动距离"""
         print("正在获取滑动距离")
         # 通过opencv比较图片,获取缺口位置
         slide_bg_img = cv.imread("./slide_bg.png")
-        slide_bg_img = self.set_contrast_brightness(slide_bg_img, 0.4, 0)
         slide_block_img = cv.imread("./slide_block.png")
+        block_height = slide_block_img.shape[0]
+        # 裁剪对应坐标图片,缩减搜索范围
+        slide_bg_img = slide_bg_img[int(slide_bg_y) - 5: int(slide_bg_y + block_height) + 5, :]
+        slide_bg_img = self.set_contrast_brightness(slide_bg_img, 1, 100)
+        cv.imwrite("./slide_bg_handled.png", slide_bg_img)
+
         slide_block_img = self.set_contrast_brightness(slide_block_img, 0.4, 0)
         cv.imwrite("./slide_block_handled.png", slide_block_img)
         result = cv.matchTemplate(slide_block_img, slide_bg_img, cv.TM_CCOEFF_NORMED)
         minVal, maxVal, minLoc, maxLoc = cv.minMaxLoc(result)
 
-        # 缺口的x坐标
-        notch_x1 = minLoc[0]
-        notch_x2 = maxLoc[0]
+        th, tw = slide_block_img.shape[:2]
+        tl = maxLoc  # 左上角点的坐标
+        br = (tl[0] + tw, tl[1] + th)  # 右下角点的坐标
+
+        cv2.rectangle(slide_bg_img, tl, br, (0, 0, 255), 2)  # 绘制矩形
+        cv2.rectangle(slide_bg_img, minLoc, (minLoc[0] + tw, minLoc[1] + th), (0, 255, 255), 2)  # 绘制矩形
+        cv2.imwrite("./match_result.png", slide_bg_img)  # 保存在本地
 
         # 距离
-        distance1 = notch_x1 - start_x
-        distance2 = notch_x2 - start_x
+        distance1 = minLoc[0] - start_x
+        distance2 = maxLoc[0] - start_x
         return distance1, distance2
 
+    def get_slide_distance2(self, start_x):
+        """获取滑动距离"""
+        print("正在获取滑动距离")
+        # 通过opencv比较图片,获取缺口位置
+        slide_bg_img = cv2.imread("./slide_bg.png")
+        slide_bg_img = cv2.Canny(slide_bg_img, 100, 200)
+        cv2.imwrite("./slide_bg_handle1.png", slide_bg_img)
+        slide_bg_img = cv2.cvtColor(slide_bg_img, cv2.COLOR_GRAY2RGB)
+        cv2.imwrite("./slide_bg_handle2.png", slide_bg_img)
+
+        slide_block_img = cv.imread("./slide_block.png")
+        slide_block_img = cv2.Canny(slide_block_img, 100, 200)
+
+        cv.imwrite("./slide_block_handled1.png", slide_block_img)
+        slide_block_img = cv2.cvtColor(slide_block_img, cv2.COLOR_GRAY2RGB)
+        cv2.imwrite("./slide_block_handled2.png", slide_block_img)  # 保存在本地
+        result = cv.matchTemplate(slide_block_img, slide_bg_img, cv.TM_CCOEFF_NORMED)
+        minVal, maxVal, minLoc, maxLoc = cv.minMaxLoc(result)
+
+        th, tw = slide_block_img.shape[:2]
+        tl = maxLoc  # 左上角点的坐标
+        br = (tl[0] + tw, tl[1] + th)  # 右下角点的坐标
+        cv2.rectangle(slide_bg_img, tl, br, (0, 0, 255), 2)  # 绘制矩形
+        cv2.imwrite("./match_result.png", slide_bg_img)  # 保存在本地
+
+        # 返回缺口的X坐标
+        return maxLoc[0] - start_x, minLoc[0] - start_x
+
     @staticmethod
     def set_contrast_brightness(frame, contrast_value, brightness_value):
         if not contrast_value:
@@ -177,5 +222,6 @@ class CaptchaIdent:
         """刷新验证码"""
         # 获取滑动验证码所在的iframe
         print("刷新验证码")
+        self.frame.query_selector('.tc-action-icon').click()
+        self.page.wait_for_timeout(2500)
         self.frame = self.page.frames[1]
-        self.page.wait_for_timeout(2000)