python模拟登录新浪微博自动获得调用新浪api所需的code

用这篇文章来记录一下从头到尾调用新浪api的过程


一、安装api

第一步肯定是要先安装新浪微博的库,安装了pip的同学直接在cmd中执行

pip install weibo

便可安装成功

二、获得OAuth2.0的授权

授权机制如下图所示
python模拟登录新浪微博自动获得调用新浪api所需的code_第1张图片
该链接中有介绍:点击打开链接
首先我们需要App key和App Secret,这两个创建一个sina应用便会发送给你
接着我们调用weibo库中的APIClient函数便可获得授权页面:
url= APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri =CALLBACK_URL).get_authorize_url()
CALLBACK_URL是在新建一个sina应用的时候就可以设定的,我们一般将它设为如下:
https://api.weibo.com/oauth2/default.html

一般情况下我们获得授权页面之后手动输入到浏览器再登录便可获得code值,再调用如下函数便可开始调用api了:
request = client.request_access_token(code, CALLBACK_URL)
access_token = request.access_token
expires_in = request.expires_in
client.set_access_token(access_token, expires_in)
调用api的方式很简单,用授权的client调用即可,api的函数名即是将 新浪api中的名字的斜杠换成双下划线
如statuses/public_timeline->statuses__public_timeline
调用方式为client.statuses__public_timeline(),其中的参数参考api文档

三、自动获得code

想要自动获得code值就是要解决如何获得授权界面之后的登录问题,这个问题也困扰了我很久
起初我是手动登录第一次,然后直接用chrome查看发送的请求,将其中的cookies复制下来,每次直接发送get请求获得回调网页获得code值,如下:
get_code_url=requests.get(url,cookies=cook).url
code=get_code_url.url[47:]
这方法老实说十分方便,不用分析太多新浪登录的方法,但当我调用api次数受限制之后,这个方法又不管用了
当一个应用的调用api受限之后我们可以创建多个新浪帐号多个应用,获得多个App key和App Secret反复调用,这样就一定要解决如何自动登录新浪获取code的问题
首先我们要分析新浪微博的登录过程,我用chrome、edge、ie还是fiddler4都不能完全抓取完整登录过程,最后试了firefox才成功抓去了整个登录的过程
虽然只输入了一次帐号密码但是发送了两次post请求

我们逐条请求来分析一下:
第一条get请求是在我们输入完新浪帐号之后就发送了,他向https://login.sina.com.cn/sso/prelogin.php?entry=openapi&callback=sinaSSOController.preloginCallBack&su=sxOTk0NjEwJTQwcXEuY&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.15)&_=1450667794267发送我们的帐号信息(su=sxOTk0NjEwJTQwcXEuY 这个帐号是base64加密过后的用户名,后面会讲如何实现,我随便改的,大家知道意思就好)
请求成功之后服务器会给我们返回一段信息,其中有我们在后面会用到的参数

sinaSSOController.preloginCallBack({"retcode":0,"servertime":1450667800,"pcid":"gz-fee1d39aaf203ccc63dc783a13ccce11413a","nonce":"1HRSQP","pubkey":"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443","rsakv":"1330428213","is_openlock":0,"showpin":0,"exectime":18})
其中servertime、nonce、pubket和rsakv这几个值是我们后面需要的,我们需要将其解析出来:
get_arg=requests.get(get_arg_url)
get_arg_content=get_arg.content
get_arg_content_split=get_arg_content.split(',')
servertime=get_arg_content_split[1].split(':')[1]
nonce=get_arg_content_split[3].split(':')[1][1:-1]
pubkey=get_arg_content_split[4].split(':')[1][1:-1]
rsakv=get_arg_content_split[5].split(':')[1][1:-1]
这个get_arg_url就是我上面说的那个请求url

接着我们来看第二条post请求
第二条请求向https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=1450667802929发送一个表单
python模拟登录新浪微博自动获得调用新浪api所需的code_第2张图片
其中servertime、nonce、pubket和rsakv便是我们在上一个get请求中得到的,su就是加密过后的帐号,sp就是加密过后的密码
su的加密方式是base64,先安装一个base64的库,然后调用如下函数:
su=base64.encodestring(username)[:-1]
密码的加密方式要稍微复杂一点,还要用到servertime、nonce、 pubket和rsakv:
rsaPublickey = int(pubkey, 16)
key = rsa.PublicKey(rsaPublickey, 65537) #创建公钥
message = str(servertime) + '\t' + str(nonce) + '\n' + str(password) 
sp = rsa.encrypt(message, key) #加密
sp = binascii.b2a_hex(sp) #将加密信息转换为16进制。
密码的加密需要用到binascii库和rsa库
发送完这个请求之后服务器会返回一个JSON数据,其中有一个ticket是我们待会儿要用到的

请求并获得ticket代码如下:
postPara = {
        'entry': 'openapi',
        'gateway': '1',
        'from':'',
        'savestate': '0',
        'userticket': '1',
        'pagerefer':'',
        'ct': '1800',
        's':'1',
        'vsnf': '1',
        'vsnval': '',
        'door':'',
        'appkey':'52laFx',
        'su': su,
        'service': 'miniblog',
        'servertime': servertime,
        'nonce': nonce,
        'pwencode': 'rsa2',
        'rsakv' : rsakv,
        'sp': sp,
        'sr':'1920*1080',
        'encoding': 'UTF-8',
        'cdult':'2',
        'domain':'weibo.com',
        'prelt':'2140',
        'returntype': 'TEXT',
    }
    get_ticket_url='https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=1450667802929'
    req=requests.post(get_ticket_url,postPara)
    print req.content
    ticket=req.content.split(',')[1].split(':')[1][1:-1]

然后是第三条请求
第三条请求仍然是post请求,向https://api.weibo.com/oauth2/authorize发的请求,这一个表单的内容就是直接在html代码中给出了
python模拟登录新浪微博自动获得调用新浪api所需的code_第3张图片
其中client_id是我们的APP_KEY;redirect_url是我们的回调页面,就是我们一开始建立应用时设置的;regCallback具体我不知道是哪来的,但是其中有两个变量,一个是APP_KEY,一个就是我们设置的回调页面;其它的表单内容都是固定的。请求代码如下:
fields={
    'action': 'login',
    '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='+APP_KEY+'&response_type=code&display=default&redirect_uri='+CALLBACK_URL+'&from=&with_cookie=',
    'redirect_uri':CALLBACK_URL,
    'client_id':APP_KEY,
    'appkey62': '52laFx',
    'state': '',
    'verifyToken': 'null',
    'from': '',
    'switchLogin':'0',
    'userId':'',
    'passwd':''
    }
headers = {
    "User-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0",
           "Referer": url,
           "Content-Type": "application/x-www-form-urlencoded"}
post_url='https://api.weibo.com/oauth2/authorize'
get_code_url=requests.post(post_url,data=fields,headers=headers)
最后在从响应成功的get_code_url将code值分析出来即可
code=get_code_url.url[47:]
这样我们就成功自动的获取了code值

如果有什么不懂的问题可以微博私信我

你可能感兴趣的:(python)