使用新浪微博API:创建Web应用

使用新浪微博API:创建SDK一文中,我们为编写Web应用准备好了SDK,并可在命令行中测试成功。现在,我们可以在Web网站中集成并调用新浪微博的API了。

微博登录

使用新浪微博API的第一步是让用户通过微博登陆。在您的网站放置一个“用微博帐号登录”的链接,该链接指向网站的一个URL,例如/signin。代码如下:

<a href="/signin"><img src="/static/i/signin.png" style="width: 239px;height: 48px" /></a>

效果如图所示:

weibo-signin-button

在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效果如图:

miniweibo

不过,仔细观察,我们输出的微博和新浪微博官网还有所不同,官网会把@和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('<', '&lt;').replace('>', '&gt;').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下载:

https://github.com/michaelliao/miniweibo