python調用新浪微博API實踐


因為最近接觸到調用新浪微博開放接口的項目,所以就想試試用python調用微博API。

SDK下載地址:http://open.weibo.com/wiki/SDK  代碼不多十幾K,完全可以看懂。

有微博賬號可以新建一個APP,然后就可以得到app key和app secret,這個是APP獲得OAuth2.0授權所必須的。

了解OAuth2可以查看鏈接新浪微博的說明。 OAuth2授權參數除了需要app key和app secret還需要網站回調地址redirect_uri,並且這個回調地址不允許是局域網的(神馬localhost,127.0.0.1好像都不行),這個着實讓我着急了半天。我使用API也不是網站調用,於是查了很多。看到有人寫可以用這個地址替代,https://api.weibo.com/oauth2/default.html,我試了一下果然可以,對於屌絲來說是個好消息。

下面先來個簡單的程序,感受一下:

設置好以下參數

 

import sys
import weibo
import webbrowser

APP_KEY = ''
MY_APP_SECRET = ''
REDIRECT_URL = 'https://api.weibo.com/oauth2/default.html'

 

獲得微博授權URL,如第2行,用默認瀏覽器打開后會要求登陸微博,用需要授權的賬號登陸,如下圖

1 api = weibo.APIClient(app_key=APP_KEY,app_secret=MY_APP_SECRET,redirect_uri=REDIRECT_URL)
2 authorize_url = api.get_authorize_url()
3 print(authorize_url)
4 webbrowser.open_new(authorize_url)

登陸后會調轉到一個連接https://api.weibo.com/oauth2/default.html?code=92cc6accecfb5b2176adf58f4c

關鍵就是code值,這個是認證的關鍵。手動輸入code值模擬認證

1 request = api.request_access_token(code, REDIRECT_URL)
2 access_token = request.access_token
3 expires_in = request.expires_in
4 api.set_access_token(access_token, expires_in)
5 api.statuses.update.post(status=u'Test OAuth 2.0 Send a Weibo!')
access_token就是獲得的token,expires_in是授權的過期時間 (UNIX時間)
用set_access_token保存授權。往下就可以調用微博接口了。測試發了一條微博

 

但是這樣的手動輸入code方式,不適合程序的調用,是否可以不用打開鏈接的方式來請求登陸獲取授權,經多方查找和參考,將程序改進如下,可以實現自動獲取code並保存,方便程序服務調用。

accessWeibo
# -*- coding: utf-8 -*-  
#/usr/bin/env python  
 
#access to SinaWeibo By sinaweibopy 
#實現微博自動登錄,token自動生成,保存及更新 
#適合於后端服務調用 
  

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訪問配置  
APP_KEY = ''      # app key  
APP_SECRET = ''   # app secret  
REDIRECT_URL = 'https://api.weibo.com/oauth2/default.html' # callback url 授權回調頁,與OAuth2.0 授權設置的一致  
USERID = ''       # 登陸的微博用戶名,必須是OAuth2.0 設置的測試賬號                     
USERPASSWD = ''   # 用戶密碼  
 
  
client = APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri=REDIRECT_URL)  
  
def make_access_token():  
    #請求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數據庫
    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 目的是當調用make_access_token()后再執行一次apply_access_token()
@retry(1)  
def apply_access_token():  
    #從MongoDB讀取及設置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過期重新生成  
                    make_access_token()
                    return False  
            else:  
                pass  
    except:  
        make_access_token()
        return False  
      
    return True  
  
if __name__ == "__main__":  
    apply_access_token()  
  
    # 以下為訪問微博api的應用邏輯  
    # 以發布文字微博接口為例
    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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM