Python实现新版正方系统滑动验证码识别
程序员文章站
2022-03-04 13:41:21
目录步骤一:点击数据分析步骤二:滑动验证码图像分析,计算滑动距离x值步骤三:生成提交参数python实现新版正方系统滑动验证码识别算法和方案步骤一:点击数据分析点击滑动按钮,将发送一个请求到 /zfc...
python实现新版正方系统滑动验证码识别算法和方案
步骤一:点击数据分析
点击滑动按钮,将发送一个请求到 /zfcaptchalogin
请求内容
"type": "verify" "rtk": "6cfab177-afb2-434e-bacf-06840c12e7af" "time": "1624611806948" "mt": "w3sieci6oty1lcj5ijoxnjksinqioje2mjq2mte4mdy4njh9lhsieci6oty1lcj5ijoxnjksinqioje2mjq2mte4mdy5ndh9xq==" "instanceid": "zfcaptchalogin" "extend": "eyjhchboyw1lijoitmv0c2nhcguilcj1c2vyqwdlbnqioijnb3ppbgxhlzuumcaotwfjaw50b3nooybjbnrlbcbnywmgt1mgwcaxmf8xnv83ksbbchbszvdlyktpdc81mzcumzygketive1mlcbsawtliedly2tvksbdahjvbwuvoteumc40ndcyljewnibtywzhcmkvntm3ljm2iiwiyxbwvmvyc2lvbii6ijuumcaotwfjaw50b3nooybjbnrlbcbnywmgt1mgwcaxmf8xnv83ksbbchbszvdlyktpdc81mzcumzygketive1mlcbsawtliedly2tvksbdahjvbwuvoteumc40ndcyljewnibtywzhcmkvntm3ljm2in0="
通过 base64 解密 mt和 extend 得出解密的数值
# mt [{"x":965,"y":169,"t":1624611806868},{"x":965,"y":169,"t":1624611806948}] # extend {"appname":"netscape","useragent":"mozilla/5.0 (macintosh; intel mac os x 10_15_7) applewebkit/537.36 (khtml, like gecko) chrome/91.0.4472.106 safari/537.36","appversion":"5.0 (macintosh; intel mac os x 10_15_7) applewebkit/537.36 (khtml, like gecko) chrome/91.0.4472.106 safari/537.36"}
mt 为用户的点击行为,x为x轴上的值,y为y轴上的值,t为时间戳。通过大量点击分析,发现x值最小值为 950,得出950 为 x轴的起点,y值随机无固定值。
extend 为请求头部内容
步骤二:滑动验证码图像分析,计算滑动距离x值
将图像灰度化,通过getpixel可以获取图像某一点的颜色值, 颜色值越高代表图像越浅,所以寻找纵向连续50个像素点均是 getpixel(x+1, y) > getpixel(x, y)(x轴=x 比 x轴=x+1 颜色浅)
并扫描图像,当x=130、扫描高度=50时,的颜色比x+1时深。
from pil import image import matplotlib.pyplot as plt import numpy as np scanf_height= 50 # 扫描的高度 img = image.open("zfcaptchalogin.png") def contrast(imgl, x, y,scanf_height): # 黄框颜色值比红框颜色值浅的个数 count = 0 for i in range(scanf_height): if imgl.getpixel((x+1, y+i)) > imgl.getpixel((x, y+i)): count += 1 # 当 count = scanf_height, 代表黄条区域 整体 红条区域 颜色值浅,则是验证码框位置 return count def scanf(img): imgx, imgy = img.size imgl = img.convert('l') # 图像灰度化 plt.yticks([]) plt.xticks([i for i in range(0, imgx, 25)]) plt.imshow(img) plt.pause(0.5) for y in range(0, imgy-scanf_height, 10): plt.pause(0.01) plt.clf() plt.yticks([]) plt.xticks([i for i in range(0, imgx, 25)]) plt.imshow(imgl, cmap=plt.cm.gray) for x in range(1, imgx-1, 1): plt.pause(0.0001) plt.plot([x-1,x-1], [y, y+scanf_height], color='white') plt.plot([x,x], [y, y+scanf_height], color='red') plt.plot([x+1,x+1], [y, y+scanf_height], color='yellow') count = contrast(imgl, x,y, scanf_height) plt.title('count: {}'.format(count) ) print("x,y=[{}, {}], 黄条区域值比红条区域颜色值浅的个数:{}".format(x,y, count)) if count == scanf_height: return scanf(img) plt.show()
优化代码计算x,y值
import json import random import time from io import bytesio from pil import image class zfcaptcharecognit(object): def __init__(self, img_path): self.img = image.open(img_path) def _get_xy(self): # 计算 x,y 值 def _is_dividing_line(img_l, x, y): for n in range(50): # 寻找纵向连续50个像素点均是 x=x 比 x=x+1 颜色深 if y + n >= img_l.size[1] or x >= img_l.size[0] - 1: return false if img_l.getpixel((x + 1, y + n)) - img_l.getpixel((x, y + n)) < 2: return false return true img_l = self.img.convert("l") for x in range(img_l.size[0]): for y in range(img_l.size[1]): if _is_dividing_line(img_l, x, y): return (x, y) def show_tag(self): # 展示 切分点 x, y = self._get_xy() img2 = image.new("rgb", self.img.size, (255, 255, 255)) for x in range(self.img.size[0]): for y in range(self.img.size[1]): pix = self.img.getpixel((x, y)) img2.putpixel((x, y), pix) if x == x or y == y: img2.putpixel((x, y), 225) img2.save("show_tag.png") img2.show() captcha = zfcaptcharecognit("zfcaptchalogin.png") captcha.show_tag()
步骤三:生成提交参数
通过 步骤一得出x值最小为950,y值无规律
则提交参数mt的大致格式数据是
[{ "x":950+ 滑动距离 + 浮动值, # 浮动值的范围通过分析提交参数得出在10~20内 "y":random.randint(150, 190), # 无规律,暂定150到190范围内 "t":int(time.time() * 1000)}, # 时间戳 ...]
获取mt 参数
import json import random import time from io import bytesio from pil import image class zfcaptcharecognit(object): def __init__(self, img_stream): obj = bytesio(img_stream) self.img = image.open(obj) def _get_xy(self): ... def generate_payload(self): base_x = 950 x, y = self._get_xy() payloads = [{"x": base_x + random.randint(5, 20), "y": random.randint(150, 190), "t": int(time.time() * 1000)}] for i in range(random.randint(15, 30)): # 在上一个参数基础下浮动 last_payload = payloads[-1].copy() payloads[0]["x"] += random.choice([0] * 8 + [1, -1] * 2 + [2, -2]) last_payload["t"] += random.randint(1, 20) last_payload["y"] += random.choice([0] * 8 + [1, -1] * 2 + [2, -2]) payloads.append(last_payload) payloads[-1]["x"] = base_x + random.randint(10, 20) + x return json.dumps(payloads) captcha = zfcaptcharecognit("zfcaptchalogin.png") captcha. generate_payload()
以上就是python实现新版正方系统滑动验证码识别的详细内容,更多关于python滑动验证码识别的资料请关注其它相关文章!