|
@@ -1,6 +1,7 @@
|
|
import random
|
|
import random
|
|
import re
|
|
import re
|
|
|
|
|
|
|
|
+import cv2
|
|
import requests
|
|
import requests
|
|
|
|
|
|
import cv2 as cv
|
|
import cv2 as cv
|
|
@@ -20,11 +21,11 @@ class CaptchaIdent:
|
|
self.frame = self.page.frames[1]
|
|
self.frame = self.page.frames[1]
|
|
|
|
|
|
def start(self):
|
|
def start(self):
|
|
- for i in range(5):
|
|
|
|
|
|
+ for i in range(10):
|
|
self.page.wait_for_timeout(1000)
|
|
self.page.wait_for_timeout(1000)
|
|
|
|
+ start_x, start_y = self.get_slide_block_img_and_start()
|
|
self.get_slide_bg_img()
|
|
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)
|
|
slide_result = self.move_to_notch(distance1, distance2)
|
|
if not slide_result:
|
|
if not slide_result:
|
|
self.refresh_captcha()
|
|
self.refresh_captcha()
|
|
@@ -43,15 +44,21 @@ class CaptchaIdent:
|
|
with open("./slide_bg.png", "wb") as f:
|
|
with open("./slide_bg.png", "wb") as f:
|
|
f.write(r.content)
|
|
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坐标"""
|
|
"""获取滑块图片以及初始x坐标"""
|
|
print("正在获取滑块图片")
|
|
print("正在获取滑块图片")
|
|
|
|
|
|
# 首先保存整个登录背景截图
|
|
# 首先保存整个登录背景截图
|
|
self.page.wait_for_timeout(2000)
|
|
self.page.wait_for_timeout(2000)
|
|
slideBg = self.frame.query_selector('#slideBg')
|
|
slideBg = self.frame.query_selector('#slideBg')
|
|
- slideBg.screenshot(path="slide_bg.png")
|
|
|
|
|
|
+ slideBg.screenshot(path="bg.png")
|
|
|
|
|
|
# 获取滑动验证码所在的iframe
|
|
# 获取滑动验证码所在的iframe
|
|
captcha_frame = self.frame
|
|
captcha_frame = self.frame
|
|
@@ -77,35 +84,73 @@ class CaptchaIdent:
|
|
|
|
|
|
# 通过滑块位置,从背景图中截取滑块图片 # cropped_image = image.crop((left, top, right, bottom))
|
|
# 通过滑块位置,从背景图中截取滑块图片 # cropped_image = image.crop((left, top, right, bottom))
|
|
slide_block_rect = slide_block_ele.bounding_box()
|
|
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 # 从背景图上截取会混入滑块周围的一些像素点,所以加一个偏移值,截取到滑块内部的图片。
|
|
# 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")
|
|
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("正在获取滑动距离")
|
|
print("正在获取滑动距离")
|
|
# 通过opencv比较图片,获取缺口位置
|
|
# 通过opencv比较图片,获取缺口位置
|
|
slide_bg_img = cv.imread("./slide_bg.png")
|
|
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")
|
|
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)
|
|
slide_block_img = self.set_contrast_brightness(slide_block_img, 0.4, 0)
|
|
cv.imwrite("./slide_block_handled.png", slide_block_img)
|
|
cv.imwrite("./slide_block_handled.png", slide_block_img)
|
|
result = cv.matchTemplate(slide_block_img, slide_bg_img, cv.TM_CCOEFF_NORMED)
|
|
result = cv.matchTemplate(slide_block_img, slide_bg_img, cv.TM_CCOEFF_NORMED)
|
|
minVal, maxVal, minLoc, maxLoc = cv.minMaxLoc(result)
|
|
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
|
|
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
|
|
@staticmethod
|
|
def set_contrast_brightness(frame, contrast_value, brightness_value):
|
|
def set_contrast_brightness(frame, contrast_value, brightness_value):
|
|
if not contrast_value:
|
|
if not contrast_value:
|
|
@@ -177,5 +222,6 @@ class CaptchaIdent:
|
|
"""刷新验证码"""
|
|
"""刷新验证码"""
|
|
# 获取滑动验证码所在的iframe
|
|
# 获取滑动验证码所在的iframe
|
|
print("刷新验证码")
|
|
print("刷新验证码")
|
|
|
|
+ self.frame.query_selector('.tc-action-icon').click()
|
|
|
|
+ self.page.wait_for_timeout(2500)
|
|
self.frame = self.page.frames[1]
|
|
self.frame = self.page.frames[1]
|
|
- self.page.wait_for_timeout(2000)
|
|
|