一、前言
⚠️ 重要合规提醒
本文代码仅用于个人学习、技术研究,请勿用于批量恶意爬虫、违规刷量、破解登录等违法场景,遵守网站 robots 协议与网络安全法规。
💡 本篇独立讲解:滑块验证码专属方案
上篇回顾:1004 普通字符验证码(古诗文网图片验证码)
本篇核心:知乎极验滑块验证码突破实战
本篇 3 个核心文件清单
chaojiying.py:通用超级鹰打码客户端tools.py:滑块工具封装函数- 突破滑块验证码.py【本篇重点】
📝 系列文章回顾
第一篇:超级鹰注册充值
第二篇古诗文网字符验证码 1004 自动识别登录
第三篇(本篇):超级鹰 9901 滑块缺口识别,知乎极验滑块全自动突破登录
💡 绝大多数网站现在使用滑块验证码,单纯字符验证码越来越少,本篇带你搞定极验类滑块,实现全自动免人工拖动验证!
🛠️ 环境依赖安装
pip install requests DrissionPage
📂 项目完整目录结构
project/
├─ chaojiying.py # 通用超级鹰打码客户端(复用)
├─ tools.py # 滑块工具封装(可选,自己拓展)
└─ 突破滑块验证码.py # 本篇核心完整主程序
🔎 超级鹰题型编码再次区分(重点)
1004:普通字母 / 数字图片验证码(上篇)9901:滑块缺口坐标识别(本篇核心)
滑块验证完整原理流程

完整流程拆解
1. 初始化浏览器,Mac 用户指定 Chrome 完整路径(重点!)
2. 打开知乎首页,进入登录界面,填写账号密码并提交,触发极验滑块
3. 获取带缺口的滑块背景图,元素截图保存本地 bj.png
4. 实例化超级鹰客户端,二进制读取截图,调用 9901 识别接口拿到缺口坐标
5. 根据页面缩放比例校正像素,减去滑块本身宽度,算出真实需要滑动距离
6. 使用 DrissionPage Actions 动作链模拟真人鼠标:悬浮 → 按住 → 拖动 → 释放
7. 校验登录成功元素,判断是否完成登录,捕获异常做报错处理
二、chaojiying.py
#!/usr/bin/env python
# coding:utf-8
import requests
from hashlib import md5
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username
password = password.encode('utf8')
self.password = md5(password).hexdigest()
self.soft_id = soft_id
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype, str_debug=""):
params = {
'codetype': codetype,
'str_debug': str_debug
}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
return r.json()
def PostPic_base64(self, base64_str, codetype):
params = {
'codetype': codetype,
'file_base64':base64_str
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, headers=self.headers)
return r.json()
def ReportError(self, im_id):
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
if __name__ == '__main__':
chaojiying = Chaojiying_Client('你的账号', '你的密码', '96001')
im = open('../RandCode.png', 'rb').read()
result = chaojiying.PostPic(im, 1004)
print(result['pic_str'])
三、tools.py
from Chaojiying import Chaojiying_Client
from DrissionPage import ChromiumPage
from DrissionPage.common import Actions
def drag_verify(page):
# # 1. 初始化浏览器并访问知乎
# page = ChromiumPage()
# page.get('https://www.zhihu.com/')
# page.wait(3) # 等待页面加载
#
# # 2. 执行登录操作
# page.ele('.SignFlow-tab').click() # 点击“密码登录”标签
# page.ele('xpath://input[@name="username"]').input('3920682002@qq.com') # 输入手机号或邮箱
# page.ele('xpath://input[@name="password"]').input('Aa123456789') # 输入密码
# page.ele('xpath://button[@type="submit"]').click() # 点击登录按钮
#
# # 3. 获取验证码背景图并保存(背景图上有缺口,需要保存之后使用超级鹰的方法来识别缺口位置, 这样才能直到要将滑块滑到哪个位置)
bg_img = page.ele('.yidun_bg-img') # 定位背景图元素
# 将背景图保存为本地文件, 并重新命名
bg_img.save(name='bg.png', rename=False)
# 4. 【计算拖动距离】找到要拖动的滑块,将滑块移动到缺口位置
# 4.1 找到要拖动的滑块
slider = page.ele('.yidun_jigsaw')
# 4.2 使用超级鹰的方法,识别缺口在图片内的坐标
# 换成自己的超级鹰账号和密码, 96001可不改
chaojiying = Chaojiying_Client('tiantian991', '8nvz3u4t', '96001')
# 读取刚刚保存的背景图
with open('bg.png', 'rb') as f:
# 使用超级鹰的chaojiying.PostPic方法识别滑块缺口位置,
# f.read()是在传入读取到的图片数据,9901是专门用来识别滑块图的模式
# result中的pic_str就是缺口的位置
result = chaojiying.PostPic(f.read(), 9901)
# print(result) {'err_no': 0, 'err_str': 'OK', 'pic_id': '2330620092252970036', 'pic_str': '261,60', 'md5': 'b9af18240aaebce8981e0f8bd2b51506'}
# 解析识别结果,获取缺口相对于保存的背景图的X坐标
# 得到的result是个字典,需要的数据在字典的pic_str中, result['pic_str']获取对应的值,得到'261,60'
# '261,60', 261是缺口在背景图中x轴的位置, .split(',')表示将'261,60'从,分割成两部分,得到的结果是[261,60]
# [0]就是取列表的第一个,获取缺口的位置
blank_x = int(result['pic_str'].split(',')[0])
print(f'识别缺口X坐标: {blank_x}')
# 滑动滑块函数【直接使用】
# 【参数说明】
# drag_ele:要拖动的滑块位置
# blank_distance:缺口x坐标
def drag_slider(drag_ele, blank_distance):
# offset_x 为微调值,用于补偿识别误差
# 三目运算符,如果缺口的x小于150的话, 微调值为10,否则,微调值为8
offset_x = 10 if blank_distance < 150 else 8
axis_x = blank_distance - offset_x
print(f'计算得出的实际滑动距离: {axis_x}')
# 模拟鼠标拖动滑块完成验证
page.wait(3) # 等待验证码加载完成
ac = Actions(page)
drag_ele.hover() # 鼠标悬停在滑块上
ac.hold(drag_ele) # 按下鼠标
ac.move(axis_x, 0) # 水平移动计算出的距离(只需要横向移动)
ac.release(drag_ele) # 松开鼠标
try:
# 使用函数,滑动滑块
drag_slider(slider, blank_x)
return True
except:
return False
#只导入函数,若只导入文件则不能运行:
if __name__ == "__main__":
drag_verify()
四、【突破滑块验证码.py】完整源码
from Chaojiying import Chaojiying_Client
from DrissionPage import ChromiumPage,ChromiumOptions #网页自动化爬取------自动化库
from DrissionPage.common import Actions
co = ChromiumOptions()
co.set_browser_path("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")
co.auto_port(True)
page=ChromiumPage(co) #Mac版----创建浏览器【windows只需要page=ChromiumPage()即可】
page.get('http://www.zhihu.com')
page.wait(5)
page.ele('.SignFlow-tab').click()
page.ele('xpath://input[@name="username"]').input('你的账号')
page.ele('xpath://input[@name="password"]').input('你的密码')
page.wait(2)
page.ele('xpath://button[@type="submit"]').click()
page.wait(2)
bj_img=page.ele('.yidun_bgimg')
bj_img.get_screenshot('bj.png')
#bj_img.save(name='bj_img.png',rename=False) ,就是在保存图片====截图,名称永不改变之意
huakuai=page.ele('.yidun_slider__icon')
Chaojiying = Chaojiying_Client('你的超级鹰账号','你的超级鹰密码','96001') #登录超级鹰
with open('bj.png','rb') as f:
result = Chaojiying.PostPic(f.read(),9901)
# print(result['pic_str']) #'247,74'
blank_x = result['pic_str'].split(',')[0]
print(blank_x)
#滑动滑块函数(会用就好)
#只需要传入对应的滑块,和缺口的x坐标,就可以直接使用我供的函数了
# drag_ele:要拖动的滑块位置
#blank_distance:缺口x坐标
def drag_slider(drag_ele, blank_distance, page):
scale = 0.557
slider_w = 41
real_x = int(blank_distance) * scale
axis_x = real_x - slider_w
print(f'识别坐标:{blank_x},缩放后:{real_x:.1f},滑动距离:{axis_x:.1f}')
ac = Actions(page)
drag_ele.hover()
ac.hold(drag_ele)
ac.move(axis_x, 0)
ac.release(drag_ele)
try:
drag_slider(huakuai,int(blank_x),page)
#判断有没有登录成功
page.ele('.Avatar AppHeader-profileAvatar css-d9tvwx',timeout=3).click()
except:
print('出错了')
五、逐行保姆级源码解析
1. 模块导入
from Chaojiying import Chaojiying_Client
from DrissionPage import ChromiumPage,ChromiumOptions
from DrissionPage.common import Actions
Chaojiying_Client:调用超级鹰 9901 识别缺口坐标ChromiumPage,ChromiumOptions:浏览器自动化,Mac 重点配置 Chrome 路径Actions:模拟鼠标动作链,按住、拖动、释放滑块,防风控核心
2. Mac 专属浏览器初始化【小白高频踩坑点】
Mac 系统:必须指定 Chrome 完整可执行路径,否则启动浏览器报错
co = ChromiumOptions()
co.set_browser_path("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")
co.auto_port(True)
page=ChromiumPage(co)
Windows 简化写法(替换上面代码)
page=ChromiumPage()

3. 访问知乎并进入登录表单
page.get('http://www.zhihu.com')
page.wait(5)
page.ele('.SignFlow-tab').click()
page.ele('xpath://input[@name="username"]').input('你的账号')
page.ele('xpath://input[@name="password"]').input('你的密码')
page.wait(2)
page.ele('xpath://button[@type="submit"]').click()
page.wait(2)
page.wait():强制等待,等待页面 DOM 渲染完成,防止元素找不到报错- 定位登录 tab、账号密码输入框,填充信息提交,触发极验滑块验证码

4. 获取滑块缺口背景图 & 滑块元素
bj_img=page.ele('.yidun_bgimg')
bj_img.get_screenshot('bj.png')
huakuai=page.ele('.yidun_slider__icon')
重点:使用 get_screenshot() 对缺口背景元素截图,只截取验证码区域,减少干扰
yidun_bgimg:带缺口的背景图
yidun_slider__icon:需要拖动的滑块图标元素

5. 调用超级鹰 9901 识别缺口坐标【核心】
Chaojiying = Chaojiying_Client('你的账号','你的密码’,'96001')
with open('bj.png','rb') as f:
result = Chaojiying.PostPic(f.read(),9901)
blank_x = result['pic_str'].split(',')[0]
print(blank_x)
题型编码:
9901滑块缺口识别
返回示例pic_str:247,74,逗号分隔,前面为 X 横向坐标,后面 Y 纵向坐标
我们只需要横向 X 坐标,用来计算滑动距离

6. drag_slider 滑动函数【重中之重,缩放校正】
def drag_slider(drag_ele, blank_distance, page):
scale = 0.557
slider_w = 41
real_x = int(blank_distance) * scale
axis_x = real_x - slider_w
print(f'识别坐标:{blank_x},缩放后:{real_x:.1f},滑动距离:{axis_x:.1f}')
ac = Actions(page)
drag_ele.hover()
ac.hold(drag_ele)
ac.move(axis_x, 0)
ac.release(drag_ele)
scale = 0.557:页面缩放比例校正(很多小白忽略这个,拖动位置不准,验证失败),次数值是按照我的电脑的标准,大家可以自行修正
slider_w = 41:滑块本身宽度,必须减去滑块宽度修正偏移
动作链流程:hover 悬浮 → hold 按住滑块 → move 平移 → release 释放,模拟真人操作,降低风控检测
7. 异常捕获 + 登录成功校验
try:
drag_slider(huakuai,int(blank_x),page)
#判断有没有登录成功
page.ele('.Avatar AppHeader-profileAvatar css-d9tvwx',timeout=3).click()
except:
print('出错了')
try-except 捕获拖动、元素查找过程中的报错
查找头像元素,作为登录成功判定标识,验证是否真正登录成功

六、调试优化 & 踩坑大全(CSDN 读者最喜欢章节)
###踩坑 1:Mac 启动 Chromium 报错找不到浏览器
❌ 现象:初始化 ChromiumOptions 启动失败
✅ 解决:核对 Chrome 完整可执行路径,Mac 必须配置 set_browser_path
踩坑 2:识别坐标拿到了,拖动完依旧验证失败
❌ 现象:坐标识别成功,拖动完成,但是校验不通过
✅ 解决:重点检查缩放比例 scale,不同设备页面缩放不同,调整 scale 值,同时修正滑块宽度偏移
踩坑 3:截图空白,超级鹰识别报错
❌ 现象:截图的时候验证码还没渲染完成
✅ 解决:增加 page.wait() 等待时间,等滑块完整加载完成再截图
踩坑 4:网页改版,class 选择器失效
❌ 现象:page.ele() 获取元素返回空
解决:F12 重新检查页面,更新最新 class,如 yidun_bgimg、yidun_slider__icon
踩坑 5:超级鹰题分不足,接口返回报错
❌ 现象:调用 PostPic 返回 err_no 报错
✅ 解决:登录超级鹰后台充值题分,查看剩余题分
踩坑 6:Windows 用户照搬 Mac 浏览器初始化代码
❌ 现象:Windows 写死 Chrome 路径,浏览器启动异常
✅ 解决:Windows 直接简化 page=ChromiumPage(),去掉 ChromiumOptions 配置
踩坑 7:动作链拖动太机械,被风控拦截
❌ 现象:拖动完成但是被判定机器操作,验证失败
✅ 拓展优化:增加随机微小偏移,分段多次移动,模拟真人抖动式拖动
七、优化增强完整版代码(增加重试、异常捕获、日志输出,拓展版)
💡 给读者福利,在原版基础上加上循环重试、完善异常捕获,小白直接拿去增强稳定性
from Chaojiying import Chaojiying_Client
from DrissionPage import ChromiumPage,ChromiumOptions
from DrissionPage.common import Actions
import time
def drag_slider(drag_ele, blank_distance, page, scale=0.557, slider_w=41):
real_x = int(blank_distance) * scale
axis_x = real_x - slider_w
print(f'识别坐标:{blank_x},缩放后:{real_x:.1f},滑动距离:{axis_x:.1f}')
ac = Actions(page)
drag_ele.hover()
ac.hold(drag_ele)
ac.move(axis_x, 0)
ac.release(drag_ele)
def zhihu_slider_login(max_retry=3):
co = ChromiumOptions()
# Mac配置,Windows注释掉这两行
co.set_browser_path("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")
co.auto_port(True)
page=ChromiumPage(co)
try:
page.get('http://www.zhihu.com')
page.wait(5)
page.ele('.SignFlow-tab').click()
page.ele('xpath://input[@name="username"]').input('你的账号')
page.ele('xpath://input[@name="password"]').input('你的密码')
page.wait(2)
page.ele('xpath://button[@type="submit"]').click()
page.wait(2)
chaojiying = Chaojiying_Client('你的超级鹰账号','你的超级鹰密码','96001')
retry_cnt = 0
while retry_cnt < max_retry:
bj_img=page.ele('.yidun_bgimg')
bj_img.get_screenshot('bj.png')
huakuai=page.ele('.yidun_slider__icon')
with open('bj.png','rb') as f:
res = chaojiying.PostPic(f.read(),9901)
if res['err_no'] !=0:
print(f"识别失败,重试 {retry_cnt+1}")
retry_cnt +=1
time.sleep(1)
continue
blank_x = res['pic_str'].split(',')[0]
print(f"识别缺口X坐标:{blank_x}")
drag_slider(huakuai,int(blank_x),page)
try:
page.ele('.Avatar AppHeader-profileAvatar css-d9tvwx',timeout=3)
print("✅ 登录成功!")
break
except:
print(f"验证失败,重试 {retry_cnt+1}")
retry_cnt +=1
except Exception as e:
print(f"程序异常:{e}")
finally:
# page.quit() # 可选择关闭浏览器
pass
if __name__ == "__main__":
zhihu_slider_login()
八、拓展思考
1. 🤔 思考 1:如何增加随机抖动偏移,优化拖动轨迹,进一步规避网站风控检测?
2. 🤔 思考 2:多账号批量登录场景,如何循环刷新验证码,批量突破滑块?
3. 🤔 思考 3:不同网站滑块缩放比例不一样,能不能自动识别缩放比例,不用手动填 scale?
4. 🤔 思考 4:如果是多段式、旋转类验证码,超级鹰对应的题型编码该如何选择?
九、 系列总结
【系列完整收官】
第一篇:1004 字符验证码(古诗文网)
第二篇:9901 极验滑块验证码(知乎)
两套方案覆盖市面上绝大多数登录验证码场景,学会这两套,绝大多数自动化登录验证码难题可以搞定!欢迎评论区交流你遇到的各种奇葩验证码踩坑经历!
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/Echo_Vale/article/details/169741926




