mirror of
https://github.com/sijiyo/projects.git
synced 2025-04-12 11:36:59 +08:00
数美滑块/shumei_slide
This commit is contained in:
parent
400049e486
commit
b8e9ea42d6
89
shumei_slide/gap.py
Normal file
89
shumei_slide/gap.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import cv2
|
||||||
|
|
||||||
|
|
||||||
|
class SlideCrack(object):
|
||||||
|
def __init__(self, gap, bg, out):
|
||||||
|
"""
|
||||||
|
init code
|
||||||
|
:param gap: 缺口图片
|
||||||
|
:param bg: 背景图片
|
||||||
|
:param out: 输出图片
|
||||||
|
"""
|
||||||
|
self.gap = gap
|
||||||
|
self.bg = bg
|
||||||
|
self.out = out
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def clear_white(img):
|
||||||
|
# 清除图片的空白区域,这里主要清除滑块的空白
|
||||||
|
img = cv2.imread(img)
|
||||||
|
rows, cols, channel = img.shape
|
||||||
|
min_x = 255
|
||||||
|
min_y = 255
|
||||||
|
max_x = 0
|
||||||
|
max_y = 0
|
||||||
|
for x in range(1, rows):
|
||||||
|
for y in range(1, cols):
|
||||||
|
t = set(img[x, y])
|
||||||
|
if len(t) >= 2:
|
||||||
|
if x <= min_x:
|
||||||
|
min_x = x
|
||||||
|
elif x >= max_x:
|
||||||
|
max_x = x
|
||||||
|
|
||||||
|
if y <= min_y:
|
||||||
|
min_y = y
|
||||||
|
elif y >= max_y:
|
||||||
|
max_y = y
|
||||||
|
img1 = img[min_x:max_x, min_y: max_y]
|
||||||
|
return img1
|
||||||
|
|
||||||
|
def template_match(self, tpl, target):
|
||||||
|
th, tw = tpl.shape[:2]
|
||||||
|
result = cv2.matchTemplate(target, tpl, cv2.TM_CCOEFF_NORMED)
|
||||||
|
# 寻找矩阵(一维数组当作向量,用Mat定义) 中最小值和最大值的位置
|
||||||
|
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
|
||||||
|
tl = max_loc
|
||||||
|
br = (tl[0] + tw, tl[1] + th)
|
||||||
|
# 绘制矩形边框,将匹配区域标注出来
|
||||||
|
# target:目标图像
|
||||||
|
# tl:矩形定点
|
||||||
|
# br:矩形的宽高
|
||||||
|
# (0,0,255):矩形边框颜色
|
||||||
|
# 1:矩形边框大小
|
||||||
|
cv2.rectangle(target, tl, br, (0, 0, 255), 2)
|
||||||
|
cv2.imwrite(self.out, target)
|
||||||
|
return tl[0]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def image_edge_detection(img):
|
||||||
|
edges = cv2.Canny(img, 100, 200)
|
||||||
|
return edges
|
||||||
|
|
||||||
|
def discern(self):
|
||||||
|
img1 = self.clear_white(self.gap)
|
||||||
|
img1 = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
|
||||||
|
slide = self.image_edge_detection(img1)
|
||||||
|
|
||||||
|
back = cv2.imread(self.bg, 0)
|
||||||
|
back = self.image_edge_detection(back)
|
||||||
|
|
||||||
|
slide_pic = cv2.cvtColor(slide, cv2.COLOR_GRAY2RGB)
|
||||||
|
back_pic = cv2.cvtColor(back, cv2.COLOR_GRAY2RGB)
|
||||||
|
x = self.template_match(slide_pic, back_pic)
|
||||||
|
# 输出横坐标, 即 滑块在图片上的位置
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
def get_gap():
|
||||||
|
# 滑块图片
|
||||||
|
image1 = "img/slide.png"
|
||||||
|
# 背景图片
|
||||||
|
image2 = "img/bg.png"
|
||||||
|
|
||||||
|
# 处理结果图片,用红线标注
|
||||||
|
image3 = "img/show_image.png"
|
||||||
|
sc = SlideCrack(image1, image2, image3)
|
||||||
|
return sc.discern()
|
BIN
shumei_slide/img/bg.png
Normal file
BIN
shumei_slide/img/bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
shumei_slide/img/show_image.png
Normal file
BIN
shumei_slide/img/show_image.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
BIN
shumei_slide/img/slide.png
Normal file
BIN
shumei_slide/img/slide.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
64
shumei_slide/main.py
Normal file
64
shumei_slide/main.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import requests,re,json,base64,execjs
|
||||||
|
from urllib import request
|
||||||
|
from gap import *
|
||||||
|
from track import *
|
||||||
|
with open('shumei.js', 'r', encoding='utf-8') as f:
|
||||||
|
js = execjs.compile(f.read())
|
||||||
|
def get_image(organization):
|
||||||
|
url = 'https://captcha1.fengkongcloud.cn/ca/v1/register'
|
||||||
|
params = {
|
||||||
|
"organization": organization,
|
||||||
|
"data": "{}",
|
||||||
|
"appId": "default",
|
||||||
|
"model": "slide",
|
||||||
|
"rversion": '1.0.4',
|
||||||
|
"lang": "zh-cn",
|
||||||
|
"channel": "DEFAULT",
|
||||||
|
"callback": get_callback(),
|
||||||
|
"sdkver": '1.1.3',
|
||||||
|
"captchaUuid": get_captchaUuid()
|
||||||
|
}
|
||||||
|
res = requests.get(url, params=params).text
|
||||||
|
match = re.search(r'({.+})', res).group(1)
|
||||||
|
data = json.loads(match)
|
||||||
|
request.urlretrieve('https://castatic.fengkongcloud.cn'+data['detail']['bg'], './img/bg.png')
|
||||||
|
request.urlretrieve('https://castatic.fengkongcloud.cn'+data['detail']['fg'], './img/slide.png')
|
||||||
|
distance = round(get_gap()/2)
|
||||||
|
rid = data['detail']['rid']
|
||||||
|
return distance,rid
|
||||||
|
def get_main(organization):
|
||||||
|
distance,rid = get_image(organization)
|
||||||
|
track = get_track(distance)
|
||||||
|
je = js.call('DES_Encrypt', str(distance / 300), "5ea96022")
|
||||||
|
ww = js.call('DES_Encrypt', str(track[-1][-1] + random.randint(10, 100)), "17a94a08")
|
||||||
|
mu = js.call('DES_Encrypt', json.dumps(track, separators=(',', ':')), "e7e1eb0d")
|
||||||
|
params = {
|
||||||
|
"je": je,
|
||||||
|
"ww": ww,
|
||||||
|
"mu": mu,
|
||||||
|
"rid": rid,
|
||||||
|
"captchaUuid": get_captchaUuid(),
|
||||||
|
"organization": organization,
|
||||||
|
"callback": get_callback(),
|
||||||
|
"rversion": '1.0.4',
|
||||||
|
"sdkver": '1.1.3',
|
||||||
|
"nu": "C0kH/bWLjw8=", # mouseEndX=300, "390aac0d"
|
||||||
|
"dy": "Rfpr5oqb5y4=", # trueHeight=150, "a9001672"
|
||||||
|
"en": "y+ugz9NIWys=",
|
||||||
|
"tb": "3jSn4gNaAVM=", # 1,'6f5e9847'
|
||||||
|
"kq": "mtlOTdT5LOE=",
|
||||||
|
"mp": "WYfkIZp7GoA=",
|
||||||
|
"oc": "h9oFKi8cHpg=",
|
||||||
|
"xy": "YabT6nmJOC0=", # "zh-cn"
|
||||||
|
"jo": "l3aEINYnwpY=",
|
||||||
|
"protocol": "180",
|
||||||
|
"ostype": "web",
|
||||||
|
"act.os": "web_pc",
|
||||||
|
}
|
||||||
|
url = 'https://captcha1.fengkongcloud.cn/ca/v2/fverify'
|
||||||
|
res = requests.get(url, params=params).text
|
||||||
|
match = re.search(r'({.+})', res).group(1)
|
||||||
|
print(match)
|
||||||
|
if __name__ == '__main__':
|
||||||
|
organization = "RlokQwRlVjUrTUlkIqOg"
|
||||||
|
get_main(organization)
|
1219
shumei_slide/shumei.js
Normal file
1219
shumei_slide/shumei.js
Normal file
File diff suppressed because it is too large
Load Diff
35
shumei_slide/track.py
Normal file
35
shumei_slide/track.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import random,time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def get_track(distance):
|
||||||
|
"""生成轨迹"""
|
||||||
|
base_track = [
|
||||||
|
[0, 0, 0], [0, -2, 102], [9, -3, 205],
|
||||||
|
[44, -5, 303], [82, -4, 409], [125, -3, 503],
|
||||||
|
[138, -2, 601], [166, -1, 702], [194, -1, 805],
|
||||||
|
[211, -1, 903], [222, -1, 1005], [224, -1, 1101],
|
||||||
|
[228, -1, 1201], [228, -1, 1316], [232, -2, 1401],
|
||||||
|
[232, -2, 1514], [232, -2, 1601], [233, -2, 1705],
|
||||||
|
[233, -2, 1801], [233, -2, 1902], [236, -3, 2001],
|
||||||
|
[236, -3, 2101], [236, -3, 2201], [236, -3, 2309],
|
||||||
|
[236, -3, 2402], [236, -3, 2512], [236, -3, 2601],
|
||||||
|
[236, -3, 2715], [236, -3, 2809], [236, -3, 2902]
|
||||||
|
]
|
||||||
|
random_y = random.randint(0, 5)
|
||||||
|
radio = distance / base_track[-1][0]
|
||||||
|
new_track = []
|
||||||
|
for x, y, t in base_track:
|
||||||
|
y = y + random_y if y else 0
|
||||||
|
point = [round(x * radio), y, round(t * radio)]
|
||||||
|
new_track.append(point)
|
||||||
|
return new_track
|
||||||
|
|
||||||
|
def get_callback():
|
||||||
|
return 'sm_' + str(int(time.time() * 1000))
|
||||||
|
def get_captchaUuid():
|
||||||
|
"""生成请求参数captchaUuid smcp.min.js"""
|
||||||
|
text = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"
|
||||||
|
random18_str = ''.join(random.choices(text, k=18))
|
||||||
|
time_str = datetime.now().strftime('%Y%m%d%H%M%S')
|
||||||
|
return time_str + random18_str
|
Loading…
x
Reference in New Issue
Block a user