Python爬虫破解登陆哔哩哔哩的方法


Posted in Python onNovember 17, 2020

写在前面

作为一名找不到工作的爬虫菜鸡人士来说,登陆这一块肯定是个比较大的难题。
 从今天开始准备一点点对大型网站进行逐个登陆破解。加深自己爬虫水平。

环境搭建

  • Python 3.7.7环境,Mac电脑测试
  • Python内置库
  • 第三方库:rsa、urllib、requests

PC端登陆

全部代码:

'''PC登录哔哩哔哩'''
class Bilibili_For_PC():
  def __init__(self, **kwargs):
    for key, value in kwargs.items(): setattr(self, key, value)
    self.session = requests.Session()
    self.__initialize()
  '''登录函数'''
  def login(self, username, password, crack_captcha_func=None, **kwargs):
    # 若参数中给入代理,则设置
    self.session.proxies.update(kwargs.get('proxies', {}))
    # 是否需要验证码
    is_need_captcha = False
    while True:
      # 需要验证码
      if is_need_captcha:
        captcha_img = self.session.get(self.captcha_url, headers=self.captcha_headers).content
        data = {'image': base64.b64encode(captcha_img).decode('utf-8')}
        captcha = self.session.post(self.crack_captcha_url, json=data).json()['message']
      # 获得key值
      appkey = '1d8b6e7d45233436'
      data = {
            'appkey': appkey,
            'sign': self.__calcSign('appkey={}'.format(appkey))
          }
      response = self.session.post(self.getkey_url, data=data)
      response_json = response.json()
      key_hash = response_json['data']['hash']
      pub_key = rsa.PublicKey.load_pkcs1_openssl_pem(response_json['data']['key'].encode('utf-8'))
      # 模拟登录
      if is_need_captcha:
        data = "access_key=&actionKey=appkey&appkey={}&build=6040500&captcha={}&challenge=&channel=bili&cookies=&device=pc&password={}&permission=ALL&seccode=&subid=1&ts={}&username={}&validate=" \
            .format(appkey, captcha, urllib.parse.quote_plus(base64.b64encode(rsa.encrypt('{}{}'.format(key_hash, password).encode(), pub_key))), int(time.time()), urllib.parse.quote_plus(username))
      else:
        data = "access_key=&actionKey=appkey&appkey={}&build=6040500&captcha=&challenge=&channel=bili&cookies=&device=pc&password={}&permission=ALL&seccode=&subid=1&ts={}&username={}&validate=" \
            .format(appkey, urllib.parse.quote_plus(base64.b64encode(rsa.encrypt('{}{}'.format(key_hash, password).encode(), pub_key))), int(time.time()), urllib.parse.quote_plus(username))
      data = "{}&sign={}".format(data, self.__calcSign(data))
      response = self.session.post(self.login_url, data=data, headers=self.login_headers)
      response_json = response.json()
      # 不需要验证码, 登录成功
      if response_json['code'] == 0 and response_json['data']['status'] == 0:
        for cookie in response_json['data']['cookie_info']['cookies']:
          self.session.cookies.set(cookie['name'], cookie['value'], domain='.bilibili')
        print('[INFO]: Account -> %s, login successfully' % username)
        infos_return = {'username': username}
        infos_return.update(response_json)
        return infos_return, self.session
      # 需要识别验证码
      elif response_json['code'] == -105:
        is_need_captcha = True
      # 账号密码错误
      elif response_json['code'] == -629:
        raise RuntimeError('Account -> %s, fail to login, username or password error' % username)
      # 其他错误
      else:
        raise RuntimeError(response_json.get('message'))
  '''计算sign值'''
  def __calcSign(self, param, salt="560c52ccd288fed045859ed18bffd973"):
    sign = hashlib.md5('{}{}'.format(param, salt).encode('utf-8'))
    return sign.hexdigest()
  '''初始化'''
  def __initialize(self):
   # 登陆请求头
    self.login_headers = {'Content-type': 'application/x-www-form-urlencoded'}
    # 破解验证码请求头
    self.captcha_headers = {'Host': 'passport.bilibili.com'}
    # 获取key密钥URL
    self.getkey_url = 'https://passport.bilibili.com/api/oauth2/getKey'
    # 获取登陆URL
    self.login_url = 'https://passport.bilibili.com/api/v3/oauth2/login'
    # 获取验证码URL
    self.captcha_url = 'https://passport.bilibili.com/captcha'
    # 破解网站来自: https://github.com/Hsury/Bilibili-Toolkit
    # 破解验证码URL
    self.crack_captcha_url = 'https://bili.dev:2233/captcha'
    # 请求头都得加这个
    self.session.headers.update({'User-Agent': "Mozilla/5.0 BiliDroid/5.51.1 (bbcallen@gmail.com)"})

移动端登陆

移动端与PC端类似,网址URL差异以及请求头差异。在此不过多介绍。
 全部代码:

'''移动端登录B站'''
class Bilibili_For_Mobile():
  def __init__(self, **kwargs):
    for key, value in kwargs.items(): setattr(self, key, value)
    self.session = requests.Session()
    self.__initialize()
  '''登录函数'''
  def login(self, username, password, crack_captcha_func=None, **kwargs):
    self.session.proxies.update(kwargs.get('proxies', {}))
    # 是否需要验证码
    is_need_captcha = False
    while True:
      # 需要验证码
      if is_need_captcha:
        captcha_img = self.session.get(self.captcha_url, headers=self.captcha_headers).content
        data = {'image': base64.b64encode(captcha_img).decode('utf-8')}
        captcha = self.session.post(self.crack_captcha_url, json=data).json()['message']
      # 获得key值
      appkey = 'bca7e84c2d947ac6'
      data = {
            'appkey': appkey,
            'sign': self.__calcSign('appkey={}'.format(appkey))
          }
      response = self.session.post(self.getkey_url, data=data)
      response_json = response.json()
      key_hash = response_json['data']['hash']
      pub_key = rsa.PublicKey.load_pkcs1_openssl_pem(response_json['data']['key'].encode('utf-8'))
      # 模拟登录
      if is_need_captcha:
        data = "access_key=&actionKey=appkey&appkey={}&build=6040500&captcha={}&challenge=&channel=bili&cookies=&device=phone&mobi_app=android&password={}&permission=ALL&platform=android&seccode=&subid=1&ts={}&username={}&validate=" \
            .format(appkey, captcha, urllib.parse.quote_plus(base64.b64encode(rsa.encrypt('{}{}'.format(key_hash, password).encode(), pub_key))), int(time.time()), urllib.parse.quote_plus(username))
      else:
        data = "access_key=&actionKey=appkey&appkey={}&build=6040500&captcha=&challenge=&channel=bili&cookies=&device=phone&mobi_app=android&password={}&permission=ALL&platform=android&seccode=&subid=1&ts={}&username={}&validate=" \
            .format(appkey, urllib.parse.quote_plus(base64.b64encode(rsa.encrypt('{}{}'.format(key_hash, password).encode(), pub_key))), int(time.time()), urllib.parse.quote_plus(username))
      data = "{}&sign={}".format(data, self.__calcSign(data))
      response = self.session.post(self.login_url, data=data, headers=self.login_headers)
      response_json = response.json()
      # 不需要验证码, 登录成功
      if response_json['code'] == 0 and response_json['data']['status'] == 0:
        for cookie in response_json['data']['cookie_info']['cookies']:
          self.session.cookies.set(cookie['name'], cookie['value'], domain='.bilibili')
        print('[INFO]: Account -> %s, login successfully' % username)
        infos_return = {'username': username}
        infos_return.update(response_json)
        return infos_return, self.session
      # 需要识别验证码
      elif response_json['code'] == -105:
        is_need_captcha = True
      # 账号密码错误
      elif response_json['code'] == -629:
        raise RuntimeError('Account -> %s, fail to login, username or password error' % username)
      # 其他错误
      else:
        raise RuntimeError(response_json.get('message'))
  '''计算sign值'''
  def __calcSign(self, param, salt="60698ba2f68e01ce44738920a0ffe768"):
    sign = hashlib.md5('{}{}'.format(param, salt).encode('utf-8'))
    return sign.hexdigest()
  '''初始化'''
  def __initialize(self):
    self.login_headers = {
                'Content-type': 'application/x-www-form-urlencoded'
              }
    self.captcha_headers = {
                'Host': 'passport.bilibili.com'
              }
    self.getkey_url = 'https://passport.bilibili.com/api/oauth2/getKey'
    self.login_url = 'https://passport.bilibili.com/api/v3/oauth2/login'
    self.captcha_url = 'https://passport.bilibili.com/captcha'
    # 破解网站来自: https://github.com/Hsury/Bilibili-Toolkit
    self.crack_captcha_url = 'https://bili.dev:2233/captcha'
    self.session.headers.update({'User-Agent': "Mozilla/5.0 BiliDroid/5.51.1 (bbcallen@gmail.com)"})

到此这篇关于Python爬虫破解登陆哔哩哔哩的方法的文章就介绍到这了,更多相关Python爬虫破解登陆内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python抽象类的新写法
Jun 18 Python
python语言使用技巧分享
May 31 Python
Python中pillow知识点学习
Apr 30 Python
详解用TensorFlow实现逻辑回归算法
May 02 Python
Python subprocess模块功能与常见用法实例详解
Jun 28 Python
pyttsx3实现中文文字转语音的方法
Dec 24 Python
Flask框架钩子函数功能与用法分析
Aug 02 Python
pytorch 在网络中添加可训练参数,修改预训练权重文件的方法
Aug 17 Python
python操作cfg配置文件方式
Dec 22 Python
python爬虫构建代理ip池抓取数据库的示例代码
Sep 22 Python
教你漂亮打印Pandas DataFrames和Series
May 29 Python
python接口测试返回数据为字典取值方式
Feb 12 Python
appium+python自动化配置(adk、jdk、node.js)
Nov 17 #Python
python调用百度API实现人脸识别
Nov 17 #Python
详解利用python识别图片中的条码(pyzbar)及条码图片矫正和增强
Nov 17 #Python
详解Pytorch显存动态分配规律探索
Nov 17 #Python
Python调用ffmpeg开源视频处理库,批量处理视频
Nov 16 #Python
python tkinter实现连连看游戏
Nov 16 #Python
详解python os.path.exists判断文件或文件夹是否存在
Nov 16 #Python
You might like
PHP 面向对象 final类与final方法
2010/05/05 PHP
php设计模式 Interpreter(解释器模式)
2011/06/26 PHP
解析PHP缓存函数的使用说明
2013/05/10 PHP
php生成动态验证码gif图片
2015/10/19 PHP
PHP设计模式之工厂模式与单例模式
2016/09/28 PHP
php使用GD2绘制几何图形示例
2017/02/15 PHP
PHP实现的mongoDB数据库操作类完整实例
2018/04/10 PHP
JavaScript RegExp方法获取地址栏参数(面向对象)
2009/03/10 Javascript
Js 刷新框架页的代码
2010/04/13 Javascript
基于JQuery的动态删除Table表格的行和列的代码
2011/05/12 Javascript
ASP.NET jQuery 实例2 (表单中使用回车在TextBox之间向下移动)
2012/01/13 Javascript
JQuery for与each性能比较分析
2013/05/14 Javascript
JQuery教学之性能优化
2014/05/14 Javascript
js 通过html()及text()方法获取并设置p标签的显示值
2014/05/14 Javascript
JavaScript包装对象使用详解
2015/07/09 Javascript
极力推荐一款小巧玲珑的可视化编辑器bootstrap-wysiwyg
2016/05/27 Javascript
利用Angularjs和Bootstrap前端开发案例实战
2016/08/27 Javascript
NODE.JS跨域问题的完美解决方案
2016/10/20 Javascript
JavaScript实现格式化字符串函数String.format
2016/12/16 Javascript
JS组件系列之MVVM组件构建自己的Vue组件
2017/04/28 Javascript
基于JS判断对象是否是数组
2020/01/10 Javascript
python实现在windows下操作word的方法
2015/04/28 Python
Python单例模式的两种实现方法
2017/08/14 Python
使用pandas读取csv文件的指定列方法
2018/04/21 Python
python字符串常用方法
2018/06/14 Python
Django添加KindEditor富文本编辑器的使用
2018/10/24 Python
Django 实现 Websocket 广播、点对点发送消息的代码
2020/06/03 Python
如何在C# winform中异步调用web services
2015/09/21 面试题
区域总监的岗位职责
2013/11/21 职场文书
党员十八大心得体会
2014/09/12 职场文书
2014年村官工作总结
2014/11/24 职场文书
安全教育观后感
2015/06/17 职场文书
总经理年会致辞
2015/07/29 职场文书
当你找不到方向的时候,不妨读读刘备的一生
2019/08/05 职场文书
Go标准容器之Ring的使用说明
2021/05/05 Golang
解决springboot druid数据库连接失败后一直重连的方法
2022/04/19 Java/Android