前段時間開始學習Python,一直想不到有什么好的小項目可以做,憋得慌,這不, 絞盡腦汁想出了一個爬取新浪微博,並對爬取數據做簡單統計的項目。一開始我自以為學習了點Python正則就可以搞定了,熟料在機器登陸上栽了跟頭,從完全一頭霧水到現在初步登陸獲取到數據,整整歷經了四五天。因為之前沒搞過機器登陸方面的代碼,所以這次項目的初步完成完全歸功於網上的一些大神,我只是拾人牙慧,拼湊了幾個大神的代碼,另外加幾行注釋而已。
# import 這邊需要注意的是只有一個rsa這個模塊是需要install的,其他的都是內置
import re , urllib.parse , urllib.request , http.cookiejar , base64 , binascii , rsa
# 以下4行代碼說簡單點就是讓你接下來的所有get和post請求都帶上已經獲取的cookie,因為稍大些的網站的登陸驗證全靠cookie cj = http.cookiejar.LWPCookieJar() cookie_support = urllib.request.HTTPCookieProcessor(cj) opener = urllib.request.build_opener(cookie_support , urllib.request.HTTPHandler) urllib.request.install_opener(opener) # 封裝一個用於get的函數,新浪微博這邊get出來的內容編碼都是-8,所以把utf-8寫死在里邊了,真實項目中建議根據內容實際編碼來決定 def getData(url) : request = urllib.request.Request(url) response = urllib.request.urlopen(request) text = response.read().decode('utf-8') return text # 封裝一個用於post的函數,驗證密碼和用戶名都是post的,所以這個postData在本demo中專門用於驗證用戶名和密碼 def postData(url , data) :
# headers需要我們自己來模擬 headers = {'User-Agent' : 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)'}
# 這里的urlencode用於把一個請求對象用'&'來接來字符串化,接着就是編碼成utf-8 data = urllib.parse.urlencode(data).encode('utf-8') request = urllib.request.Request(url , data , headers) response = urllib.request.urlopen(request) text = response.read().decode('gbk') return text def login_weibo(nick , pwd) : #==========================獲取servertime , pcid , pubkey , rsakv===========================
# 預登陸請求,獲取到若干參數 prelogin_url = 'http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=%s&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.15)&_=1400822309846' % nick preLogin = getData(prelogin_url)
# 下面獲取的四個值都是接下來要使用的 servertime = re.findall('"servertime":(.*?),' , preLogin)[0] pubkey = re.findall('"pubkey":"(.*?)",' , preLogin)[0] rsakv = re.findall('"rsakv":"(.*?)",' , preLogin)[0] nonce = re.findall('"nonce":"(.*?)",' , preLogin)[0] #===============對用戶名和密碼加密================
# 好,你已經來到登陸新浪微博最難的一部分了,如果這部分沒有大神出來指點一下,那就真是太難了,我也不想多說什么,反正就是各種加密,最后形成了加密后的su和sp su = base64.b64encode(bytes(urllib.request.quote(nick) , encoding = 'utf-8')) rsaPublickey = int(pubkey , 16) key = rsa.PublicKey(rsaPublickey , 65537)
# 稍微說一下的是在我網上搜到的文章中,有些文章里並沒有對拼接起來的字符串進行bytes,這是python3的新方法好像是。rsa.encrypt需要一個字節參數,這一點和之前不一樣。其實上面的base64.b64encode也一樣 message = bytes(str(servertime) + '\t' + str(nonce) + '\n' + str(pwd) , encoding = 'utf-8') sp = binascii.b2a_hex(rsa.encrypt(message , key)) #=======================登錄=======================
#param就是激動人心的登陸post參數,這個參數用到了若干個上面第一步獲取到的數據,可說的不多 param = {'entry' : 'weibo' , 'gateway' : 1 , 'from' : '' , 'savestate' : 7 , 'useticket' : 1 , 'pagerefer' : 'http://login.sina.com.cn/sso/logout.php?entry=miniblog&r=http%3A%2F%2Fweibo.com%2Flogout.php%3Fbackurl%3D' , 'vsnf' : 1 , 'su' : su , 'service' : 'miniblog' , 'servertime' : servertime , 'nonce' : nonce , 'pwencode' : 'rsa2' , 'rsakv' : rsakv , 'sp' : sp , 'sr' : '1680*1050' , 'encoding' : 'UTF-8' , 'prelt' : 961 , 'url' : 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack'}
# 這里就是使用postData的唯一一處,也很簡單 s = postData('http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)' , param)
# 好了,當你的代碼執行到這里時,已經完成了大部分了,可是有很多爬蟲童鞋跟我一樣還就栽在了這里,假如你跳過這里直接去執行獲取粉絲的這幾行代碼你就會發現你獲取的到還是讓你登陸的頁面,真郁悶啊,我就栽在這里長達一天啊
# 好了,我們還是繼續。這個urll是登陸之后新浪返回的一段腳本中定義的一個進一步登陸的url,之前還都是獲取參數和驗證之類的,這一步才是真正的登陸,所以你還需要再一次把這個urll獲取到並用get登陸即可
urll = re.findall("location.replace\(\'(.*?)\'\);" , s)[0] getData(urll) #======================獲取粉絲====================
# 如果你沒有跳過剛才那個urll來到這里的話,那么恭喜你!你成功了,接下來就是你在新浪微博里暢爬的時候了,獲取到任何你想獲取到的數據了!
# 可以嘗試着獲取你自己的微博主頁看看,你就會發現那是一個多大幾百kb的文件了 text = getData('http://weibo.com/527891819/home?wvr=5&lf=reg') fp = open('yeah.txt' , 'w' , encoding = 'utf-8') fp.write(text) fp.close() login_weibo('你的微博郵箱' , '你的微博密碼')
#==================================================后記============================================================
#不經歷風雨,怎能見彩虹!
