在Python中用Request库模拟登陆(四):哔哩哔哩(有加密,有验证码)

 !已失效!

抓包分析

获取验证码html

获取加密公钥web

其中hash是变化的,公钥key不变ajax

登陆json

其中用户名没有被加密,密码被加密。浏览器

由于在获取公钥的时候同时返回了一个hash值,推测此hash值与密码加密有关。session

经过谷歌浏览器控制台分析js代码

 右键登陆按钮,检查,查看 Event Listeners ,点击a.btn.btn-login右边的login.4f030c3....js:6查看js代码。dom

点击左下角的{}展开代码async

由于获取公钥和hash的连接中有action=getkey,尝试在源代码中搜索getkey,因而找到这样一个函数:函数

 1 encryptPassword: function (e, t) {
 2     var n = this,
 3     r = !1;
 4     return $.ajax({
 5         url: "https://passport.bilibili.com/login?act=getkey&r=" + Math.random(),
 6         async: !1
 7     }).done(function (t) {
 8         t && t.error && (n.publicTip = "登陆失败,服务端出现异常", e = null);
 9         var i = new JSEncrypt;
10         i.setPublicKey(t.key);
11         var a = i.encrypt(t.hash + e);
12         e = a,
13         r = !0
14     }),
15     r ? e : ""
16 }

 观察第十、11行,可知hash和变量e相加后被RSA加密,如今须要肯定e是什么。在第11行代码所在的位置设置一个断点,输入用户名密码验证码以后点击登陆,在这里密码框输入的是‘mypassword’post

点击e就会显示出e的值,看来e就是密码明文。

因而,能够猜想,加密的过程是:密码字符串前面串接hash值,而后进行RSA加密。下面经过测试检查猜想是否正确。

模拟登陆

每一次请求的headers都彻底复制抓包的内容。

1.获取验证码

1 def get_code():
2     url='https://passport.bilibili.com/captcha?r=0.1265352187487443'
3     headers={复制抓包到的headers}
4     session.headers.clear()
5     session.headers.update(headers)
6     r=session.get(url)
7     file=open('code.jpg','wb')
8     file.write(r.content)
9     file.close()

2.getkey

1 def get_key():
2     url='https://passport.bilibili.com/login?act=getkey&r=0.4365052982637341'
3     headers={复制抓包到的headers}
4     session.headers.clear()
5     session.headers.update(headers)
6     r=session.get(url)
7     jsondata=json.loads(r.text)
8     #hash变化,key不变
9     return (jsondata['hash'],jsondata['key'])

3.加密,具体能够参考博客园的模拟登陆的附录部分

1 def encrypt(Hash,key,password):
2     from Crypto.PublicKey import RSA
3     from Crypto.Cipher import PKCS1_v1_5
4     from base64 import b64encode
5     encryptor=PKCS1_v1_5.new(RSA.importKey(bytes(key,'utf-8')))
6     return str(b64encode(encryptor.encrypt(bytes(Hash+password,'utf-8'))),'utf-8')

4.登陆

 1 def login(code,username,password):
 2     #注意,在登陆页面中验证码会自动转成大写
 3     url='https://passport.bilibili.com/web/login'
 4     headers={复制抓包到的headers}
 5     data={'cType':'2',
 6           'vcType':'1',
 7           'captcha':code,
 8           'user':username,
 9           'pwd':password,
10           'keep':'true',
11           'gourl':'http://www.bilibili.com/'}
12     session.headers.clear()
13     session.headers.update(headers)
14     r=session.post(url,data=data)
15     return r.text

若是登陆成功,将返回 "code":0

5.测试

testurl='https://www.bilibili.com/account/dynamic'

在未登陆时,testurl的标题为“bilibili - 提示”,登陆时标题为“哔哩哔哩 (゜-゜)つロ 干杯~-bilibili”

session.headers.clear()
r=session.get(testurl)
p=r.text.find('<title>')+len('<title>')
print(r.text[p:r.text.find('<',p)])
相关文章
相关标签/搜索