python模拟登录新浪微博自动获得调用新浪api所需的code
![](http://static.blog.csdn.net/images/category_icon.jpg)
版权声明:本文为博主原创文章,未经博主允许不得转载。
用这篇文章来记录一下从头到尾调用新浪api的过程
一、安装api
第一步肯定是要先安装新浪微博的库,安装了pip的同学直接在cmd中执行
- pip install weibo
便可安装成功
二、获得OAuth2.0的授权
授权机制如下图所示
![](http://www.sinaimg.cn/blog/developer/wiki/oAuth2_01.gif)
该链接中有介绍:点击打开链接
首先我们需要App key和App Secret,这两个创建一个sina应用便会发送给你
接着我们调用weibo库中的APIClient函数便可获得授权页面:
- url= APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri =CALLBACK_URL).get_authorize_url()
一般情况下我们获得授权页面之后手动输入到浏览器再登录便可获得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)
调用方式为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受限之后我们可以创建多个新浪帐号多个应用,获得多个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]
接着我们来看第二条post请求
第二条请求向https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=1450667802929发送一个表单
第二条请求向https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=1450667802929发送一个表单
其中servertime、nonce、pubket和rsakv便是我们在上一个get请求中得到的,su就是加密过后的帐号,sp就是加密过后的密码
su的加密方式是base64,先安装一个base64的库,然后调用如下函数:
- su=base64.encodestring(username)[:-1]
- 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进制。
发送完这个请求之后服务器会返回一个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代码中给出了
其中client_id是我们的APP_KEY;redirect_url是我们的回调页面,就是我们一开始建立应用时设置的;regCallback具体我不知道是哪来的,但是其中有两个变量,一个是APP_KEY,一个就是我们设置的回调页面;其它的表单内容都是固定的。请求代码如下:
最后在从响应成功的get_code_url将code值分析出来即可
- 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)
- code=get_code_url.url[47:]