閑來無事,由於校園內網絡是限流量的,查詢流量很是頻繁,於是萌生了寫一個本地腳本進行一鍵查詢自己的剩余流量。
整個部分可以分為三個過程進行:
- 對登陸時http協議進行分析
- 利用python進行相關的模擬登陸
- 后期整合
第一部分:對登陸時http協議進行分析
模擬瀏覽器進行登陸,那么就需要知道當瀏覽器進行登陸時發生了什么事情。對此可以參見下面這張自制的圖,它展示了一次瀏覽器訪問一個地址的全過程。
圖1 瀏覽器在地址框輸入一個地址后發生的事情
參考自:http://www.linux178.com/web/httprequest.html
對於本部分來說,我們只需要關系途中的3和4過程,即http協議請求及服務器響應http協議請求返回html文件。
由圖可知,http協議請求分為三部分:起始行,頭部,主體。既然我們是模擬瀏覽器登陸進行,那么瀏覽器的這些信息是怎么填的呢?這個可以通過瀏覽器自帶的開發者工具看到,我所使用的瀏覽器是chorm,通過點擊右上角的按鈕,然后“更多工具——開發者工具”,之后選擇其中的Network選項,效果如下圖所示
圖2 瀏覽器的開發者工具
將上面的內容清空后,輸入能夠登錄查詢的網址。具體例子是我們學校為http://zyzfw.xidian.edu.cn/ 詳情見圖3
圖3 查詢http協議信息
之后就可以看見協議中相關部分所填內容。但這並非我們所要的東西,我們所需要的是模擬登陸的過程,也就是說需要的是在我們填好賬號密碼驗證碼后點擊登陸所發生的動作。因此應該去找點擊登陸后所發出的請求內容是什么(在這里可以通過輸入錯誤的密碼來查看所發出的內容是什么,以免頁面跳轉后突然彈出大量的通信將我們所需要的信息淹沒),頭部信息如圖4
圖4 頭部信息
其中具體每一項什么作用可以參考這兩個文章,講的很細致很有條理
https://www.zybuluo.com/yangfch3/note/167490
http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html
我們模擬登陸所需要的為圖4中的Host Referer User-Agent 以及圖5中的數據主體
圖5 數據主體
當我們把這些信息都搞到手后,就可以開始模擬瀏覽器登陸過程了。
整理一下,在本網站登陸所用的請求方法為“POST” 其采用的簡單安全措施為__crsf 與驗證碼 因此下一步的主要工作就是講驗證碼與__crsf問題搞定
第二部分:利用python進行模擬登陸
此部分參考:https://github.com/xchaoinfo/fuck-login/blob/master/001%20zhihu/zhihu.py
首先,構造頭部信息(最好在字符串前加上r,防止某些轉義問題)
url_login=r'http://zyzfw.xidian.edu.cn/' postdata={'LoginForm[username]':'1503*****','LoginForm[password]':'*****'} agent=r'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36' headers = { "Host": "zyzfw.xidian.edu.cn", "Referer": r"http://zyzfw.xidian.edu.cn/", 'User-Agent': agent }
由於有驗證碼的存在,因此需要將驗證碼得到,具體如下:
def get_captcha(): t = str(int(time.time() * 1000)) captcha_url = 'http://zyzfw.xidian.edu.cn/site/captcha?refresh=1&_=' + t r = session.get(captcha_url, headers=headers) #兩層get tem=r.json()['url'] captcha_url='http://zyzfw.xidian.edu.cn'+tem r=session.get(captcha_url,headers=headers) with open('captcha.jpg', 'wb') as f: f.write(r.content) f.close() # 用pillow 的 Image 顯示驗證碼 # 如果沒有安裝 pillow 到源代碼所在的目錄去找到驗證碼然后手動輸入 try: im = Image.open('captcha.jpg') im.show() im.close() except: print(u'請到 %s 目錄找到captcha.jpg 手動輸入' % os.path.abspath('captcha.jpg')) captcha = input("please input the captcha\n>") return captcha
其中的那個驗證碼的地址,通過和第一部分同樣的方法,找到其獲取驗證碼的地址(我測試的幾個網站驗證碼獲取地址都和時間有關),將驗證碼圖片下載保存下來后就可以進行驗證碼的讀取工作。
只有在進行__xsrf參數的獲取,過程類似,如下:
def get_csrf(): '''_csrf 是一個動態變化的參數''' index_url = 'http://zyzfw.xidian.edu.cn' # 獲取登錄時需要用到的_xsrf index_page = session.get(index_url, headers=headers) html = index_page.text pattern = r'name="_csrf" value="(.*?)"' # 這里的_xsrf 返回的是一個list _xsrf = re.findall(pattern, html) return _xsrf[0]
其中涉及到簡單的字符串匹配,使用簡單的正則匹配就可以提取出相應的數據。
至此,我們完成了該數據准備工作,,下一步就是開始模擬登陸,如下:
postdata['_csrf']=get_csrf() postdata['LoginForm[verifyCode]']=get_captcha() result=session.post(url_login,data=postdata,headers=headers)
第三部分:后期處理
html拿到手之后,剩下的就是進行對html解析,將自己需要的信息通過正則匹配拿出來就行。
之后在寫一個批處理,做到一鍵查詢的功能,效果如下:
至此,最終完成了一個簡易版的一鍵流量查詢。
展望:此程序由於沒有進行自動的驗證碼識別,所以輸入驗證碼是一大瑕疵,如果能夠做到自動識別驗證碼,那么將是真正的一鍵查詢,下一步主要就此問題進行解決。