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 相关文章推荐
linux系统使用python监控apache服务器进程脚本分享
Jan 15 Python
Python实现的简单文件传输服务器和客户端
Apr 08 Python
在Linux系统上通过uWSGI配置Nginx+Python环境的教程
Dec 25 Python
Python学习小技巧之列表项的拼接
May 20 Python
python 如何快速找出两个电子表中数据的差异
May 26 Python
Python基于PyGraphics包实现图片截取功能的方法
Dec 21 Python
python OpenCV GrabCut使用实例解析
Nov 11 Python
Python 简单计算要求形状面积的实例
Jan 18 Python
python 中的paramiko模块简介及安装过程
Feb 29 Python
记一次pyinstaller打包pygame项目为exe的过程(带图片)
Mar 02 Python
解决python脚本中error: unrecognized arguments: True错误
Apr 20 Python
通过实例简单了解Python sys.argv[]使用方法
Aug 04 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
星际争霸任务指南——神族
2020/03/04 星际争霸
PHP与Java进行通信的实现方法
2013/10/21 PHP
PHP设计模式之观察者模式实例
2016/02/22 PHP
PHP调用API接口实现天气查询功能的示例
2017/09/21 PHP
在 PHP 和 Laravel 中使用 Traits的方法
2019/11/13 PHP
window.onload 加载完毕的问题及解决方案(上)
2009/07/09 Javascript
js中键盘事件实例简析
2015/01/10 Javascript
JavaScript通过this变量快速找出用户选中radio按钮的方法
2015/03/23 Javascript
JS动态添加iframe的代码
2015/09/14 Javascript
JS+DIV+CSS排版布局实现美观的选项卡效果
2015/10/10 Javascript
JS数组操作(数组增加、删除、翻转、转字符串、取索引、截取(切片)slice、剪接splice、数组合并)
2016/05/20 Javascript
js数组常用操作方法小结(增加,删除,合并,分割等)
2016/08/02 Javascript
JavaScript制作颜色反转小游戏
2016/09/25 Javascript
js制作支付倒计时页面
2016/10/21 Javascript
原生JS控制多个滚动条同步跟随滚动效果
2017/12/22 Javascript
Angular 中使用 FineReport不显示报表直接打印预览
2019/08/21 Javascript
Jquery使用each函数实现遍历及数组处理
2020/07/14 jQuery
在Python中操作字符串之replace()方法的使用
2015/05/19 Python
python检查URL是否正常访问的小技巧
2017/02/25 Python
Python使用pickle模块存储数据报错解决示例代码
2018/01/26 Python
python构建深度神经网络(续)
2018/03/10 Python
Python拼接字符串的7种方式详解
2020/03/19 Python
python中封包建立过程实例
2021/02/18 Python
HTML5使用drawImage()方法绘制图像
2014/06/23 HTML / CSS
Farfetch香港官网:汇集全球时尚奢侈品购物平台
2017/11/26 全球购物
西班牙家用电器和电子产品购物网站:Mi Electro
2019/02/25 全球购物
乐高奥地利官方商店:LEGO Shop AT
2019/07/16 全球购物
建筑设计师岗位职责
2013/11/18 职场文书
关于雷锋的演讲稿
2014/05/10 职场文书
出国留学自荐信模板
2015/03/06 职场文书
公司人事任命通知
2015/04/20 职场文书
道歉信怎么写
2015/05/12 职场文书
运动会加油稿30字
2015/07/21 职场文书
微信小程序实现拍照和相册选取图片
2021/05/09 Javascript
jupyter notebook保存文件默认路径更改方法汇总(亲测可以)
2021/06/09 Python
Python 匹配文本并在其上一行追加文本
2022/05/11 Python