在使用新浪微博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
在获取用户授权后,即可调用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下载: