识别方法参考:https://blog.csdn.net/zhangzeyuaaa/article/details/119508407
问题
当失败次数过多时, 再尝试登录时, 会出现验证信息:滑动图片补全缺口;

脚本内容
# coding=utf-8 # @Time : 2023/2/2 22:59 # @Author : yu dian # @BlogUrl: http://119.23.247.188/ # @email: hhuyudian@163.com/dian.yu@casstime.com # @File : captcha_solver.py # @Software: PyCharm import cv2 import requests from urllib.parse import urljoin import time import base64 # fiddler_proxies = {'http': 'http://127.0.0.1:8888', 'https': 'http://127.0.0.1:8888'} class ECCaptchaSolver: env = { 'hwbeta': r'https://ec-hwbeta.casstime.com/' } def __init__(self, host, username, env=None): if env is None: self.host = host else: self.host = self.env[env] self.username = username self.sliderFile = 'slider.png' self.backgroundFile = "background.png" def _url(self, addr): return urljoin(self.host, addr) def isCaptchaNeed(self): """ 抓包判断是否会出现验证码 :return: """ # preurl = r'https://ec-hwbeta.casstime.com/passport/captcha/need' url = self._url(r'/passport/captcha/need') timestamp = int(time.time()) datas = { 'userName': self.username, 'data': timestamp } res = requests.get(url, params=datas) return res.json()['data'] def get_captcha_info(self): """ 获取验证码信息:背景图片, 碎片图片, y轴坐标 :return:token, y轴坐标 """ url = self._url('/passport/captcha') timestamp = int(time.time()) datas = { 'userName': self.username, 'data': timestamp } res = requests.get(url, params=datas).json()['data'] # print(res) captchaToken = res['captchaToken'] sliderImage = base64.b64decode(res['cutoutImage']) backgroundImage = base64.b64decode(res['shadeImage']) with open('slider.png', 'wb') as f: f.write(sliderImage) with open('background.png', 'wb') as f: f.write(backgroundImage) y = res['y'] # print(f'y:{y}') return captchaToken, y def get_slide_distance(self): """ 通过cv2库获取要滑动的距离. :return: x """ slider = self.sliderFile background = self.backgroundFile bg_img = cv2.imread(background) # 背景图片 tp_img = cv2.imread(slider) # 缺口图片 bg_edge = cv2.Canny(bg_img, 100, 200) tp_edge = cv2.Canny(tp_img, 100, 200) # 转换图片格式 bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB) tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB) # 缺口匹配 res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) # 寻找最优匹配 x = max_loc[0] # 滑块在验证图片的x坐标(左边) # 绘制方框 th, tw = tp_pic.shape[:2] tl = max_loc # 左上角点的坐标 br = (tl[0] + tw, tl[1] + th) # 右下角点的坐标 cv2.rectangle(bg_img, tl, br, (0, 0, 255), 2) # 绘制矩形 cv2.imwrite('out.jpg', bg_img) # 保存在本地 return x def move(self, token, x, y): """ 调接口来实现滑动动作. :param token: :param x: :param y: :return:是否成功. True/False """ url = self._url(r'/passport/captcha/verification') datas = { "y": y, "x": x, "captchaToken": token, "userName": "angus001" } res = requests.post(url, json=datas).json() return res['data'] def exec(self, max_times=10): """ 将上面的方法串起来执行. :param max_times: :return: """ if self.isCaptchaNeed(): for i in range(max_times): token, y = self.get_captcha_info() x = self.get_slide_distance() if self.move(token, x, y) is True: print('滑动拼图验证码解决成功.') break def cass_login(url, username, password): captchaSolver = ECCaptchaSolver(url, username) # 环境要修改为制动获取 captchaSolver.exec() session = requests.session() session.request( method="post", url=url + '/passport/login', data={'username': username, 'password': password, 'logintype': 'PASSWORD'} ) res = session.request(method='get', url=url) session.headers.update({"Cookie": res.request.headers.get('cookie', '')}) return session if __name__ == '__main__': cass_login(r'https://ec-hwbeta.casstime.com', 'name', 'password')
留言