Python模擬登錄新浪微博

上篇介紹了新浪微博的登錄過程,這節使用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)

你們能夠根據不一樣的需求設計不一樣的爬蟲模塊了,模擬登錄的代碼放在這裏

相關文章
相關標籤/搜索