Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)


Posted in Python onFebruary 17, 2020

准备工作

B站登录页 https://passport.bilibili.com/login
python3
pip install selenium (webdriver框架)
pip install PIL (图片处理)
chrome driver:http://chromedriver.storage.googleapis.com/index.html
firefox driver:https://github.com/mozilla/geckodriver/releases

Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)

B站的滑块验证码如上。

这类验证码可以使用 selenium 操作浏览器拖拽滑块来进行破解,难点两个,一个如何确定拖拽到的位置,另一个是避开人机识别(反爬虫)。

确定滑块验证码需要拖拽的位移距离

有三种方式

  • 人工智能机器学习,确定滑块位置
  • 通过完整图片与缺失滑块的图片进行像素对比,确定滑块位置
  • 边缘检测算法,确定位置

各有优缺点。人工智能机器学习,确定滑块位置,需要进行训练,比较麻烦,也可以看是否存在在线api可以调用。以下介绍其他两种方式。

对比完整图片与缺失滑块的图片

| 仅介绍,本文不进行实现。对于B站来说,是准确率最高的方式(100%),但不能保证未来B站的滑块验证升级,导致不可用。

B站的滑块验证模块,一共有三张图片:

完整图、缺失滑块图、滑块图,都是由画布绘制出的。类似于:

完整图:

Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)

缺失滑块图:

Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)

滑块图:

Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)

HTML代码类似于:

<div class="geetest_canvas_img geetest_absolute" style="display: block;">
<div class="geetest_slicebg geetest_absolute">
	<canvas class="geetest_canvas_bg geetest_absolute" height="160" width="260"></canvas>
	<canvas class="geetest_canvas_slice geetest_absolute" width="260" height="160"></canvas>
</div>
<canvas class="geetest_canvas_fullbg geetest_fade geetest_absolute" height="160" width="260" style="display: none;"></canvas>
</div>

只需要通过selenium获取画布元素,执行js拿到画布像素,遍历完整图和缺失滑块图的像素,一旦获取到差异(需要允许少许像素误差),像素矩阵x轴方向即是滑块位置。
另外由于滑块图距离画布坐标原点有距离,还需要减去这部分距离。
最后使用 selenium 拖拽即可。

边缘检测算法,确定位置

| 滑块基本上是个方形,通过算法确定方形起始位置即可。

Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)

介绍两种方式

  • 滑块是方形的,存在垂直的边,该边在缺失滑块图中基本都是灰黑的。遍历像素找到基本都是灰黑的边即可。
  • 缺失滑块图中滑块位置是灰黑封闭的。通过算法可以找到封闭区域,大小与滑块相近,即是滑块需要拖拽到的位置。

第二种实现起来有些复杂,不进行实现了。

下面是第一种实现方式,会存在检测不出或错误的情况,使用时需要换一张验证码。也可能存在检测出的边是另一条(因为B站的滑块不是长方形,存在弧形边),那么需要减去滑块宽度

class VeriImageUtil():

 def __init__(self):
  self.defaultConfig = {
   "grayOffset": 20,
   "opaque": 1,
   "minVerticalLineCount": 30
  }
  self.config = copy.deepcopy(self.defaultConfig)

 def updateConfig(self, config):
  # temp = copy.deepcopy(config)
  for k in self.config:
   if k in config.keys():
    self.config[k] = config[k]

 def getMaxOffset(self, *args):
  # 计算偏移平均值最大的数
  av = sum(args) / len(args)

  maxOffset = 0
  for a in args:
   offset = abs(av - a)
   if offset > maxOffset:
    maxOffset = offset
  return maxOffset

 def isGrayPx(self, r, g, b):
  # 是否是灰度像素点,允许波动offset
  return self.getMaxOffset(r, g, b) < self.config["grayOffset"]

 def isDarkStyle(self, r, g, b):
  # 灰暗风格
  return r < 128 and g < 128 and b < 128

 def isOpaque(self, px):
  # 不透明
  return px[3] >= 255 * self.config["opaque"]

 def getVerticalLineOffsetX(self, bgImage):
  # bgImage = Image.open("./image/bg.png")
  # bgImage.im.mode = 'RGBA'
  bgBytes = bgImage.load()

  x = 0
  while x < bgImage.size[0]:
   y = 0
   # 点》》线,灰度线条数量
   verticalLineCount = 0
   if x == 258:
    print(y)
   while y < bgImage.size[1]:
    px = bgBytes[x, y]
    r = px[0]
    g = px[1]
    b = px[2]
    # alph = px[3]
    # print(px)
    if self.isDarkStyle(r, g, b) and self.isGrayPx(r, g, b) and self.isOpaque(px):
     verticalLineCount += 1
    else:
     verticalLineCount = 0
     y += 1
     continue

    if verticalLineCount >= self.config["minVerticalLineCount"]:
     # 连续多个像素都是灰度像素,直线
     # print(x, y)
     return x

    y += 1

   x += 1
  pass


if __name__ == '__main__':
 bgImage = Image.open("./image/bg.png")
 veriImageUtil = VeriImageUtil()

 # veriImageUtil.updateConfig({
 #  "grayOffset": 20,
 #  "opaque": 0.6,
 #  "minVerticalLineCount": 10
 # })
  bgOffsetX = veriImageUtil.getVerticalLineOffsetX(bgImage)
 print("bgOffsetX:{} ".format(bgOffsetX))

总结

以上所述是小编给大家介绍的Python破解BiliBili滑块验证码的思路详解(完美避开人机识别),希望对大家有所帮助!

Python 相关文章推荐
Django框架下在URLconf中指定视图缓存的方法
Jul 23 Python
python+selenium实现京东自动登录及秒杀功能
Nov 18 Python
Python编程实现的简单神经网络算法示例
Jan 26 Python
解决python3爬虫无法显示中文的问题
Apr 12 Python
python3.6.3+opencv3.3.0实现动态人脸捕获
May 25 Python
python实现词法分析器
Jan 31 Python
python生成每日报表数据(Excel)并邮件发送的实例
Feb 03 Python
Python numpy线性代数用法实例解析
Nov 15 Python
Pandas时间序列重采样(resample)方法中closed、label的作用详解
Dec 10 Python
Python实现猜年龄游戏代码实例
Mar 25 Python
Django配置Bootstrap, js实现过程详解
Oct 13 Python
浅谈Python3中datetime不同时区转换介绍与踩坑
Aug 02 Python
Tensorflow 实现将图像与标签数据转化为tfRecord文件
Feb 17 #Python
将自己的数据集制作成TFRecord格式教程
Feb 17 #Python
tensorflow 实现数据类型转换
Feb 17 #Python
Django Haystack 全文检索与关键词高亮的实现
Feb 17 #Python
python使用docx模块读写docx文件的方法与docx模块常用方法详解
Feb 17 #Python
python itsdangerous模块的具体使用方法
Feb 17 #Python
django-crontab实现服务端的定时任务的示例代码
Feb 17 #Python
You might like
MOTOROLA 摩托罗拉 MODEL 66-XI五灯中波收音机
2021/03/02 无线电
Yii扩展组件编写方法实例分析
2015/06/29 PHP
PHP实现上传文件并存进数据库的方法
2015/07/16 PHP
PHP创建word文档的方法(平台无关)
2016/03/29 PHP
php结合redis高并发下发帖、发微博的实现方法
2016/12/15 PHP
php使用Jpgraph创建折线图效果示例
2017/02/15 PHP
PHP7下协程的实现方法详解
2017/12/17 PHP
解决laravel上传图片之后,目录有图片,但是访问不到(404)的问题
2019/10/14 PHP
给moz-firefox下添加IE方法和属性
2007/04/10 Javascript
jQuery 使用手册(二)
2009/09/23 Javascript
javascript使用百度地图api和html5特性获取浏览器位置
2014/01/10 Javascript
微信WeixinJSBridge API使用实例
2015/05/25 Javascript
js实现文本框选中的方法
2015/05/26 Javascript
跟我学习javascript的最新标准ES6
2015/11/20 Javascript
JS加载iFrame出现空白问题的解决办法
2016/05/13 Javascript
JavaScript mixin实现多继承的方法详解
2017/03/30 Javascript
VueJS组件之间通过props交互及验证的方式
2017/09/04 Javascript
微信小程序bindinput与bindsubmit的区别实例分析
2019/04/17 Javascript
VUE前后端学习tab写法实例
2019/08/06 Javascript
JS回调函数 callback的理解与使用案例分析
2019/09/09 Javascript
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
2014/06/10 Python
python dict.get()和dict['key']的区别详解
2016/06/30 Python
在Django的View中使用asyncio的方法
2019/07/12 Python
使用Nibabel库对nii格式图像的读写操作
2020/07/01 Python
python 绘制国旗的示例
2020/09/27 Python
分布式全文检索引擎ElasticSearch原理及使用实例
2020/11/14 Python
纽约家具、家居装饰和地毯店:ABC Carpet & Home
2017/06/21 全球购物
YesBabyOnline美国:全球性的在线婚纱礼服工厂
2018/05/05 全球购物
美国在线自行车商店:Jenson USA
2018/05/22 全球购物
高中毕业生自我鉴定例文
2013/12/29 职场文书
商场消防演习方案
2014/02/12 职场文书
篮球赛口号
2014/06/18 职场文书
2014县委书记四风对照检查材料思想汇报
2014/09/21 职场文书
国际贸易本科毕业生求职信
2014/09/26 职场文书
工程技术负责人岗位职责
2015/04/13 职场文书
城南旧事观后感
2015/06/11 职场文书