二、扫码登陆bilibili

考虑到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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容