本節將改進上一節中發微博的程式,主要的改進功能是:能夠儲存授權的access_token,不用進行重複授權。先看一下本節工程的目錄結構(1所示)。
圖1
send_weibo.py為發微博的主程式,與上一節中的程式沒有什麼差別。目錄initclient是我自己定義的一個包,目錄中的initclient.py封裝了授權過程,後面詳細解釋,token-record.log是一個資料檔案,用來儲存授權的access_token,__init__.py是自訂包所必須的,檔案為空白(關於__init__.py不明白的朋友可以查看Python相關文檔)。
首先看一下initclient.py的內容:
#! /usr/bin/pythonimport weibo import urllibimport timeimport osclass myAPIClient(weibo.APIClient): """ myAPIClient類繼承自weibo包中的APIClient類,對其進行了擴充。SDK中的APIClient類沒有根據已授權的access_token擷取授權詳細資料的介面。另外,SDK中 的APIClient不能儲存當前授權使用者的uid,該繼承類實現了這兩個功能,使得用起來更加方便。 """def __init__(self, app_key, app_secret, redirect_uri=None, response_type='code', domain='api.weibo.com', version='2'):weibo.APIClient.__init__(self, app_key, app_secret, redirect_uri=None, response_type='code', domain='api.weibo.com', version='2') #儲存當前授權使用者的uidself.uid = ""def request_access_token_info(self, at): """ 該介面傳入參數at為已經授權的access_token,函數將返回該access_token的詳細資料,返回Json對象,與APIClient類的request_access_token類似。 """r = weibo._http_post('%s%s' % (self.auth_url, 'get_token_info'), access_token = at)current = int(time.time())expires = r.expire_in + currentremind_in = r.get('remind_in', None)if remind_in:rtime = int(remind_in) + currentif rtime < expires:expires = rtimereturn weibo.JsonDict(expires=expires, expires_in=expires, uid=r.get('uid', None))def set_uid(self, uid):self.uid = uidTOKEN_FILE = 'token-record.log'def load_tokens(filename=TOKEN_FILE):acc_tk_list = []try:filepath = os.path.join(os.path.dirname(__file__), filename)f = open(filepath)acc_tk_list.append(f.readline().strip())print "===> Get the access_token from file token-record.log : ", acc_tk_list[0]except IOError:print "===> File token-record.log does not exist."f.close()return acc_tk_listdef dump_tokens(tk, filename=TOKEN_FILE):try:filepath = os.path.join(os.path.dirname(__file__), filename)f = open(filename, 'a')f.write(tk)f.write('\n')except IOError:print "===> File token-record.log does not exist."f.close()print "===> The new access_token has been written to file token-record.log."def get_client(appkey, appsecret, callback):client = myAPIClient(appkey, appsecret, callback)at_list = load_tokens()if at_list:access_token = at_list[-1]r = client.request_access_token_info(access_token)expires_in = r.expires_inprint "===> The access_token's expires_in : %f" % expires_in #授權access_token到期if r.expires_in <= 0:return Noneclient.set_uid(r.uid)else:auth_url = client.get_authorize_url()print "===> auth_url : " + auth_url print """===> Note! The access_token is not available, you should be authorized again. Please open the url above in your browser, then you will get a returned url with the code field. Input the code in the follow step."""code = raw_input("===> input the retured code : ")r = client.request_access_token(code)access_token = r.access_tokenexpires_in = r.expires_inprint "===> the new access_token is : ", access_tokendump_tokens(access_token)client.set_access_token(access_token, expires_in)client.set_uid(r.uid)return client
【說明】:
(1)myAPIClient類繼承自weibo包中的APIClient類,增加了兩個功能:第一,儲存當前授權使用者的uid,該值在後面需要用到,所以儲存到類成員變數中;第二,根據授權的access_token擷取授權資訊,這裡實際是調用新浪微博提供的API,具體參考官方文檔(http://open.weibo.com/wiki/Oauth2/get_token_info);
(2)load_tokens和dump_tokens兩個函數分別用於從檔案token-record.log讀取授權的access_token和將access_token寫入檔案;
(3)get_client是擷取授權的myAPIClient對象的介面,也是該模組最關鍵的函數,也很簡單,就是讀取檔案token-record.log,如果讀到access_token就調用myAPIClient類的函數request_access_token_info擷取該access_token的詳細資料(主要是expires_in),如果檔案中沒有讀到則需要重新授權(跟上一節中的內容一樣),最後返回授權的client對象。圖2中顯示了該過程。
圖2
下面看一下send_weibo.py的內容:
#! /usr/bin/pythonfrom initclient import initclientAPP_KEY = '2024******'APP_SECRET = '91a57******'CALL_BACK = 'http://bingbingrobot.sinaapp.com/'def run(): #調用initclietn模組建立授權的client對象client = initclient.get_client(APP_KEY, APP_SECRET, CALL_BACK)if not client: return #根據使用者輸入內容發微博while True:print "Ready! Do you want to send a new weibo?(y/n)"choice = raw_input()if choice == 'y' or choice == 'Y':content = raw_input('input the your new weibo content : ')if content:client.statuses.update.post(status=content)print "Send succesfully!"break;else:print "Error! Empty content!"if choice == 'n' or choice == 'N':breakif __name__ == "__main__":run()
【說明】:
(1)注意第3行的import語句,表示從包(目錄)initclient中引入initclient模組,要求initclient目錄中必須含有__init__.py檔案(不瞭解的朋友請查看相關文檔);
(2)有了initclient包後,主程式send_weibo.py變得非常簡單,擷取授權client只需要一行代碼即可,而且程式功能也變得非常合理了,只要上一次授權的access_token沒有到期,這一次就不需要重複授權了。而且該initclient包是可以重複利用的,後面需要開發其他功能直接使用該包即可;
(3)運行結果3所示。
圖3
【補充】:
大家有沒有注意到load_tokens函數中讀取access_token是用的一個list儲存的,而且dump_tokens中寫入access_token是用的追加模式,這樣寫實為了程式的擴充,將來如果想把自己的應用發布,有很多使用者使用時,每個授權使用者都會有一個access_token,這樣就可以把所有使用者的access_token存在檔案中,根據登陸使用者的access_token去檔案中尋找是否已經授權。本程式中都是用我自己的賬戶登陸的,所以是有一個access_token,所以initclient.py的第63行讀取的是at_list[-1],即讀取檔案中的最後一個access_token。
代碼打包下載:http://download.csdn.net/detail/lewsn2008/5583803
By: