綜述
最近山大軟體園校區QLSC_STU無線網掉線掉的厲害,連上之後平均十分鐘左右掉線一次,很是讓人心煩,還能不能愉快地上自習了?能忍嗎?反正我是不能忍了,嗯,自己動手,豐衣足食!寫個程式解決掉它!
假若你不能連這個無線,那就照照思路啦~
決戰前夕
首先我們看一下那個驗證頁面是咋樣滴,上個圖先

嘿,這界面還算可以把,需要我們輸入的東西就是倆,一個就是學号,另一個是身份證号後六位,然後就可以登入,享受免費的無線網啦。
不過不知道誰設定了個登入時長,一段時間後就會掉線了,于是,自動模拟登陸系統就要應運而生啦。
來,我們先點選一下連接配接,看一下浏覽器怎麼工作的。
按下F12,監聽網絡,我們點選第一個響應,也就是login.jsp,看一下。
嗯,一目了然POST的資料和送出的位址。 讓我們來分析幾個資料吧:
ClientIP:目前用戶端的IP位址,在山大軟體園校區這個位址是211.87開頭的
timeoutvalue:連接配接等待時間,也就是俗話說的timeout
StartTime:登入時間,也就是在你登入的那一刻的時間戳,這個時間戳是13位的,精确到了毫秒,不過一般是10位的,我們加3個0就好了
shkOvertime:登入持續時間,這個資料預設是720,也就是12分鐘之後,登入就失效了,自動掉線,我們可以手動更改
username:學号
password:密碼,也就是我們身份證号後六位
我們需要在登入的時候把form表單中的所有資訊都POST一下,然後就可以完成登入啦。 萬事俱備,隻欠東風,來來來,程式寫起來!
一觸即發
說走咱就走啊,天上的星星參北鬥啊!
登陸位址:Request URL:
http://192.168.8.10/portal/login.jsp?Flag=0 首先,我們需要驗證一下IP位址,先寫一個擷取IP位址的函數,首先判斷目前IP是不是211.87開頭的,如果是的話,證明連接配接的IP是有效的。 首先我們寫一個擷取本機IP的方法:self.ip_pre = "211.87"
#擷取本機無線IP
def getIP(self):
local_iP = socket.gethostbyname(socket.gethostname())
if self.ip_pre in str(local_iP):
return str(local_iP)
ip_lists = socket.gethostbyname_ex(socket.gethostname())
for ip_list in ip_lists:
if isinstance(ip_list, list):
for i in ip_list:
if self.ip_pre in str(i):
return str(i)
elif type(ip_list) is types.StringType:
if self.ip_pre in ip_list:
return ip_list
這個方法利用了gethostbyname和gethostbyname_ex方法,擷取了各個網卡的IP位址,周遊一下,找到那個211.87開頭的IP,傳回 接下來,擷取到IP之後,我們便可以建構form,然後進行模拟登陸了。
#模拟登入
def login(self):
print self.getCurrentTime(), u"正在嘗試認證QLSC_STU無線網絡"
ip = self.getIP()
data = {
"username": self.username,
"password": self.password,
"serverType": "",
"isSavePass": "on",
"Submit1": "",
"Language": "Chinese",
"ClientIP": self.getIP(),
"timeoutvalue": 45,
"heartbeat": 240,
"fastwebornot": False,
"StartTime": self.getNowTime(),
#持續時間,超過這個時間自動掉線,可進行設定
"shkOvertime": self.overtime,
"strOSName": "",
"iAdptIndex": "",
"strAdptName": "",
"strAdptStdName": "",
"strFileEncoding": "",
"PhysAddr": "",
"bDHCPEnabled": "",
"strIPAddrArray": "",
"strMaskArray": "",
"strMask": "",
"iDHCPDelayTime": "",
"iDHCPTryTimes": "",
"strOldPrivateIP": self.getIP(),
"strOldPublicIP": self.getIP(),
"strPrivateIP": self.getIP(),
"PublicIP": self.getIP(),
"iIPCONFIG":0,
"sHttpPrefix": "http://192.168.8.10",
"title": "CAMS Portal"
}
#消息頭
headers = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36',
'Host': '192.168.8.10',
'Origin': 'http://192.168.8.10',
'Referer': 'http://192.168.8.10/portal/index_default.jsp?Language=Chinese'
}
post_data = urllib.urlencode(data)
login_url = "http://192.168.8.10/portal/login.jsp?Flag=0"
request = urllib2.Request(login_url, post_data, headers)
response = urllib2.urlopen(request)
result = response.read().decode('gbk')
比較多的内容就在于form表單的資料内容以及請求頭,後來利用urllib2的urlopen方法實作模拟登陸。
如果大家對此不熟悉,可以參見
Urllib的基本使用:
http://cuiqingcai.com/947.html這樣,登入後的結果就會儲存在result變量中,我們隻需要從result中提取出我們需要的資料就可以了。
乘勝追擊
接下來,我們就分析一下資料啦,結果有這麼幾種:
1.登入成功 2.已經登入 3.使用者不存在 4.密碼錯誤 5.未知錯誤
好,利用result分析一下結果
#列印登入結果
def getLoginResult(self, result):
if u"使用者上線成功" in result:
print self.getCurrentTime(),u"使用者上線成功,線上時長為",self.overtime/60,"分鐘"
elif u"您已經建立了連接配接" in result:
print self.getCurrentTime(),u"您已經建立了連接配接,無需重複登陸"
elif u"使用者不存在" in result:
print self.getCurrentTime(),u"使用者不存在,請檢查學号是否正确"
elif u"使用者密碼錯誤" in result:
pattern = re.compile('<td class="tWhite">.*?2553:(.*?)</b>.*?</td>', re.S)
res = re.search(pattern, result)
if res:
print self.getCurrentTime(),res.group(1),u"請重新修改密碼"
else:
print self.getCurrentTime(),u"未知錯誤,請檢查學号密碼是否正确"
通過字元串比對和正規表達式,我們分辨并提取出了上述五種情況。
增加循環檢測 既然是檢測網絡是否斷開,那麼我們隻需要每隔一段時間檢測一下就好了,那就10秒吧。
因為這個10秒是可配置的,為了友善配置,統一配置到__init__方法裡面。
#檢測間隔時間,機關為秒
self.every = 10
然後,我們寫一個循環來檢測一下
while True:
nowIP = self.getIP()
if not nowIP:
print self.getCurrentTime(), u"請檢查是否正常連接配接QLSC_STU無線網絡"
else:
print self.getCurrentTime(),u"成功連接配接了QLSC_STU網絡,本機IP為",nowIP
self.login()
while True:
can_connect = self.canConnect()
if not can_connect:
nowIP = self.getIP()
if not nowIP:
print self.getCurrentTime(), u"目前已經斷線,請確定連接配接上了QLSC_STU網絡"
else:
print self.getCurrentTime(), u"目前已經斷線,正在嘗試重新連接配接"
self.login()
else:
print self.getCurrentTime(), u"目前網絡連接配接正常"
time.sleep(self.every)
time.sleep(self.every)
其中我們用到了canConnect方法,這個就是檢測網絡是否已經斷開的方法,我們可以利用ping百度的方法來檢測一下。
方法實作如下
#判斷目前是否可以聯網
def canConnect(self):
fnull = open(os.devnull, 'w')
result = subprocess.call('ping www.baidu.com', shell = True, stdout = fnull, stderr = fnull)
fnull.close()
if result:
return False
else:
return True
好啦,所有的要點我們已經逐一擊破,等着凱旋吧
收拾戰場
好了,所有的代碼要點已經被我們攻破了,接下來就整理一下,讓他們組合起來,變成一個應用程式吧。
__author__ = 'CQC'
#-*- coding:utf-8 -*-
import urllib
import urllib2
import socket
import types
import time
import re
import os
import subprocess
class Login:
#初始化
def __init__(self):
#學号密碼
self.username = '201200131012'
self.password = 'XXXXXX'
#山大無線STU的IP網段
self.ip_pre = '211.87'
#登入時長
self.overtime = 720
#檢測間隔時間,機關為秒
self.every = 10
#模拟登入
def login(self):
print self.getCurrentTime(), u"正在嘗試認證QLSC_STU無線網絡"
ip = self.getIP()
data = {
"username": self.username,
"password": self.password,
"serverType": "",
"isSavePass": "on",
"Submit1": "",
"Language": "Chinese",
"ClientIP": self.getIP(),
"timeoutvalue": 45,
"heartbeat": 240,
"fastwebornot": False,
"StartTime": self.getNowTime(),
#持續時間,超過這個時間自動掉線,可進行設定
"shkOvertime": self.overtime,
"strOSName": "",
"iAdptIndex": "",
"strAdptName": "",
"strAdptStdName": "",
"strFileEncoding": "",
"PhysAddr": "",
"bDHCPEnabled": "",
"strIPAddrArray": "",
"strMaskArray": "",
"strMask": "",
"iDHCPDelayTime": "",
"iDHCPTryTimes": "",
"strOldPrivateIP": self.getIP(),
"strOldPublicIP": self.getIP(),
"strPrivateIP": self.getIP(),
"PublicIP": self.getIP(),
"iIPCONFIG":0,
"sHttpPrefix": "http://192.168.8.10",
"title": "CAMS Portal"
}
#消息頭
headers = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36',
'Host': '192.168.8.10',
'Origin': 'http://192.168.8.10',
'Referer': 'http://192.168.8.10/portal/index_default.jsp?Language=Chinese'
}
post_data = urllib.urlencode(data)
login_url = "http://192.168.8.10/portal/login.jsp?Flag=0"
request = urllib2.Request(login_url, post_data, headers)
response = urllib2.urlopen(request)
result = response.read().decode('gbk')
self.getLoginResult(result)
#列印登入結果
def getLoginResult(self, result):
if u"使用者上線成功" in result:
print self.getCurrentTime(),u"使用者上線成功,線上時長為",self.overtime/60,"分鐘"
elif u"您已經建立了連接配接" in result:
print self.getCurrentTime(),u"您已經建立了連接配接,無需重複登陸"
elif u"使用者不存在" in result:
print self.getCurrentTime(),u"使用者不存在,請檢查學号是否正确"
elif u"使用者密碼錯誤" in result:
pattern = re.compile('<td class="tWhite">.*?2553:(.*?)</b>.*?</td>', re.S)
res = re.search(pattern, result)
if res:
print self.getCurrentTime(),res.group(1),u"請重新修改密碼"
else:
print self.getCurrentTime(),u"未知錯誤,請檢查學号密碼是否正确"
#擷取目前時間戳,13位
def getNowTime(self):
return str(int(time.time()))+"000"
#擷取本機無線IP
def getIP(self):
local_iP = socket.gethostbyname(socket.gethostname())
if self.ip_pre in str(local_iP):
return str(local_iP)
ip_lists = socket.gethostbyname_ex(socket.gethostname())
for ip_list in ip_lists:
if isinstance(ip_list, list):
for i in ip_list:
if self.ip_pre in str(i):
return str(i)
elif type(ip_list) is types.StringType:
if self.ip_pre in ip_list:
return ip_list
#判斷目前是否可以聯網
def canConnect(self):
fnull = open(os.devnull, 'w')
result = subprocess.call('ping www.baidu.com', shell = True, stdout = fnull, stderr = fnull)
fnull.close()
if result:
return False
else:
return True
#擷取目前時間
def getCurrentTime(self):
return time.strftime('[%Y-%m-%d %H:%M:%S]',time.localtime(time.time()))
#主函數
def main(self):
print self.getCurrentTime(), u"您好,歡迎使用模拟登陸系統"
while True:
nowIP = self.getIP()
if not nowIP:
print self.getCurrentTime(), u"請檢查是否正常連接配接QLSC_STU無線網絡"
else:
print self.getCurrentTime(),u"成功連接配接了QLSC_STU網絡,本機IP為",nowIP
self.login()
while True:
can_connect = self.canConnect()
if not can_connect:
nowIP = self.getIP()
if not nowIP:
print self.getCurrentTime(), u"目前已經掉線,請確定連接配接上了QLSC_STU網絡"
else:
print self.getCurrentTime(), u"目前已經掉線,正在嘗試重新連接配接"
self.login()
else:
print self.getCurrentTime(), u"目前網絡連接配接正常"
time.sleep(self.every)
time.sleep(self.every)
login = Login()
login.main()
來,我們來運作一下,看下效果吧! 執行
python login.py
目前是可以聯網的,我分别在網頁上操作執行了斷開,操作,程式自動檢測到掉線,自動重新連接配接。
接下來我直接斷開了QLSC_STU網絡的連結,程式同樣檢測到QLSC_STU這個熱點沒有連接配接上,提示使用者連結。
接下來我重新連接配接上了這個熱點,由于剛才已經登入上線,且持續時間較短,網絡自動恢複正常。
下面是運作結果:
嗯,這樣我們就是實作了自動掉線的檢測和模拟登入。
凱旋而歸
咿呀伊爾喲,想約妹子上自習嗎?那就趕緊來試試吧!一網在手,天下我有!追男神女神都不再是夢想!
如果有問題,歡迎留言讨論,代碼肯定有不完善的地方,僅供參考。
原文釋出時間為:2018-12-7
本文作者:燈塔大資料
本文來自雲栖社群合作夥伴“
燈塔大資料”,了解相關資訊可以關注“DTbigdata”微信公衆号