在使用新浪微博API:创建SDK一文中,我们为编写Web应用准备好了SDK,并可在命令行中测试成功。现在,我们可以在Web网站中集成并调用新浪微博的API了。
使用新浪微博API的第一步是让用户通过微博登陆。在您的网站放置一个“用微博帐号登录”的链接,该链接指向网站的一个URL,例如/signin。代码如下:
<a href="/signin"><img src="/static/i/signin.png" style="width: 239px;height: 48px" /></a>
效果如图所示:
在URL映射的处理函数signing中,创建一个APIClient实例,然后调用get_authorize_url()方法获得新浪微博认证的URL,将用户重定向至该URL。代码如下:
def _create_client(): _APP_ID = '12345' _APP_SECRET = 'abc123xyz' _REDIRECT_URI = 'http://example.com/callback' return APIClient(_APP_ID, _APP_SECRET, _REDIRECT_URI) @get('/signin') def signin(): client = _create_client() # 重定向到新浪微博登陆页: raise seeother(client.get_authorize_url())
当用户在新浪微博的认证页中完成登录后,新浪微博将用户重定向到我们指定的redirect_uri,并附加参数code。处理redirect_uri的函数将提取参数code,然后,获取登录用户的access token。代码如下:
@get('/callback') def callback(): client = _create_client() r = client.request_access_token(ctx.request['code']) access_token, expires_in, uid = r.access_token, r.expires_in, r.uid
在获取access token的同时,新浪微博还将返回access token的过期时间和用户ID。SDK将过期时间转化成UNIX时间戳后返回。
获取到的access token就可以该登录用户的身份调用API,从而进一步获取用户详细资料。代码如下:
@get('/callback') def callback(): ... client.set_access_token(access_token, expires_in) user = client.users.show.get(uid=uid) logging.info(json.dump(user)) # { "uid": 1234, "screen_name": "Michael", … }
紧接着,网站要判断该用户是否是第一次访问,如果是,在数据库中创建一条记录,如果用户已存在,则更新用户的相关信息。由于uid是用户在新浪微博的唯一ID号,所以可作为主键保存用户信息。同时,将access token和过期时间一并存入数据库。代码如下:
@get('/callback') def callback(): ... if (_is_user_exist(uid)): _update_user(user, access_token, expires_in) else: _create_user(user, access_token, expires_in)
最后一步是在您的网站上通过session或cookie来标识用户已登录,然后,用户就可以以登录身份访问您的网站。
在获取用户授权后,即可调用API。例如,列出用户关注的微博列表,代码如下:
@get('/list') def list_weibo(): user = _user_from_session() client = _create_client() client.set_access_token(user.auth_token, user.expired_time) r = client.statuses.home_timeline.get() return Template('list.html', statuses = r.statuses)
在HTML模板里,您可以将JSON格式的statuses列表转化为HTML,代码如下:
L = [] for st in statuses: L.append(''' <div> <div><img src="%s" /></div> <div>%s</div> <div>%s</div> </div>''' % (st.user.profile_image_url, st.user.screen_name, st.text) print ''.join(L)
经过CSS处理后的最终HTML效果如图:
不过,仔细观察,我们输出的微博和新浪微博官网还有所不同,官网会把@和http开头的文本和#话题#变为超链接,如何处理@某某某,#话题#和链接?这里给出一个JavaScript的正则匹配解决方案,代码如下:
var g_all = /(\@[^\s\&\:\)\uff09\uff1a\@]+)|(\#[^\#]+\#)|(http\:\/\/[a-zA-Z0-9\_\/\.\-]+)/g; var g_at = /^\@[^\s\&\:\)\uff09\uff1a\@]+$/; var g_topic = /^\#[^\#]+\#$/; var g_link = /^http\:\/\/[a-zA-Z0-9\_\/\.\-]+$/; function format_text(t) { ss = t.replace('<', '<').replace('>', '>').split(g_all); L = [] $.each(ss, function(index, s) { if (s===undefined) return; if (g_at.test(s)) { L.push('<a href="http://weibo.com/n/' + s.substring(1) + '" target="_blank">' + s + '</a>'); } else if (g_topic.test(s)) { L.push('<a href="http://huati.weibo.com/k/' + s.substring(1, s.length-1) + '" target="_blank">' + s + '</a>'); } else if (g_link.test(s)) { L.push('<a href="' + s + '" target="_blank">' + s + '</a>'); } else { L.push(s); } }); return L.join(''); }
发布微博的API是statuses/update,该API需要通过POST调用。发布微博的代码如下:
@post('/update') def statuses_update(): text = ctx.request['text'] user = _user_from_session() client = _create_client() client.set_access_token(user.auth_token, user.expired_time) r = client.statuses.update.post(status=text) return True
本文演示网站:
http://sinaweibopy.sinaapp.com/
本文的网站源码可以从GitHub下载: