识别方法参考: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')
# 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')
# 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')
最后修改日期: 2024年11月3日

作者

留言

撰写回覆或留言