Python:新浪微博API的使用及安全的類比登陸自動擷取code值__Python

來源:互聯網
上載者:User

一直用類比登陸的方法擷取微博資料。突然感覺好老土,最重要的是,soga,好慢。所以摸索下API的使用,體驗高大上的感覺。

作者@廖雪峰 貢獻了SDK。Demo懵懵懂懂,實踐出真知。廢話不多說。開始。 1. API下載及應用建立

微博API首頁地址:點擊開啟連結。

1、首先要填寫個人開發人員或者企業開發的資訊。時間太久,這不是痛點,不詳細說明。

2、下面開始建立應用,我選擇的是站內應用。這個也很簡單。


3、下載對應的SDK,我用的是Python。安裝,如果報錯,請直接複製weibo.py到你的工程目錄。另外一個檔案還不知道怎麼用(14.05.21注,隨時更新)。

SDK下載地址:點擊開啟連結。

4、使用,參考文章:新浪微博API使用之python介面的使用 作者@monsion 

#!/usr/bin/python # -*- coding: utf-8 -*-"""# 微博API測試"""import sys reload(sys)sys.setdefaultencoding("utf8")from weibo import APIClientimport MySQLdb, webbrowserimport urllib3if __name__ == "__main__":    APP_KEY = u'' # app key    APP_SECRET = u'' # app secret    CALLBACK_URL = 'http://apps.weibo.com/zhanhisnshows'    client = APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri=CALLBACK_URL)    url = client.get_authorize_url()    print url    webbrowser.open_new(url)
APP_KEY和APP_SECRET建立應用後就會獲得,關鍵是CALLBACK_URL怎麼獲得。

隨便填個CALLBACK_URL報錯:


原因正是CALLBACK_URL填寫錯誤。

於是百度,果斷的,找的資訊都沒用。都是說去下圖的地方填寫


試了不行。於是我試著填寫應用資料。填寫站內應用地址後,搞定。如下圖所示:


最終結果就是第三四個圖了。擷取code成功。

(2014.05.21註:今天找到了教程,為啥我需要的時候沒找到捏。參考:新浪微博API使用初步介紹——解決回調地址的問題 作者@monsion)


code的值在地址欄裡。接下來開始擷取資料。

(2014。05.21註:博主玩著玩著就掉到自動擷取code的坑裡了,資料擷取慢慢道來,以後更新。。。) 2. 自動擷取code的值 博主自己慢慢琢磨,中間擷取 關鍵參數ticket時遇到問題,問題如下: 問題1:錯誤:urllib2.URLError: <urlopen error unknown url type: https>

解決方案:很多都說是沒有安裝OpemSSL,我的已經安裝了,還是報錯。最後找到的原因是:URL錯誤。。。我去,完全搞不搞,看起來是沒錯的,但是複製到瀏覽器就發現https前面多了點什麼,就是這個,搞了幾個小時。

好了其他沒什麼問題。需要提醒大家的是:pcid, servertime, nonce, rsakv, sp, su參數的擷取,涉及到類比登陸,如果不會,可以參考我的sina部落格文章:python 新浪微博類比登陸 & 密碼加密分析看完不懂可以在Blog留言或者微博@The_Third_Wave 。

博主搞定ticket後,開始最後的攻堅戰,成功。

其中有參考python調用新浪微博API實踐 @風行影者 

下載了@風行影者 的代碼,運行OK,發現問題。@風行影者 代碼中明文傳輸了使用者名稱和密碼,於是重寫如下,代碼貼出,歡迎批評指正:

#!/usr/bin/python # -*- coding: utf-8 -*-"""[Filename]WeiboAPI.py@author: U{The_Third_Wave/huan zhan<mailto: zhanh121823 at sina.com>}@copyright: U{Copyright (c) 2014.05.22, huan zhan}@contact: zhanh121823 at sina.com/QQ:563134080@version: $1.0$# 微博API介面"""import sys reload(sys)sys.setdefaultencoding("utf8")from weibo import APIClientimport MySQLdb, webbrowser, re, jsonimport urllib, urllib2, urllib3, cookielibimport hashlib, base64, rsa, binascii # encryptclass SmartRedirectHandler(urllib2.HTTPRedirectHandler):    """    # 參考:風行影者/Blog:http://www.cnblogs.com/wly923/archive/2013/04/28/3048700.html    """    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        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        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 rvclass SinaAPI():    """    # @author: U{The_Third_Wave/huan zhan<mailto: zhanh121823 at sina.com>}    # get_code_NS()方法為風行影者所寫。/Blog:http://www.cnblogs.com/wly923/archive/2013/04/28/3048700.html    # get_code_NS()明文傳輸密碼,不安全。所以作者@The_Third_Wave 用類比登陸的方法擷取重要參數'ticket'。保證傳輸過程中不明文傳輸密碼。保證安全。    # get_code_Security()方法為作者@The_Third_Wave所寫安全自動擷取code的方法。    # 有疑問的請Blog:http://blog.csdn.net/zhanh1218/article/details/26383469留言或者sina微博關注作者@The_Third_Wave。    """    def __init__(self, CALLBACK_URL, APP_KEY, REDIRECT_URL, USER_ID, USER_PSWD):        self.CALLBACK_URL = CALLBACK_URL        self.APP_KEY = APP_KEY        self.REDIRECT_URL = REDIRECT_URL        self.USER_ID = USER_ID        self.USER_PSWD = USER_PSWD        self.http = urllib3.PoolManager()            def get_username(self, USER_ID):        # The Encryption Algorithm of username         # ssologin.js : ah.su=sinaSSOEncoder.base64.encode(m(aj));        USER_ID_ = urllib.quote(USER_ID) # encode username, avoid error example:@ &          su = base64.encodestring(USER_ID_)[:-1]        return su       def get_password_rsa(self, USER_PSWD, PUBKEY, servertime, nonce):        # 密碼加密運算sina我已知有兩種,這是其中一種。        # rsa Encrypt :  #when pwencode = "rsa2"        rsaPubkey = int(PUBKEY, 16)#pubkey from 16 to 10        key_1 = int('10001', 16) #10001 to 65537         key = rsa.PublicKey(rsaPubkey, key_1) #        message = str(servertime) + "\t" + str(nonce) + "\n" + str(USER_PSWD)        passwd = rsa.encrypt(message, key)        passwd = binascii.b2a_hex(passwd) #to 16        return passwd          def get_parameter(self):        su = self.get_username(self.USER_ID)        #su = get_username(USER_ID)        url = "https://login.sina.com.cn/sso/prelogin.php?entry=openapi&callback=sinaSSOController.preloginCallBack\&su="+su+"&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.15)"        r = self.http.request('GET', url)        p = re.compile('\((.*)\)')        json_data = p.search(r.data).group(1)        data = json.loads(json_data)                PUBKEY = data['pubkey']        pcid = data['pcid']        servertime = str(data['servertime'])        nonce = data['nonce']        rsakv = str(data['rsakv'])        sp = self.get_password_rsa(self.USER_PSWD, PUBKEY, servertime, nonce)                #print pcid; print servertime; print nonce; print rsakv; print sp; print su        return pcid, servertime, nonce, rsakv, sp, su             def get_ticket(self):        pcid, servertime, nonce, rsakv, sp, su = self.get_parameter()        fields = urllib.urlencode({            'entry'        : 'openapi',            'gateway'      : '1',            'from'         : '',            'savestate'    : '0',            'useticket'    : '1',            'pagerefer'    :'',            'pcid'         : pcid,            'ct'           : '1800',            's'            : '1',            'vsnf'         : '1',            'vsnval'       : '',            'door'         : '',            'appkey'       : 'kxR5R',            'su'           : su,            'service'      : 'miniblog',            'servertime'   : servertime,            'nonce'        : nonce,            'pwencode'     : 'rsa2',            'rsakv'        : rsakv,            'sp'           : sp,            'sr'           : '1680*1050',            'encoding'     : 'UTF-8',            'cdult'        : '2',            'domain'       : 'weibo.com',            'prelt'        : '0',            'returntype'   : 'TEXT',        })        headers = {                   #"請求": "POST /sso/login.php?client=ssologin.js(v1.4.15)&_=1400652171542 HTTP/1.1",                   #"Accept": "*/*",                    "Content-Type": "application/x-www-form-urlencoded",                   #"Referer": self.CALLBACK_URL,                   #"Accept-Language": "zh-CN",                   #"Origin": "https://api.weibo.com",                   #"Accept-Encoding": "gzip, deflate",                   #"User-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; EIE10;ZHCNMSE; rv:11.0) like Gecko",                   #"Host": "login.sina.com.cn",                   #"Connection": "Keep-Alive",                   #"Cache-Control": "no-cache",                   }        url = "https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)"        req = urllib2.Request(url, fields, headers)        f = urllib2.urlopen(req)        data = json.loads(f.read())        return data["ticket"]        def get_code_Security(self):         ticket = self.get_ticket()        fields = urllib.urlencode({            'action': 'submit', # 必須            'display': 'default',            'withOfficalFlag': '0', # 必須            'quick_auth': 'null',            'withOfficalAccount': '',            'scope': '',            'ticket': ticket, # 必須            'isLoginSina': '',              'response_type': 'code', # 必須            'regCallback': 'https://api.weibo.com/2/oauth2/authorize?client_id='+self.APP_KEY+'\&response_type=code&display=default&redirect_uri='+self.REDIRECT_URL+'&from=&with_cookie=',            'redirect_uri': self.REDIRECT_URL, # 必須            'client_id': self.APP_KEY, # 必須            'appkey62': 'kxR5R',            'state': '', # 必須            'verifyToken': 'null',            'from': '', # 必須            'userId': "", # 此方法不需要填寫明文ID            'passwd': "", # 此方法不需要填寫純文字密碼            })        LOGIN_URL = 'https://api.weibo.com/oauth2/authorize'         headers = {"User-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; EIE10;ZHCNMSE; rv:11.0) like Gecko",                   "Referer": self.CALLBACK_URL,                   "Content-Type": "application/x-www-form-urlencoded",                   }        req = urllib2.Request(LOGIN_URL, fields, headers)        req_ =urllib2.urlopen(req)        return_redirect_uri = req_.geturl()        code = re.findall(r"(?<=code%3D).{32}|(?<=code=).{32}", return_redirect_uri) # url中=用%3D表示或者=直接表示         print code        return code         def get_code_NS(self):        fields = urllib.urlencode({            'action': 'submit', # 必須            'display': 'default',            'withOfficalFlag': '0', # 必須            'quick_auth': 'null',            'withOfficalAccount': '',            'scope': '',            'ticket': '', # 必須            'isLoginSina': '',              'response_type': 'code', # 必須            'regCallback': '',            'redirect_uri': self.REDIRECT_URL, # 必須            'client_id': self.APP_KEY, # 必須            'appkey62': 'kxR5R',            'state': '', # 必須            'verifyToken': 'null',            'from': '', # 必須            'userId': self.USER_ID, # 必須            'passwd': self.USER_PSWD, # 必須            })        LOGIN_URL = 'https://api.weibo.com/oauth2/authorize'         headers = {"User-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; EIE10;ZHCNMSE; rv:11.0) like Gecko",                   "Referer": self.CALLBACK_URL,                   "Content-Type": "application/x-www-form-urlencoded",                   }        r = urllib2.Request(LOGIN_URL, fields, headers)        opener = get_opener(False)         urllib2.install_opener(opener)        try:              f = opener.open(r)              return_redirect_uri = f.url               print "NS1", return_redirect_uri                     except urllib2.HTTPError, e:              return_redirect_uri = e.geturl()              print "NS2", return_redirect_uri          # 取到返回的code          #code = return_redirect_uri.split('=')[1]        # 以下我用正則改寫,這樣不會因為url變化而不能提取code的值        code = re.findall(r"(?<=code%3D).{32}|(?<=code=).{32}", return_redirect_uri) # url中=用%3D表示或者=直接表示         print code        return code  if __name__ == "__main__":    APP_KEY = u'' # app key    APP_SECRET = u'' # app secret    REDIRECT_URL = 'http://apps.weibo.com/zhanhisnshows'    client = APIClient(app_key=APP_KEY, app_secret=APP_SECRET, redirect_uri=REDIRECT_URL)    CALLBACK_URL = client.get_authorize_url()    print CALLBACK_URL       API = SinaAPI(CALLBACK_URL, APP_KEY, REDIRECT_URL, username, password)    code = API.get_code_Security()    #code = API.get_code_NS() http://    """    #webbrowser.open_new(url) #擷取code=後面的內容      code = raw_input('輸入url中code後面的內容後按斷行符號鍵:')      print code, "code"    """    requests = client.request_access_token(code)      access_token = requests.access_token # 新浪返回的token,類似abc123xyz456      expires_in = requests.expires_in      # 設定得到的access_token      client.set_access_token(access_token, expires_in)      print client.statuses__public_timeline()      statuses = client.statuses__public_timeline()['statuses']      length = len(statuses)      #輸出了部分資訊      for i in range(0,length):          print u'暱稱:'+statuses[i]['user']['screen_name']          print u'簡介:'+statuses[i]['user']['description']          print u'位置:'+statuses[i]['user']['location']          print u'微博:'+statuses[i]['text']  

3. 資料擷取詳解 具體請看API: http://open.weibo.com/wiki/%E5%BE%AE%E5%8D%9AAPI 。 廖雪峰先生關於API的說明: 點擊開啟連結 一定要看。 看完上面兩篇就知道怎麼自訂命令了。很好的教程。廖老師真是做了很多事情的。感謝。 最後編輯於:2014.05.24 9:54

檔案免費下載地址:weibo.py &WeiboAPI.py

本文由@The_Third_Wave原創。不定期更新,有錯誤請指正。

Sina微博關註:@The_Third_Wave 

如果這篇博文對您有協助,為了好的網路環境,不建議轉載,建議收藏。如果您一定要轉載,請帶上尾碼和本文地址。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.