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 相关文章推荐
python赋值操作方法分享
Mar 23 Python
python求最大值最小值方法总结
Jun 25 Python
linux下安装python3和对应的pip环境教程详解
Jul 01 Python
Python爬虫学习之获取指定网页源码
Jul 30 Python
Window10下python3.7 安装与卸载教程图解
Sep 30 Python
keras 特征图可视化实例(中间层)
Jan 24 Python
python实现图像拼接
Mar 05 Python
tensorflow模型的save与restore,及checkpoint中读取变量方式
May 26 Python
解决python 执行sql语句时所传参数含有单引号的问题
Jun 06 Python
Python 实现进度条的六种方式
Jan 06 Python
深度学习小工程练习之垃圾分类详解
Apr 14 Python
Python Matplotlib绘制等高线图与渐变色扇形图
Apr 14 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
php生成缩略图的类代码
2008/10/02 PHP
php csv操作类代码
2009/12/14 PHP
PHP与jquery实时显示网站在线人数实例详解
2016/12/02 PHP
Yii框架实现的验证码、登录及退出功能示例
2017/05/20 PHP
Laravel框架中VerifyCsrfToken报错问题的解决
2017/08/30 PHP
php实现的支付宝网页支付功能示例【基于TP5框架】
2019/09/16 PHP
js类的静态属性和实例属性的理解
2009/10/01 Javascript
jquery实现预览提交的表单代码分享
2014/05/21 Javascript
使用js画图之圆、弧、扇形
2015/01/12 Javascript
jQuery实现拖动调整表格单元格大小的代码实例
2015/01/13 Javascript
Javascript设计模式之观察者模式的多个实现版本实例
2015/03/03 Javascript
JS获取时间的相关函数及时间戳与时间日期之间的转换
2016/02/04 Javascript
JS组件系列之Bootstrap table表格组件神器【终结篇】
2016/05/10 Javascript
AngularJS 简单应用实例
2016/07/28 Javascript
Vue开发过程中遇到的疑惑知识点总结
2017/01/20 Javascript
浅谈JavaScript作用域和闭包
2017/09/18 Javascript
原生JS实现小小的音乐播放器
2017/10/16 Javascript
Angular6项目打包优化的实现方法
2019/12/15 Javascript
JS数组方法join()用法实例分析
2020/01/18 Javascript
详解uniapp的全局变量实现方式
2021/01/11 Javascript
python实现解数独程序代码
2017/04/12 Python
python基础之包的导入和__init__.py的介绍
2018/01/08 Python
python实现生命游戏的示例代码(Game of Life)
2018/01/24 Python
python使用tensorflow深度学习识别验证码
2018/04/03 Python
python通过nmap扫描在线设备并尝试AAA登录(实例代码)
2019/12/30 Python
Python爬虫库BeautifulSoup的介绍与简单使用实例
2020/01/25 Python
Ajxa常见问题都有哪些
2014/03/26 面试题
工作室成员个人发展规划范文
2014/01/24 职场文书
《藤野先生》教学反思
2014/02/19 职场文书
《美丽的小兴安岭》教学反思
2014/02/26 职场文书
村干部承诺书
2014/03/28 职场文书
大学毕业谢师宴致辞
2015/07/27 职场文书
毕业生入职感言
2015/07/31 职场文书
师德培训心得体会2016
2016/01/09 职场文书
教师学期述职自我鉴定
2019/08/16 职场文书
分享Python获取本机IP地址的几种方法
2022/03/17 Python