新浪微博自动登录脚本

sddtc 于 2017-04-25 发布

背景

使用过weibo第三方登录api的人都知道在获取code值时,一般都需要手动打开浏览器获得跳转之后的地址,例如

https://www.sddtc.florist/?code=2156b2ef6161df36a27464728bb40e77

因为单纯用

response = urllib2.urlopen(request)

这样的方式无法正常的跳转,为此我曾保存过一个博主byrain的博文,他可以自动获取code的值,然而今天查看书签的时候突然发现他的博客更换主题文章都404了,于是想在此记录他曾记录的片段.

获取方法

sina的登陆采取了RSA2加密的方式

一、用户名密码加密

# encode username
def get_username(user_id):
    user_id_ = urllib.quote(user_id)  
    su = base64.encodestring(user_id_)[:-1]
    return su

#encode password
def get_password_rsa(USER_PSWD, PUBKEY, servertime, nonce):
    rsa_pubkey = int(PUBKEY, 16) 
    key_1 = int('10001', 16) 
    key = rsa.PublicKey(rsa_pubkey, key_1)
    message = str(servertime) + "\t" + str(nonce) + "\n" + str(USER_PSWD)
    passwd = rsa.encrypt(message, key)
    passwd = binascii.b2a_hex(passwd)  # to 16
    return passwd

来源网络,可以看出对于username的加密很简单,但是对于password的加密,就用到了PUBKEY, servertime,nonce这几个参数.

二、参数获取

def get_parameter():
    name = con.USERID #set by your own
    password = con.PASSWD  #set by your own
    su = get_username(name)
    url = "https://login.sina.com.cn/sso/prelogin.php?entry=openapi&callback=sinaSSOController.preloginCallBack&su=" + su + "&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.15)"
    r = requests.get(url)
    p = re.compile('\((.*)\)')
    json_data = p.search(r.text).group(1)
    data = json.loads(json_data)
    PUBKEY = data['pubkey']
    servertime = str(data['servertime'])
    nonce = data['nonce']
    rsakv = str(data['rsakv'])
    sp = get_password_rsa(password, PUBKEY, servertime, nonce)
    return servertime, nonce, rsakv, sp, su

来源网络,采用正则将返回的内容分离,提取所需信息,同时需要获得额外的rsakv,供之后的登陆使用.

三、获取ticket

有了这几个参数后,就可以获得自动授权所需要的ticket.

def get_ticket():
    servertime, nonce, rsakv, sp, su = get_parameter()
    header = {
        'Accept': '*/*',
        'Accept-Encoding': 'gzip,deflate,sdch',
        'Accept-Language': 'zh,en-US;q=0.8,en;q=0.6,zh-TW;q=0.4,zh-CN;q=0.2',
        'Connection': 'keep-alive',
        'Content-Length': '565',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Host': 'login.sina.com.cn',
        'Origin': 'https://api.weibo.com',
        'Referer': 'https://api.weibo.com/oauth2/authorize?redirect_uri='
                   +con.CALL_BACK+'&response_type=code&client_id='+con.APP_KEY,
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 '
                      '(KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36'
    }
    content = {
        'entry': 'openapi',
        'gateway': '1',
        'from': None,
        'savestate': '0',
        'useticket': '1',
        'pagerefer': None,
        'ct': '1800',
        's': '1',
        'vsnf': '1',
        'vsnval': None,
        'door': None,
        'appkey': '3hXzQr',
        'su': su,
        'service': 'miniblog',
        'servertime': servertime,
        'nonce': nonce,
        'pwencode': 'rsa2',
        'rsakv': rsakv,
        'sp': sp,
        'sr': '1280*1024',
        'encoding': 'UTF-8',
        'cdult': '2',
        'domain': 'weibo.com',
        'prelt': '603',
        'returntype': 'TEXT'
    }
    url = 'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)'
    r = requests.post(url=url, headers=header, data=content)
    json_data = r.text
    data = json.loads(json_data)
    ticket = data['ticket']
    return ticket

post到server端的信息如上,然后获取返回的内容里就有ticket.

四、获得授权

def get_code():
    ticket = get_ticket()
    header = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Referer': 'https://api.weibo.com/oauth2/authorize?redirect_uri='
                   +con.CALL_BACK+'&response_type=code&client_id='+con.APP_KEY,
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 '
                      '(KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36'
    }
    content = {
        'action': 'submit',
        'display': 'default',
        'withOfficalFlag': '0',
        'quick_auth': 'null',
        'withOfficalAccount': '',
        'scope': '',
        'ticket': ticket,
        'isLoginSina': '',
        'response_type': 'code',
        'regCallback': 'https://api.weibo.com/2/oauth2/authorize?'
                       'client_id=' + con.APP_KEY +
                       '&response_type=code&display=default&redirect_uri=' +
                       con.CALL_BACK + '&from=&with_cookie=',
        'redirect_uri': con.CALL_BACK,
        'client_id': con.APP_KEY,
        'appkey62': '3hXzQr',
        'state': '',
        'verifyToken': 'null',
        'from': '',
        'switchLogin': '0',
        'userId': con.USERID,
        'passwd': ""
    }
    login_url = 'https://api.weibo.com/oauth2/authorize'
    r = requests.post(login_url, data=content, headers=header, allow_redirects=False)
    return_redirect_uri = r.headers['location']
    print return_redirect_uri
    code = return_redirect_uri[32:]
    return code

授权的页面和之前登陆的页面并不是一个.在POST https://api.weibo.com/oauth2/内容的时候,会重定向,所以需要在requests.post里添加allow_redirects=False参数,获得302的返回header里包括了包含code码的url,提取出来就OK啦.

使用说明

这部分代码有一些参数需要配置,包括APP_KEY,CLIENT_ID,USER_ID,USER_PASSWORD,都是需要在新浪微博的开发者平台注册
新浪微博机器人可见我的项目weiborobot,该项目在myConfig.py里面填写相应的参数值,是可以直接运行自动发微。

以上。