Django开发中整合新浪微博API

fmms 12年前

随着新浪微博用户日益增加,我们有时候会考虑在自己的网站中整合新浪微博。比如说我现在的独立博客。

在我的博客中做到整合主要就这几方面:我写一篇文章,就会同步发送至微博。同时呢,用户可以用微博帐号登录,并且可以选择把对文章的评论,同步评论到文章的微博。另外,用户可以选择是否把博客留言同步至新浪微博。

新浪微博开放平台地址在这里。文档地址在这里

首先要涉及的问题,就是用户用新浪微博帐号登录的问题,即授权机制。基本方法有两种:

  1. OAuth
  2. Basic auth(需要强调的是,微博开放平台将于6月1日正式停止Basic Auth的支持。因此,此种方法不作讨论了,其实需要用户名和密码的方式本身就不安全。)

OAuth新浪官方的文档在这里。想要了解OAuth技术说明的可以访问项目主页

其实,OAuth的流程还是很简单的。大致如下:

  1. 向API调用获得request token。
  2. 将用户重定向到授权页(auth url)。
  3. 用户输入用户名和密码完成授权。重定向到Callback_url。
  4. 用request token向新浪微博换取access token。
  5. 完成。

大致了解了OAuth的原理以后,由于我们是整合至Django,自然需要下载微博SDK的Python版

不过,在全部开始前,你得先向新浪微博申请你的应用。申请地址在这里。这里要强调的是,日后应用需要申请审核,因为只有审核通过后,在来源中才能显示个性的应用名。所以,在申请的时候,注意应用介绍信息的完整,以及应用分类的填写正确。(在本例中,我们的分类是合作网站。)

申请完成以后将会得到你的应用的App KeyApp Secret

回到授权用户登录的话题。允许新浪微博帐号接入,首先我们需要在urlpatterns中添加几个URL。如下:

urlpatterns = patterns('projectname.appname.views',      url(r'^log/$', 'login', name='log'),      url(r'^logincheck/$', 'login_check', name='logcheck'),      url(r'^logout/$', 'logout', name='logout'),  )

接着,我们开始views文件。代码:
#!/usr/bin/env python  # -*- coding: utf-8 -*-  """  基于django的新浪微博oauth views  需要django的session支持  """     from django.http import HttpResponseRedirect     from weibopy.auth import OAuthHandler, WeibopError  from weibopy import oauth     consumer_key = '' # 设置你申请的appkey  consumer_secret = '' # 设置你申请的appkey对于的secret     class WebOAuthHandler(OAuthHandler):         def get_authorization_url_with_callback(self, callback, signin_with_推ter=False):          """Get the authorization URL to redirect the user"""          try:              # get the request token              self.request_token = self._get_request_token()                 # build auth request and return as url              if signin_with_推ter:                  url = self._get_oauth_url('authenticate')              else:                  url = self._get_oauth_url('authorize')              request = oauth.OAuthRequest.from_token_and_callback(                  token=self.request_token, callback=callback, http_url=url              )              return request.to_url()          except Exception, e:              raise WeibopError(e)        def _get_referer_url(request):      referer_url = request.META.get('HTTP_REFERER', '/')      host = request.META['HTTP_HOST']      if referer_url.startswith('http') and host not in referer_url:          referer_url = '/' # 避免外站直接跳到登录页而发生跳转错误      return referer_url     def _oauth():      """获取oauth认证类"""      return WebOAuthHandler(consumer_key, consumer_secret)     def login(request):      # 保存最初的登录url,以便认证成功后跳转回来      back_to_url = _get_referer_url(request)      request.session['login_back_to_url'] = back_to_url         # 获取oauth认证url      login_backurl = request.build_absolute_uri('/logincheck')      auth_client = _oauth()      auth_url = auth_client.get_authorization_url_with_callback(login_backurl)      # 保存request_token,用户登录后需要使用它来获取access_token      request.session['oauth_request_token'] = auth_client.request_token      # 跳转到登录页面      return HttpResponseRedirect(auth_url)     def login_check(request):      """用户成功登录授权后,会回调此方法,获取access_token,完成授权"""        # http://mk2.com/?oauth_token=c30fa6d693ae9c23dd0982dae6a1c5f9&oauth_verifier=603896      verifier = request.GET.get('oauth_verifier', None)      auth_client = _oauth()      # 设置之前保存在session的request_token      request_token = request.session['oauth_request_token']      del request.session['oauth_request_token']         auth_client.set_request_token(request_token.key, request_token.secret)      access_token = auth_client.get_access_token(verifier)      # 保存access_token,以后访问只需使用access_token即可      request.session['oauth_access_token'] = access_token         # 跳转回最初登录前的页面      back_to_url = request.session.get('login_back_to_url', '/')      return HttpResponseRedirect(back_to_url)     def logout(request):      """用户登出,直接删除access_token"""      del request.session['oauth_access_token']      back_to_url = _get_referer_url(request)      return HttpResponseRedirect(back_to_url)

在完成了授权的代码之后,接着我们就要知道如何向新浪微博作发送消息等操作了。其实,在下载的SDK下的exanples文件夹(没错,其实是 examples,这英文水平,吐槽不能)中的例子基本上拿来改改就可以直接使用了。拿oauthSetTokenUpdate.py来说,我们就可以照着这么写:
# -*- coding: utf-8 -*-     from weibopy.auth import OAuthHandler  from weibopy.api import API     consumer_key= '应用的key'  consumer_secret ='应用的App Secret'     auth = OAuthHandler(consumer_key, consumer_secret)  auth_url = auth.get_authorization_url()  print 'Please authorize: ' + auth_url  verifier = raw_input('PIN: ').strip()  auth.get_access_token(verifier)  api = API(auth)     status = api.update_status(status='hello world', lat='12.3', long='45.6') # 注意status必须是UTF-8编码的字符串,经纬度是可以不写的  print status.id  print status.text

运行这个程序就会提示一个URL链接,在浏览器里打开这个链接,并且给予访问权限,就会拿到一串PIN码。把这个PIN码输上去,就会发送一条推了,并且还会显示用户的Access token key和Access token secret。

不过呢,这么做是不是有点太nerd了。其实我们只要知道Access token key和Access token secret之后,就可以直接用它们来创建API对象了:

# -*- coding: utf-8 -*-     from weibopy.auth import OAuthHandler  from weibopy.api import API     consumer_key= '应用的key'  consumer_secret ='应用的App Secret'  token = '用户的Access token key'  tokenSecret = '用户的Access token secret'     auth = OAuthHandler(consumer_key, consumer_secret)  auth.setToken(token, tokenSecret)  api = API(auth)     status = api.update_status(status='搞定收工~')

这个时候,我们可以重构一下代码,写一个weibo类,来实现以上的功能,并且实现一些api的操作。
class weibo(object):      def __init__(self):          self.consumer_key = consumer_key          self.consumer_secret = consumer_secret             def getAtt(self, key):          try:              return self.obj.__getattribute__(key)          except Exception, e:              print e              return ''                 def getAttValue(self, obj, key):          try:              return obj.__getattribute__(key)          except Exception, e:              print e              return ''                 def auth(self):          self.auth = OAuthHandler(self.consumer_key, self.consumer_secret)          auth_url = self.auth.get_authorization_url()          print 'Please authorize: ' + auth_url          verifier = raw_input('PIN: ').strip()          self.auth.get_access_token(verifier)          self.api = API(self.auth)              def setToken(self, token, tokenSecret):          self.auth = OAuthHandler(self.consumer_key, self.consumer_secret)          self.auth.setToken(token, tokenSecret)          self.api = API(self.auth)             def update(self, message):          message = message.encode("utf-8")          status = self.api.update_status(status=message)          self.obj = status          id = self.getAtt("id")                 return id                 def destroy_status(self, id):          status = self.api.destroy_status(id)          self.obj = status          id = self.getAtt("id")                 return id             def comment(self, id, message):          comment = self.api.comment(id=id, comment=message)          self.obj = comment          mid = self.getAtt("id")          return mid             def comment_destroy (self, mid):          comment = self.api.comment_destroy(mid)          self.obj = comment          mid = self.getAtt("id")          text = self.getAtt("text")          return mid             def repost(self, id, message):          post = self.api.repost(id=id, status=message)          self.obj = post          mid = self.getAtt("id")          return mid             def get_username(self):          if getattr(self, '_username', None) is None:              self._username = self.auth.get_username()          return self._username

不知道读者还记得我们上面授权部分的代码。在login_check方法代码里,有这样一句话。
request.session['oauth_access_token'] = access_token

授权用户的access_token已经保存在session变量中。因此,在用户授权完成时,我们就可以直接使用保存在session中的access_token,像这样:
access_token = request.session.get('oauth_access_token', None)  if access_token is not None:      weibo_client = weibo()      weibo_client.setToken(access_token.key, access_token.secret)      weibo_client.update('全部完成~')

以上的例子中只使用了部分API,完整的API手册参考这里

文章出处:http://qinxuye.me/article/sina-weibo-api-in-developing-diango/