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编程之变量赋值操作实例分析
Jul 24 Python
python删除某个字符
Mar 19 Python
Python 按字典dict的键排序,并取出相应的键值放于list中的实例
Feb 12 Python
windows下numpy下载与安装图文教程
Apr 02 Python
python装饰器常见使用方法分析
Jun 26 Python
在Django下测试与调试REST API的方法详解
Aug 29 Python
python xlwt如何设置单元格的自定义背景颜色
Sep 03 Python
python可视化实现KNN算法
Oct 16 Python
Python利用Scrapy框架爬取豆瓣电影示例
Jan 17 Python
Python实现文本文件拆分写入到多个文本文件的方法
Apr 18 Python
Python学习之os包使用教程详解
Mar 21 Python
Python Pandas解析读写 CSV 文件
Apr 11 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
解析阿里云ubuntu12.04环境下配置Apache+PHP+PHPmyadmin+MYsql
2013/06/26 PHP
从PHP的源码中深入了解stdClass类
2014/04/18 PHP
php 微信公众平台开发模式实现多客服的实例代码
2016/11/07 PHP
列表内容的选择
2006/06/30 Javascript
JS创建优美的页面滑动块效果 - Glider.js
2007/09/27 Javascript
NodeJS Express框架中处理404页面一个方式
2014/05/28 NodeJs
使用jspdf生成pdf报表
2015/07/03 Javascript
学习JavaScript设计模式(接口)
2015/11/26 Javascript
简单介绍JavaScript数据类型之隐式类型转换
2015/12/28 Javascript
Angularjs的启动过程分析
2017/07/18 Javascript
微信小程序实现打开内置地图功能【附源码下载】
2017/12/07 Javascript
代码详解JS操作剪贴板
2018/02/11 Javascript
React学习笔记之高阶组件应用
2018/06/02 Javascript
vue-cli安装使用流程步骤详解
2018/11/08 Javascript
微信小程序 如何获取网络状态
2019/07/26 Javascript
Vue 实现登录界面验证码功能
2020/01/03 Javascript
python实现查找两个字符串中相同字符并输出的方法
2015/07/11 Python
python实现飞机大战微信小游戏
2020/03/21 Python
Python3.6中Twisted模块安装的问题与解决
2019/04/15 Python
利用anaconda保证64位和32位的python共存
2021/03/09 Python
Pycharm简单使用教程(入门小结)
2019/07/04 Python
Python通过VGG16模型实现图像风格转换操作详解
2020/01/16 Python
利用django创建一个简易的博客网站的示例
2020/09/29 Python
Smallable意大利家庭概念店:设计师童装及家居装饰
2018/01/08 全球购物
俄罗斯童装网上商店:BebaKids
2020/06/06 全球购物
大学生毕业自我评价范文分享
2013/11/07 职场文书
房地产销售计划书
2014/01/10 职场文书
给校长的一封建议书
2014/03/12 职场文书
学雷锋宣传标语
2014/06/25 职场文书
医院义诊活动总结
2014/07/04 职场文书
父亲节寄语大全
2015/02/27 职场文书
关于环保的宣传稿
2015/07/23 职场文书
六年级作文之关于梦
2019/10/22 职场文书
pdf论文中python画的图Type 3 fonts字体不兼容的解决方案
2021/04/24 Python
mysql中between的边界,范围说明
2021/06/08 MySQL
深入浅出的讲解:信号调制到底是如何实现的
2022/02/18 无线电