美文网首页
二、扫码登陆bilibili

二、扫码登陆bilibili

作者: ouczbs | 来源:发表于2018-09-29 20:33 被阅读0次

    考虑到B站移动滑块登陆比较难而且成功率一般
    故而采用了简单的二维码登陆
    至少常用的PC+手机的网站都支持二维码登录

    一、登陆流程
    先用浏览器F12找到和登录相关的url

    1、判断用户是否已经登录了

    Get https://account.bilibili.com/home/userInfo
    

    已登录则响应 code=0以及个人信息


    图片.png

    未登录则响应 code=-101


    图片.png
    2、获取二维码地址
    Get https://passport.bilibili.com/qrcode/getLoginUrl
    

    这个地址有两个作用
    一个是返回cookie值sid
    另一个是返回的url就是二维码的内容
    需要利用Python的qrcode库制作成二维码


    图片.png

    3、根据地址生成二维码并显示
    需要安装库qrcode和matplotlib

    pip install qrcode
    pip install matplotlib
    

    4、 循环判断是否扫码

    Post https://passport.bilibili.com/qrcode/getLoginInfo!
    data={
            'oauthKey':oauthKey,
            'gourl': 'https://passport.bilibili.com/account/security'
     }
    

    共有三种响应
    未扫码时返回
    {'status': False, 'data': -4, 'message': "Can't scan~"}
    已扫码时返回
    {'status': True,'ts': 1538296048,'data': {'url': ...''}}
    以及登录cookies
    二维码过期时返回
    {'status': False, 'data': -2, 'message': "Can't Match oauthKey~"}

    5、获取个人信息
    主要是获取uid
    小电视抽奖和连接直播弹幕时会用到

    Get https://api.live.bilibili.com/User/getUserInfo
    

    代码实现

    二、API层 api.py

    1. API应满足单例模式
      只能实例化一次,返回的都是同一个对象
    2. ajax 负责管理所有请求
      可以用于添加日志
    3. 添加Login类负责登录
      确定请求方法、请求地址、请求参数
    4. 添加统一接口类BilibiliAPI
      作为唯一的暴露给服务层的接口
    from utils import singleton
    def ajax(s,url,method='GET',data=None):
        if method=='GET':return http.get(s,url,data)
        else:return http.post(s,url,data)
    
    class Login():
        def isLogin(self,s):
            url="https://account.bilibili.com/home/userInfo"
            return ajax(s,url)
    
        def get_vdcode(self,s):
            url="https://passport.bilibili.com/qrcode/getLoginUrl"
            return ajax(s,url)
    
        def loop_vdcode(self,s,oauthKey):
            url="https://passport.bilibili.com/qrcode/getLoginInfo"
            data={
                    'oauthKey':oauthKey,
                    'gourl': 'https://passport.bilibili.com/account/security'
                }
            return ajax(s,url,'POST',data)
    @singleton
    class BilibiliAPI():pass
    BilibiliAPI.Login=Login()
    
    

    三、服务层 server.py
    设置响应类型
    负责调用api层
    决定api层响应结果的逻辑
    可以给主程序提供完整的登录服务

    from api import BilibiliAPI as API
    class Login():
        def __init__(self,s):
            self.s=s
            self.oauthKey=''
            self.s._type='json'
        def isLogin(self):
            r=API.Login.isLogin(self.s)
            if r['code']==-101:return False
            else:return self.get_info()
        def get_info(self):
            r=API.User.get_info(s)
            self.info=r['data']
            return True
        def get_vdcode(self):
            r=API.Login.get_vdcode(self.s)
            code_url=r['data']['url']
            img=self.make_vdcode(code_url)
            self.show_img(img)
            self.oauthKey=r['data']['oauthKey']
        def show_img(self,img):
            import matplotlib.pyplot as plt
            plt.imshow(img)  
            plt.show()
        def make_vdcode(self,code_url):
            import qrcode
            return qrcode.make(code_url)
        def loop_vdcode(self):
            import time
            r=API.Login.loop_vdcode(self.s,self.oauthKey)
            while not r['status']:
                time.sleep(1)
                r=API.Login.loop_vdcode(self.s,self.oauthKey)
                if r['data']==-2:
                    print('二维码已过期')
                    break
            if r['status']:self.info=r['data']
            return r['status']
    

    四、测试代码

    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0',
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Accept-Encoding': 'gzip, deflate, br',
        'Referer': 'https://live.bilibili.com/',
        'Origin': 'https://live.bilibili.com',
        'Connection': 'keep-alive'
        }
    s=session(headers,'cookie.txt')
    login=Login(s)
    while not login.isLogin():
        login.get_vdcode()
        login.loop_vdcode()
    s.save()
    

    保存后的cookie.txt

    #LWP-Cookies-2.0
    Set-Cookie3: DedeUserID=269938304; path="/"; domain=".bilibili.com"; path_spec; domain_dot; expires="2018-10-29 12:11:55Z"; version=0
    Set-Cookie3: DedeUserID__ckMd5=e3b81ec041161182; path="/"; domain=".bilibili.com"; path_spec; domain_dot; expires="2018-10-29 12:11:55Z"; version=0
    Set-Cookie3: SESSDATA="136e3f28%2C1540815115%2C4df7c156"; path="/"; domain=".bilibili.com"; path_spec; domain_dot; expires="2018-10-29 12:11:55Z"; HttpOnly=None; version=0
    Set-Cookie3: bili_jct=957f743c8c8ad984fc6d260f43963242; path="/"; domain=".bilibili.com"; path_spec; domain_dot; expires="2018-10-29 12:11:55Z"; version=0
    Set-Cookie3: sid=c5g6gj6d; path="/"; domain=".bilibili.com"; path_spec; domain_dot; expires="2019-09-29 12:12:11Z"; version=0
    

    相关文章

      网友评论

          本文标题:二、扫码登陆bilibili

          本文链接:https://www.haomeiwen.com/subject/ehcboftx.html