仅用在学习交流,如有侵权,联系删除。
仅用在学习交流,如有侵权,联系删除。
仅用在学习交流,如有侵权,联系删除。
当前douyin web端,请求cookie中有两个很重要的参数,一个就是s_v_web_id
,他又被成为fp
参数,今天简单的分析下。
第一步,先找个页面触发出滑块
紧接着打开控制台,找到Application,就可会看到s_v_web_id
参数了。
这里的s_v_web_id
值等于verify_lfhkbdvj_hWnJhmth_cNhn_4AbE_AX8t_BQl75IINjLfr
,再找到network窗口,可以看到有一个https://verify.snssdk.com/captcha/get
接口,该接口主要是获取验证码的。
在这个接口中有个fp参数,他们两个的值一模一样。
再打开网页源代码,也可以看到这个参数,说明这个参数在请求页面的时候就返回来了。
当然可以用js 生成出来
function get_fp() {
var e = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("")
, t = e.length
, n = (new Date).getTime().toString(36)
, r = [];
r[8] = r[13] = r[18] = r[23] = "_",
r[14] = "4";
for (var o, i = 0; i < 36; i++)
r[i] || (o = 0 | Math.random() * t,
r[i] = e[19 == i ? 3 & o | 8 : o]);
return "verify_" + n + "_" + r.join("")
}
当然也可以用python 实现一下
def get_fp(self):
e = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
t = len(e)
milliseconds = int(round(time.time() * 1000))
base36 = ''
while milliseconds > 0:
remainder = milliseconds % 36
if remainder < 10:
base36 = str(remainder) + base36
else:
base36 = chr(ord('a') + remainder - 10) + base36
milliseconds = int(milliseconds / 36)
r = base36
o = [''] * 36
o[8] = o[13] = o[18] = o[23] = '_'
o[14] = '4'
for i in range(36):
if not o[i]:
n = 0 or int(random.random() * t)
if i == 19:
n = 3 & n | 8
o[i] = e[n]
ret = "verify_" + r + "_" + ''.join(o)
return ret
接下来就是处理图片,识别缺口位置获取距离。
第一步要做的是处理图片的空白区域,这里主要清除滑块的空白。
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 get_slider_point(slider_path, bg_path):
"""
获取滑块的缺口坐标
slider_path: 缺口图片路径
bg_path: 背景图片
"""
# 处理滑块图片
img_fg = clear_white(slider_path)
slice_edges_img = cv2.Canny(img_fg, 100, 200)
slice_edges_color_img = cv2.cvtColor(slice_edges_img, cv2.COLOR_GRAY2RGB)
cv2.imwrite(f"./img/slider_cv_.png", slice_edges_color_img)
# 处理背景图片
img_bg = cv2.imread(bg_path)
temp_edges_img = cv2.Canny(img_bg, 100, 200)
temp_edges_color_img = cv2.cvtColor(temp_edges_img, cv2.COLOR_GRAY2RGB)
cv2.imwrite(f"./img/bg_cv_.png", temp_edges_color_img)
# 获得距离
tl = template_match(slice_edges_color_img,
temp_edges_color_img, f"img/tl_.png")
return tl
第三步 模拟滑块轨迹
def get_reply(self, real_width, real_height):
distance = 0
ans = []
move_arr = []
cur = 0
start_time = time.time()
t_dis = random.randint(520, 1500)
# t_dis = 603
# print("行驶距离:", t_dis)
while distance < real_width:
cur += random.randint(10, 20)
mod = self.sigmoid
x = int(mod(real_width, cur, 3500))
if x > real_width:
x = real_width
distance = x
ans.append({
"x": x,
"y": real_height,
"relative_time": cur
})
move_arr.append({
"x": x,
"y": real_height,
"time": cur + start_time
})
return ans, move_arr
第四步是根据加密生成captcha body 值,代码敏感就不贴了。
dGMFEAAAMlBkSjZCa09VdHhENm9uT2VyYW40Sk5pa1VTdkdncmF2AKDN408eKbacFiODqk9oqyqVE5Mt8Q3kHYJtQ27gd6KSwr5HNYiy2tTzZL0bix/cOP4IoHFklM3WydbOXjrBPceEuPnk3IrjlIu+c97gKgH33RUTydeWIsLkDSAGfjxZKIoFMuGJ8QiW8YaUzFEaO/X/mIlFIp42MT5XxU6KBDNGAi6MEGSqYyCJG9uXp4zRP1cOagcS3UklBYlH1Y1gxfLzXdI5S5T+NpMA4qeaHLMv6tzqKInAFjz+qLa4MvnjLbaNrSGrSZQ+BBpNsPoqQfAHQxl/SdwqxzKbMtY9V6HjGvc463rWz7Y16ETsOxJWsEiyCVo+ieQ9+q7dE0PKIznY6BGTxw+8Q9AY8O+K/YqPX/J50sXBKxwSGS5tIRxPw+wDnc2HJJoEugSncaEgH8CUggPa/CP6M83KzJeNhGbCxmu+xs2Yo9q1HGhM6EfTwhXyRtS2vGW5fznOWwW8SnGbE3z3afsx7Fl9l1ljry4SkuvpRVOz2hW/l64uqm0zOz5hy8TjSBprceTi8CoiG+cssnS74XDRpEdz94V8MDrrBFL+bFNPfusxvKYW0NzT8P1VL9R8Yaz22dykReAz3sBBP0jupIT0Z0w0bo4JE7Zh4k+gZji6wXJPISluVbZ6iBoAEyGw/n/32g8dmtwCpsNwSOlLLd8uBGGC+uKNxzrMeWLuQQ/XS/pgbY8LO/w9zCIFFHg/IvlAwTHI7kwUOR4naZv9xH/g657y/+DtXFyOOjvJAO+wkP7hClPyQlvlqS18JQwzjh6yMmKlZMkCMgba9EDIQEJXeMITHny7VKIghN4C2eJvDbhhJx1Vl6Zq46MZQVw7VVON4d/rHRCkbCzagnTF3ZUXPtFLgOT7zNZ3Vc3eBnfP4XZl7moj/nwpGamV7IsohD7OMuxq80JiQQvj8uuBJmNYrXpQ1feECbYeREnCvM4TPA7MrNPU4rahLUMA7PpeR7E7yIZD6IZdrfmC0x7Zx82L244pWssl+qM4JTZtYFHsxZlGnsB57Dik7woABXnf7E6gvJJyPAkihhlnxY1tW+GciLWTKrk8VkRkNmsriKnDozFr5VRWYmf4RNu8C6ekLBj7qugKXUoLRKiYb5W2ApO0spCiqrmLCGH168+DKMc5SJPInL6MhbVdT4qfKDGIBWFsMTpX/3IcbqpPHZhD+qzrepzfqWHbiHZ9e40ydh5qMcxmRQc1xV5lnJKL3Am53Es7X1qNZW9pOIXT8ZT66d0/WwXhcl4nizmpOuX8ShwIGU75Lu3E0+7lxqPTlMeRwAC/YQA7S5msWluMs7msG4IxDNQveGDANmPOry71L4FIK18bAAPmjF1wQEaXjwK1IFFZXZ12jpFT64o5vjFGZgaGFgENkk2s6FsFLnNAC+QHHLIarC4UwH8LilERIAjPysqKv8/T/5YCHB7jSXFgpqh6cDgJCidUGc60+uTSx+ZJD3izClmgJ2
最后一步就是向https://verify.zijieapi.com/captcha/verify
接口发送post请求就可以了。
最后看下效果,滑块就成功过掉了。
通过这种生成的 s_v_web_id
值可以用在用户,视频列表等很多接口。
当触动验证码弹出点选类型时,会遇到这种。
背景图:
待识别的文字:
可以使用ddddocr
模块,它使用的是开源训练数据集和模型,去识别文字的坐标。
识别具体坐标如图:
识别对应字:
然后就可以构造请求体了
并向接口 https://verify.zijieapi.com/captcha/verify
发起post请求就可以成功过掉滑块了。
最后结果如下:
仅用在学习交流,如有侵权,联系删除。