因?yàn)樽罱佑|到調(diào)用新浪微博開(kāi)放接口的項(xiàng)目,所以就想試試用python調(diào)用微博API。
SDK下載地址:http://open.weibo.com/wiki/SDK 代碼不多十幾K,完全可以看懂。
有微博賬號(hào)可以新建一個(gè)APP,然后就可以得到app key和app secret,這個(gè)是APP獲得OAuth2.0授權(quán)所必須的。
了解OAuth2可以查看鏈接新浪微博的說(shuō)明。 OAuth2授權(quán)參數(shù)除了需要app key和app secret還需要網(wǎng)站回調(diào)地址redirect_uri,并且這個(gè)回調(diào)地址不允許是局域網(wǎng)的(神馬localhost,127.0.0.1好像都不行),這個(gè)著實(shí)讓我著急了半天。我使用API也不是網(wǎng)站調(diào)用,于是查了很多。看到有人寫可以用這個(gè)地址替代,https://api.weibo.com/oauth2/default.html,我試了一下果然可以,對(duì)于?潘坷此凳歉齪孟?息。
下面先來(lái)個(gè)簡(jiǎn)單的程序,感受一下:
設(shè)置好以下參數(shù)
import sys import weibo import webbrowser APP_KEY = '' MY_APP_SECRET = '' REDIRECT_URL = 'https://api.weibo.com/oauth2/default.html'
獲得微博授權(quán)URL,如第2行,用默認(rèn)瀏覽器打開(kāi)后會(huì)要求登陸微博,用需要授權(quán)的賬號(hào)登陸,如下圖
api = weibo.APIClient(app_key=APP_KEY,app_secret=MY_APP_SECRET,redirect_uri=REDIRECT_URL) authorize_url = api.get_authorize_url() print(authorize_url) webbrowser.open_new(authorize_url)
登陸后會(huì)調(diào)轉(zhuǎn)到一個(gè)連接https://api.weibo.com/oauth2/default.html?code=92cc6accecfb5b2176adf58f4c
關(guān)鍵就是code值,這個(gè)是認(rèn)證的關(guān)鍵。手動(dòng)輸入code值模擬認(rèn)證
request = api.request_access_token(code, REDIRECT_URL) access_token = request.access_token expires_in = request.expires_in api.set_access_token(access_token, expires_in) api.statuses.update.post(status=u'Test OAuth 2.0 Send a Weibo!')
access_token就是獲得的token,expires_in是授權(quán)的過(guò)期時(shí)間 (UNIX時(shí)間)
用set_access_token保存授權(quán)。往下就可以調(diào)用微博接口了。測(cè)試發(fā)了一條微博
但是這樣的手動(dòng)輸入code方式,不適合程序的調(diào)用,是否可以不用打開(kāi)鏈接的方式來(lái)請(qǐng)求登陸獲取授權(quán),經(jīng)多方查找和參考,將程序改進(jìn)如下,可以實(shí)現(xiàn)自動(dòng)獲取code并保存,方便程序服務(wù)調(diào)用。
accessWeibo # -*- coding: utf-8 -*- #/usr/bin/env python #access to SinaWeibo By sinaweibopy #實(shí)現(xiàn)微博自動(dòng)登錄,token自動(dòng)生成,保存及更新 #適合于后端服務(wù)調(diào)用 from weibo import APIClient import pymongo import sys, os, urllib, urllib2 from http_helper import * from retry import * try: import json except ImportError: import simplejson as json # setting sys encoding to utf-8 default_encoding = 'utf-8' if sys.getdefaultencoding() != default_encoding: reload(sys) sys.setdefaultencoding(default_encoding) # weibo api訪問(wèn)配置 APP_KEY = '' # app key APP_SECRET = '' # app secret REDIRECT_URL = 'https://api.weibo.com/oauth2/default.html' # callback url 授權(quán)回調(diào)頁(yè),與OAuth2.0 授權(quán)設(shè)置的一致 USERID = '' # 登陸的微博用戶名,必須是OAuth2.0 設(shè)置的測(cè)試賬號(hào) USERPASSWD = '' # 用戶密碼 client = APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri=REDIRECT_URL) def make_access_token(): #請(qǐng)求access token params = urllib.urlencode({ 'action':'submit', 'withOfficalFlag':'0', 'ticket':'', 'isLoginSina':'', 'response_type':'code', 'regCallback':'', 'redirect_uri':REDIRECT_URL, 'client_id':APP_KEY, 'state':'', 'from':'', 'userId':USERID, 'passwd':USERPASSWD, }) login_url = 'https://api.weibo.com/oauth2/authorize' url = client.get_authorize_url() content = urllib2.urlopen(url) if content: headers = { 'Referer' : url } request = urllib2.Request(login_url, params, headers) opener = get_opener(False) urllib2.install_opener(opener) try: f = opener.open(request) return_redirect_uri = f.url except urllib2.HTTPError, e: return_redirect_uri = e.geturl() # 取到返回的code code = return_redirect_uri.split('=')[1] #得到token token = client.request_access_token(code,REDIRECT_URL) save_access_token(token) def save_access_token(token): #將access token保存到MongoDB數(shù)據(jù)庫(kù) mongoCon=pymongo.Connection(host="127.0.0.1",port=27017) db= mongoCon.weibo t={ "access_token":token['access_token'], "expires_in":str(token['expires_in']), "date":time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) } db.token.insert(t,safe=True) #Decorator 目的是當(dāng)調(diào)用make_access_token()后再執(zhí)行一次apply_access_token() @retry(1) def apply_access_token(): #從MongoDB讀取及設(shè)置access token try: mongoCon=pymongo.Connection(host="127.0.0.1",port=27017) db= mongoCon.weibo if db.token.count()>0: tokenInfos=db.token.find().sort([("_id",pymongo.DESCENDING)]).limit(1) else: make_access_token() return False for tokenInfo in tokenInfos: access_token=tokenInfo["access_token"] expires_in=tokenInfo["expires_in"] try: client.set_access_token(access_token, expires_in) except StandardError, e: if hasattr(e, 'error'): if e.error == 'expired_token': # token過(guò)期重新生成 make_access_token() return False else: pass except: make_access_token() return False return True if __name__ == "__main__": apply_access_token() # 以下為訪問(wèn)微博api的應(yīng)用邏輯 # 以發(fā)布文字微博接口為例 client.statuses.update.post(status='Test OAuth 2.0 Send a Weibo!')
retry.py import math import time # Retry decorator with exponential backoff def retry(tries, delay=1, backoff=2): """Retries a function or method until it returns True. delay sets the initial delay, and backoff sets how much the delay should lengthen after each failure. backoff must be greater than 1, or else it isn't really a backoff. tries must be at least 0, and delay greater than 0.""" if backoff <= 1: raise ValueError("backoff must be greater than 1") tries = math.floor(tries) if tries < 0: raise ValueError("tries must be 0 or greater") if delay <= 0: raise ValueError("delay must be greater than 0") def deco_retry(f): def f_retry(*args, **kwargs): mtries, mdelay = tries, delay # make mutable rv = f(*args, **kwargs) # first attempt while mtries > 0: if rv == True or type(rv) == str: # Done on success .. return rv mtries -= 1 # consume an attempt time.sleep(mdelay) # wait... mdelay *= backoff # make future wait longer rv = f(*args, **kwargs) # Try again return False # Ran out of tries :-( return f_retry # true decorator -> decorated function return deco_retry # @retry(arg[, ...]) -> true decorator
http_helper.py # -*- coding: utf-8 -*- #/usr/bin/env python import urllib2,cookielib class SmartRedirectHandler(urllib2.HTTPRedirectHandler): def http_error_301(cls, req, fp, code, msg, headers): result = urllib2.HTTPRedirectHandler.http_error_301(cls, req, fp, code, msg, headers) result.status = code print headers return result def http_error_302(cls, req, fp, code, msg, headers): result = urllib2.HTTPRedirectHandler.http_error_302(cls, req, fp, code, msg, headers) result.status = code print headers return result def get_cookie(): cookies = cookielib.CookieJar() return urllib2.HTTPCookieProcessor(cookies) def get_opener(proxy=False): rv=urllib2.build_opener(get_cookie(), SmartRedirectHandler()) rv.addheaders = [('User-agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)')] return rv
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
