Reference: http://lovenight.github.io/2015/11/23/Python-%E6%A8%A1%E6%8B%9F%E7%99%BB%E5%BD%95%E6%96%B0%E6%B5%AA%E5%BE%AE%E5%8D%9A/
登录页:http://login.sina.com.cn/signup/signin.php?entry=sso
抓包可找到登录网址:
https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15/)&_=1448285708709
最后一项是时间戳,经测试,可以直接删除。所以最终登录网址是:
https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)
POST提交的表单中,用户名需要base64编码。
完整登录代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
import requests import json import base64
def login(username, password): username = base64.b64encode(username.encode('utf-8')).decode('utf-8') postData = { "entry": "sso", "gateway": "1", "from": "null", "savestate": "30", "useticket": "0", "pagerefer": "", "vsnf": "1", "su": username, "service": "sso", "sp": password, "sr": "1440*900", "encoding": "UTF-8", "cdult": "3", "domain": "sina.com.cn", "prelt": "0", "returntype": "TEXT", } loginURL = r'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)' session = requests.Session() res = session.post(loginURL, data = postData) jsonStr = res.content.decode('gbk') info = json.loads(jsonStr) if info["retcode"] == "0": print("登录成功")
|
返回的session保存了登录状态,尽情做你做想做的事吧,配合微博API效果更佳。
网上搜索到的复杂方法
本节依赖的第三方库除了上面用过的requests
,还有用于加密的rsa
,需要另行安装。
登录流程
- 向如下网址提交GET请求,获取servertim、nonce、pubkey、rsakv,后两者是固定值。
http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.18))
- 加密用户名与密码
- 向如下网址提交POST请求:
http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18))
加密方式的破解找到一段方法,我没学过javascript,就没细看,直接照搬后面的加密方法。
获得以及查看新浪微博登录js文件:
查看新浪通行证url(http://login.sina.com.cn/signup/signin.php)的源代码,其中可以找到该js的地址http://login.sina.com.cn/js/sso/ssologin.js,不过打开后里面的内容是加密过的,可以在网上找个在线解密站点解密,查看最终用户名和密码的加密方式。
分步实现
获取servertim和nonce
直接在浏览器中访问:
http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.18))
未登录状态返回:
sinaSSOController.preloginCallBack({
"retcode": 0,
"servertime": 1448278360,
"pcid": "gz-8139fa256b150b7a42e09dbdc0b4ed2224eb",
"nonce": "RDY5SN",
"pubkey": "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443",
"rsakv": "1330428213",
"exectime": 9
})
取出括号里的JSON字符串提取信息:
1 2 3 4 5 6 7 8 9 10
|
def getLoginInfo(): preLoginURL = r'http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.18)' html = requests.get(preLoginURL).text jsonStr = re.findall(r'\((\{.*?\})\)', html)[0] data = json.loads(jsonStr) servertime = data["servertime"] nonce = data["nonce"] pubkey = data["pubkey"] rsakv = data["rsakv"] return servertime, nonce, pubkey, rsakv
|
加密用户名与密码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
def getSu(username): """加密用户名,su为POST中的用户名字段""" su = base64.b64encode(username.encode('utf-8')).decode('utf-8') return su
def getSp(password, servertime, nonce, pubkey): """加密密码,sp为POST中的用户名字段""" pubkey = int(pubkey, 16)
|
提交POST请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
def login(su, sp, servertime, nonce, rsakv): postData = { 'entry': 'weibo', 'gateway': '1', 'from': '', 'savestate': '7', 'userticket': '1', "pagerefer": "http://open.weibo.com/wiki/2/statuses/home_timeline", "vsnf": "1", "su": su, "service": "miniblog", "servertime": servertime, "nonce": nonce, "pwencode": "rsa2", "rsakv": rsakv, "sp": sp, "sr": "1440*900", "encoding": "UTF-8", "prelt": "126", "url": "http://open.weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack", "returntype": "META", } headers = { "User-Agent": "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36", "Accept-Encoding": "gzip, deflate", "Content-Type": "application/x-www-form-urlencoded", "Host": "login.sina.com.cn", "Origin": "http://open.weibo.com", "Referer": "http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E", "Upgrade-Insecure-Requests": "1", } loginURL = r'http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)' session = requests.Session() session.headers = headers res = session.post(loginURL, data=postData) html = res.content.decode('gbk') info = re.findall(r"location\.replace\(\'(.*?)\'", html)[0] if 'retcode=0' in info: print("登录成功!") else: print("登录失败!") return session
|
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
import requests import json import re import base64 import rsa import binascii
def getLoginInfo(): preLoginURL = r'http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.18)' html = requests.get(preLoginURL).text jsonStr = re.findall(r'\((\{.*?\})\)', html)[0] data = json.loads(jsonStr) servertime = data["servertime"] nonce = data["nonce"] pubkey = data["pubkey"] rsakv = data["rsakv"] return servertime, nonce, pubkey, rsakv
def getSu(username): """加密用户名,su为POST中的用户名字段""" su = base64.b64encode(username.encode('utf-8')).decode('utf-8') return su
def getSp(password, servertime, nonce, pubkey):
"""加密密码,sp为POST中的用户名字段""" pubkey = int(pubkey, 16) key = rsa.PublicKey(pubkey, 65537)
|