Django開發中整合新浪微博API
隨著新浪微博用戶日益增加,我們有時候會考慮在自己的網站中整合新浪微博。比如說我現在的獨立博客。
在我的博客中做到整合主要就這幾方面:我寫一篇文章,就會同步發送至微博。同時呢,用戶可以用微博帳號登錄,并且可以選擇把對文章的評論,同步評論到文章的微博。另外,用戶可以選擇是否把博客留言同步至新浪微博。
首先要涉及的問題,就是用戶用新浪微博帳號登錄的問題,即授權機制。基本方法有兩種:
- OAuth
- Basic auth(需要強調的是,微博開放平臺將于6月1日正式停止Basic Auth的支持。因此,此種方法不作討論了,其實需要用戶名和密碼的方式本身就不安全。)
OAuth新浪官方的文檔在這里。想要了解OAuth技術說明的可以訪問項目主頁。
其實,OAuth的流程還是很簡單的。大致如下:
- 向API調用獲得request token。
- 將用戶重定向到授權頁(auth url)。
- 用戶輸入用戶名和密碼完成授權。重定向到Callback_url。
- 用request token向新浪微博換取access token。
- 完成。
大致了解了OAuth的原理以后,由于我們是整合至Django,自然需要下載微博SDK的Python版。
不過,在全部開始前,你得先向新浪微博申請你的應用。申請地址在這里。這里要強調的是,日后應用需要申請審核,因為只有審核通過后,在來源中才能顯示個性的應用名。所以,在申請的時候,注意應用介紹信息的完整,以及應用分類的填寫正確。(在本例中,我們的分類是合作網站。)
申請完成以后將會得到你的應用的App Key和App 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/