上篇介紹了新浪微博的登錄過程,這節使用Python編寫一個模擬登錄的程序。講解與程序以下:php
一、主函數(WeiboMain.py):html
import urllib2 import cookielib import WeiboEncode import WeiboSearch if __name__ == '__main__': weiboLogin = WeiboLogin('×××@gmail.com', '××××')#郵箱(帳號)、密碼 if weiboLogin.Login() == True: print "登錄成功!"
前兩個import是加載Python的網絡編程模塊,後面的import是加載另兩個文件WeiboEncode.py和Weiboseach.py(稍後介紹)。主函數新建登錄對象,而後登錄。ajax
二、WeiboLogin類(WeiboMain.py):正則表達式
class WeiboLogin: def __init__(self, user, pwd, enableProxy = False): "初始化WeiboLogin,enableProxy表示是否使用代理服務器,默認關閉" print "Initializing WeiboLogin..." self.userName = user self.passWord = pwd self.enableProxy = enableProxy self.serverUrl = "http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&rsakt=mod&client=ssologin.js(v1.4.11)&_=1379834957683" self.loginUrl = "http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.11)" self.postHeader = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0'}
初始化函數,定義了兩個關鍵的url成員:self.serverUrl用於登錄的第一步(獲取servertime、nonce等),這裏的第一步實質包含了解析新浪微博的登陸過程的1和2;self.loginUrl用於第二步(加密用戶和密碼後,POST給該URL,self.postHeader是POST的頭信息),這一步對應於解析新浪微博的登陸過程的3。類內函數還有3個:算法
def Login(self): "登錄程序" self.EnableCookie(self.enableProxy)#cookie或代理服務器配置 serverTime, nonce, pubkey, rsakv = self.GetServerTime()#登錄的第一步 postData = WeiboEncode.PostEncode(self.userName, self.passWord, serverTime, nonce, pubkey, rsakv)#加密用戶和密碼 print "Post data length:\n", len(postData) req = urllib2.Request(self.loginUrl, postData, self.postHeader) print "Posting request..." result = urllib2.urlopen(req)#登錄的第二步——解析新浪微博的登陸過程當中3 text = result.read() try: loginUrl = WeiboSearch.sRedirectData(text)#解析重定位結果 urllib2.urlopen(loginUrl) except: print 'Login error!' return False print 'Login sucess!' return True
self.EnableCookie用於設置cookie及代理服務器,網絡上有不少免費的代理服務器,爲防止新浪封IP,能夠使用。而後使登錄的第一步,訪問新浪服務器獲得serverTime等信息,而後利用這些信息加密用戶名和密碼,構建POST請求;執行第二步,向self.loginUrl發送用戶和密碼,獲得重定位信息後,解析獲得最終跳轉到的URL,打開該URL後,服務器自動將用戶登錄信息寫入cookie,登錄成功。編程
def EnableCookie(self, enableProxy): "Enable cookie & proxy (if needed)." cookiejar = cookielib.LWPCookieJar()#創建cookie cookie_support = urllib2.HTTPCookieProcessor(cookiejar) if enableProxy: proxy_support = urllib2.ProxyHandler({'http':'http://xxxxx.pac'})#使用代理 opener = urllib2.build_opener(proxy_support, cookie_support, urllib2.HTTPHandler) print "Proxy enabled" else: opener = urllib2.build_opener(cookie_support, urllib2.HTTPHandler) urllib2.install_opener(opener)#構建cookie對應的opener
EnableCookie函數比較簡單,能夠參見cookie——小甜品。json
def GetServerTime(self): "Get server time and nonce, which are used to encode the password" print "Getting server time and nonce..." serverData = urllib2.urlopen(self.serverUrl).read()#獲得網頁內容 print serverData try: serverTime, nonce, pubkey, rsakv = WeiboSearch.sServerData(serverData)#解析獲得serverTime,nonce等 return serverTime, nonce, pubkey, rsakv except: print 'Get server time & nonce error!' return None
WeiboSearch文件中的函數主要用於解析從服務器獲得的數據,比較簡單。服務器
三、sServerData函數(WeiboSearch.py):cookie
import re import json def sServerData(serverData): "Search the server time & nonce from server data" p = re.compile('\((.*)\)') jsonData = p.search(serverData).group(1) data = json.loads(jsonData) serverTime = str(data['servertime']) nonce = data['nonce'] pubkey = data['pubkey']# rsakv = data['rsakv']# print "Server time is:", serverTime print "Nonce is:", nonce return serverTime, nonce, pubkey, rsakv
解析過程主要使用了正則表達式和JSON,這部分比較容易理解。另外Login中解析重定位結果部分函數也在這個文件中以下:網絡
def sRedirectData(text): p = re.compile('location\.replace\([\'"](.*?)[\'"]\)') loginUrl = p.search(text).group(1) print 'loginUrl:',loginUrl return loginUrl
四、從第一步到第二步要對用戶和密碼進行加密,編碼操做(WeiboEncode.py)
import urllib import base64 import rsa import binascii def PostEncode(userName, passWord, serverTime, nonce, pubkey, rsakv): "Used to generate POST data" encodedUserName = GetUserName(userName)#用戶名使用base64加密 encodedPassWord = get_pwd(passWord, serverTime, nonce, pubkey)#目前密碼採用rsa加密 postPara = { 'entry': 'weibo', 'gateway': '1', 'from': '', 'savestate': '7', 'userticket': '1', 'ssosimplelogin': '1', 'vsnf': '1', 'vsnval': '', 'su': encodedUserName, 'service': 'miniblog', 'servertime': serverTime, 'nonce': nonce, 'pwencode': 'rsa2', 'sp': encodedPassWord, 'encoding': 'UTF-8', 'prelt': '115', 'rsakv': rsakv, 'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack', 'returntype': 'META' } postData = urllib.urlencode(postPara)#網絡編碼 return postData
PostEncode函數構建POST的消息體,要求構建獲得內容與真正登錄所需的信息相同。難點在用戶名和密碼的加密方式:
def GetUserName(userName): "Used to encode user name" userNameTemp = urllib.quote(userName) userNameEncoded = base64.encodestring(userNameTemp)[:-1] return userNameEncoded def get_pwd(password, servertime, nonce, pubkey): rsaPublickey = int(pubkey, 16) key = rsa.PublicKey(rsaPublickey, 65537) #建立公鑰 message = str(servertime) + '\t' + str(nonce) + '\n' + str(password) #拼接明文js加密文件中獲得 passwd = rsa.encrypt(message, key) #加密 passwd = binascii.b2a_hex(passwd) #將加密信息轉換爲16進制。 return passwd
新浪登陸過程,密碼的加密方式原來是SHA1,如今變爲了RSA,之後可能還會變化,可是各類加密算法在Python中都有對應的實現,只要發現它的加密方式(),程序比較易於實現。
到這裏,Python模擬登錄新浪微博就成功了,運行輸出:
loginUrl: http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&ssosavestate=1390390056&ticket=ST-MzQ4NzQ5NTYyMA==-1387798056-xd-284624BFC19FE242BBAE2C39FB3A8CA8&retcode=0 Login sucess!
若是須要爬取微博中的信息,接下來只須要在Main函數後添加爬取、解析模塊就能夠了,好比讀取某微博網頁的內容:
htmlContent = urllib2.urlopen(myurl).read()#獲得myurl網頁的全部內容(html)
你們能夠根據不一樣的需求設計不一樣的爬蟲模塊了,模擬登錄的代碼放在這裏。