最终目标希望完成如下几个功能:
- (1)登录校园网
- (2)登出校园网
- (3)查询当前网络状态
- (4)查询流量、帐户余额、当前用户组等基本信息
- (5)查询本账号当前在线IP信息
- (6)查询每日流量使用明细,并生成直方图
使用方法
使用前请到同级目录下USERNAME_PASSWORD.txt文件中修改你的校园网账号和密码。
可将tunet.py设置为外部命令,参数如下:
-h, --help : 显示帮助
-v, --version: 显示当前清华大学联网助手版本号
-u : 输入用户名
-p : 输入密码
-a : 稍后输入用户名和密码,可以登录其他校园网帐户
-i, --login : 联网操作(当不带任何其他操作时,默认进行联网操作)
-o, --logout : 断网操作
-c, --check : 检查当前网络状态
-q, --query : 查询流量、帐户余额、当前用户组等基本信息,查询本账号当前在线IP信息,查询每日流量使用明细,并生成直方图,查询结果保存在USER_DETAIL_INFOMATION.LOG文件下
说明
(1)USER_DETAIL_INFOMATION.LOG文件保存最近一次综合查询结果
(2)USERNAME_PASSWORD.txt文件保存用户的账号和密码
版本v1.2更新内容
(1)增加了账户和密码的文件管理
(2)性能调整
(3)当不带任何参数时,默认连接校园网,简化输入
3 版本v1.1更新内容:
(1)增加了综合查询功能:查询流量、帐户余额、当前用户组等基本信息,查询本账号当前在线IP信息,查询每日流量使用明细,并生成直方图,查询结果保存在USER_DETAIL_INFOMATION.LOG文件中
版本v1.0更新内容:
(1)提供基本的联网、断网和检查当前网络状态的操作
QUERY
import sys, time, os
import urllib.request, hashlib, http.cookiejar
import codecs, re
query_login_url = 'https://usereg.tsinghua.edu.cn/do.php'
user_info_url = 'https://usereg.tsinghua.edu.cn/user_info.php'
online_state_url = 'https://usereg.tsinghua.edu.cn/online_user_ipv4.php'
query_logout_url = 'https://usereg.tsinghua.edu.cn/do.php'
info_header = [ '#' * 89,
'#\t\t\t\tUser Flux Detail Infomation\t\t\t\t#',
'#' * 89]
#########################################################
# File I/O Modules #
#########################################################
def create_path(relative_path):
base_path = os.path.abspath(os.path.dirname(sys.argv[0]))
return os.path.join(base_path, relative_path)
def write_inline(file_handler, contents):
for line in contents:
file_handler.write(line + '\r\n')
def save_query(contents):
relative_path = 'USER_DETAIL_INFOMATION.LOG'
file_handler = open(create_path(relative_path), 'w')
write_inline(file_handler, info_header)
file_handler.write('\t\t\t\tDatetime: ' + time.strftime('%Y-%m-%d %H:%M:%S') + '\r\n' + '-' * 89 + '\r\n')
write_inline(file_handler, contents)
file_handler.write('\r\n')
file_handler.close()
#########################################################
# Connection Modules #
#########################################################
def create_opener():
cookie = http.cookiejar.CookieJar()
cookie_proc = urllib.request.HTTPCookieProcessor(cookie)
return urllib.request.build_opener(cookie_proc)
def response_login(login_data):
request_url = urllib.request.Request(query_login_url, login_data.encode())
response_url = urllib.request.urlopen(request_url)
return response_url.read().decode()
#########################################################
# Main Login/Logout Modules #
#########################################################
def query_login(username, password):
hashcd_md5 = hashlib.md5()
hashcd_md5.update(password.encode())
tr_password = hashcd_md5.hexdigest()
login_data = 'user_login_name=' + username + '&user_password=' + tr_password + '&action=login'
urllib.request.install_opener(create_opener())
answer = response_login(login_data)
if answer == 'ok':
return True
else:
return False
def query_logout():
logout_data = 'action=logout'
request_url = urllib.request.Request(query_logout_url, logout_data.encode())
response_url = urllib.request.urlopen(request_url)
print ('Your flux details and other infomations are saved in USER_DETAIL_INFOMATION.LOG under the SAME directory')
#########################################################
# Data Post-Process Modules #
#########################################################
def post_process(info):
end_time = time.strftime('%Y-%m-%d')
start_time = end_time[:8:] + '01'
flux_detail_url = 'https://usereg.tsinghua.edu.cn/user_detail_list.php?action=balance2&user_login_name=&user_real_name=&desc=&order=&start_time=' + start_time + '&end_time=' + end_time + '&user_ip=&user_mac=&nas_ip=&nas_port=&is_ipv6=0&page=1&offset=200'
response_usr = urllib.request.urlopen(user_info_url)
response_state = urllib.request.urlopen(online_state_url)
response_details = urllib.request.urlopen(flux_detail_url)
info = flux_account_query(info, response_usr)
info = online_state_query(info, response_state)
info = flux_detail_query(info, response_details)
return info
#########################################################
# Integrated Query Modules #
#########################################################
flux_account_keys = ('用户名', '用户组', '姓名', '证件号', '当前计费组', '使用时长(IPV4)', '使用流量(IPV4)',
'使用时长(IPV6)', '使用流量(IPV6)', '帐户余额')
online_state_keys = ()
flux_detail_keys = ()
#Auxiliary Function
def turn_key(key):
if key[-5:-1] == 'byte':
flux, unit = key.split('(')
flux = float(flux) / 1024 / 1024
new_key = '-->' + str(int(flux)) + '(MB)'
key += new_key
return key
def get_days(year, month):
month_length = (31,28,31,30,31,30,31,31,30,31,30,31)
month_length_leap = (31,29,31,30,31,30,31,31,30,31,30,31)
if year % 400 == 0 or year % 100 != 0 and year % 4 == 0:
return month_length_leap[month-1]
else:
return month_length[month-1]
def solve_flux(flux):
unit = flux[-1]
val = float(flux[:len(flux)-1:])
if unit == 'B':
val /= 1024 * 1024
elif unit == 'K':
val /= 1024
elif unit == 'G':
val *= 1024
return int(val)
def trans_content(response):
raw = response.read().decode('gb2312')
raw = re.sub('<[^>]+>| |[\n\t]+|-->',' ',raw)
raw = re.sub(' +', ' ', raw)
return raw
def push_front(figure, line):
tf = []
tf.append(line)
return tf + figure
def display_fluxAccount_onlineState(info):
print()
for line in info:
if line[0] != '-':
print(line)
else:
print()
def display_flux_detail(fluxin, year, month, day):
maxflux = 0
divide = 10
figure = []
for flux in fluxin:
if flux > maxflux:
maxflux = flux
top = str(int(maxflux)) + 'MB|'
length = len(top)
mid = str(int(maxflux / 2)) + 'MB|'
mid = ' ' * (length - len(mid)) + mid
bottom = '0MB|'
bottom = ' ' * (length - len(bottom)) + bottom
unit = maxflux / divide
for i in range(day):
fluxin[i] = int(fluxin[i] / unit)
for i in range(divide):
line = ''
if i == divide - 1:
line = top
elif i == int((divide - 1) / 2):
line = mid
elif i == 0:
line = bottom
else:
line = ' ' * (length - 1) + '|'
for j in range(day):
if fluxin[j] > 0:
line += '**'
fluxin[j] -= 1
else:
line += ' '
figure = push_front(figure, line)
figure = push_front(figure, '**每日流量使用统计列表**')
figure.append(' ' * length + '--' * day)
date_front = str(year) + '-' + str(month) +'-' + '1'
date_rear = str(year) + '-' + str(month) +'-' + str(day)
date_mid = str(year) + '-' + str(month) +'-' + '15'
figure.append(' %s\t\t\t%s\t\t\t%s' %(date_front, date_mid, date_rear))
for line in figure:
print(line)
print()
#Integrated Query
def flux_account_query(info, response):
info.append('**用户基本信息**')
done = trans_content(response)
match = re.search('用户名.*?(元) ', done)
done = match.group()
tlist = done.split(' ')
line = ''
for key in tlist:
if line != '':
key = turn_key(key)
line = line + '\t: ' + key
info.append(line)
line = ''
elif key in flux_account_keys:
line = key
info.append('-' * 89)
return info
def online_state_query(info, response):
info.append('**用户在线状态**')
done = trans_content(response)
match = re.search('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}.*\d{2}:\d{2}', done)
if match == None:
info.append('当前没有任何IP在线')
else:
info.append('在线IP地址\t登陆日期\t登陆时间')
done = match.group()
tlist = done.split(' ')
line = ''
count = 0
for key in tlist:
if count == 0:
if re.search('\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}', key) != None:
line = key
count += 1
elif count == 1:
if re.search('\d{4}-\d{2}-\d{2}', key) != None:
line += '\t' + key
count += 1
elif count == 2:
if re.search('\d{2}:\d{2}:\d{2}', key) != None:
line += '\t' + key
info.append(line)
line = ''
count = 0
info.append('-' * 89)
display_fluxAccount_onlineState(info);
return info
def flux_detail_query(info, response):
info.append('**每日流量使用统计列表**')
info.append('登出日期\t入流量\t出流量')
done = trans_content(response)
year, month = time.strftime('%Y %m').split(' ')
days = get_days(int(year), int(month))
tlist = done.split(' ')
fluxin_perday = [0 for i in range(days)]
fluxout_perday = [0 for i in range(days)]
offline_date = True
count = 0
for key in tlist:
if re.search('\d{4}-\d{2}-\d{2}', key) and offline_date:
offline_date = False
elif re.search('\d{4}-\d{2}-\d{2}', key) and not offline_date:
offline_date = True
year, month, day = key.split('-')
iday = int(day)
elif re.search('\d+[.]\d*[BKMG]', key) and count == 0:
fluxin_perday[iday-1] += solve_flux(key)
count += 1
elif re.search('\d+[.]\d*[BKMG]', key) and count == 1:
fluxout_perday[iday-1] += solve_flux(key)
count += 1
elif re.search('\d+[.]\d*[BKMG]', key) and count == 2:
count = 0
for i in range(days):
if i + 1 < 10:
d = '0' + str(i + 1)
else:
d = str(i + 1)
info.append('%s\t%s\t%s' %(time.strftime('%Y-%m-') + d, str(fluxin_perday[i]) + 'MB', str(fluxout_perday[i]) + 'MB'))
display_flux_detail(fluxin_perday, int(year), int(month), days)
return info
#########################################################
# Main Part #
#########################################################
def tunet_query(username, password):
print('FETCHING DATA FROM http://usereg.tsinghua.edu.cn, PLEASE WAIT FOR A MOMENT...')
is_login = query_login(username, password)
if is_login:
info = []
info = post_process(info)
save_query(info)
query_logout()
else:
print ('CAN\'T CAPTURE YOUR FLUX DATA, PLEASE TRY AGAIN LATER')
def pytunet_query():
username = 'hhy14'
password = '123456'
tunet_query(username, password)
if __name__ == '__main__':
pytunet_query()
CONNECT
import time
import urllib.request, hashlib
import codecs
login_url = 'http://net.tsinghua.edu.cn/cgi-bin/do_login'
logout_url = 'http://net.tsinghua.edu.cn/cgi-bin/do_logout'
check_url = 'http://net.tsinghua.edu.cn/cgi-bin/do_login'
query_url = 'https://usereg.tsinghua.edu.cn/login.php'
times_cnt = {1: 'FIRST', 2: 'SECOND', 3: 'THIRD', 4: 'FORTH', 5: 'FIFTH'}
ret_type = {'logout_ok' : 'LOGOUT SUCCESS',
'not_online_error' : 'NOT ONLINE',
'ip_exist_error' : 'IP ALREADY EXISTS',
'user_tab_error' : 'THE CERTIFICATION PROGRAM WAS NOT STARTED',
'username_error' : 'WRONG USERNAME',
'user_group_error' : 'ACCOUNT INFOMATION INCORRECT',
'password_error' : 'WRONG PASSWORD',
'status_error' : 'ACCOUNT OVERDUE, PLEASE RECHARGE',
'available_error' : 'ACCOUNT HAS BEEN SUSPENDED',
'delete_error' : 'ACCOUNT HAS BEEN DELETED',
'usernum_error' : 'USERS NUMBER LIMITED',
'online_num_error' : 'USERS NUMBER LIMITED',
'mode_error' : 'DISABLE WEB REGISTRY',
'time_policy_error': 'CURRENT TIME IS NOT ALLOWED TO CONNECT',
'flux_error' : 'FLUX OVER',
'ip_error' : 'IP NOT VALID',
'mac_error' : 'MAC NOT VALID',
'sync_error' : 'YOUR INFOMATION HAS BEEN MODIFIED, PLEASE TRY AGAIN AFTER 2 MINUTES',
'ip_alloc' : 'THE IP HAS BEEN ASSIGNED TO OTHER USER'
}
version = '1.2'
sleep_time = 8
#########################################################
# Main Login/Logout Modules #
#########################################################
def trans_content(response):
content = response.read().decode()
ret = ''
for ch in content:
if ch.isalpha() or ch == '_':
ret += ch
return ret
def tunet_login(username, password):
hashcd_md5 = hashlib.md5()
hashcd_md5.update(password.encode())
tr_password = hashcd_md5.hexdigest()
login_data = 'username=' + username + '&password=' + tr_password + '&drop=0&type=1&n=100'
login_data = login_data.encode()
request_url = urllib.request.Request(login_url, login_data)
response_url = urllib.request.urlopen(request_url)
ret = trans_content(response_url)
print (ret_type.get(ret, 'CONNECTED'))
return ret
def tunet_logout():
response_url = urllib.request.urlopen(logout_url)
ret = trans_content(response_url)
print (ret_type.get(ret, 'CONNECTED'))
return ret
def tunet_check():
check_data = 'action=check_online'
check_data = check_data.encode()
request_url = urllib.request.Request(check_url, check_data)
response_url = urllib.request.urlopen(request_url)
ret = trans_content(response_url)
if ret == '':
print ('NOT ONLINE')
else:
print (ret_type.get(ret, 'CONNECTED'))
return ret
#########################################################
# Help&Version Modules #
#########################################################
def tunet_help():
print ('-h, --help : show all options of Tsinghua University Internet Connector')
print ('-v, --version: show version of Tsinghua University Internet Connector')
print ('-u : input your username after \'-u\'')
print ('-p : input your password after \'-p\'')
print ('-a : enter username and password later, you can login other campus network account')
print ('-i, --login : login operation')
print ('-o, --logout : logout operation')
print ('-c, --check : check the internet')
print ('-q, --query : query basic infomation, online state and flux usage details')
def tunet_version():
print ('Tsinghua University Internet Connector ', version)
def tunet_others():
print ('UNKNOWN OPTIONS')
print ('WHICH OPTION DO YOU WANT?')
tunet_help()
print ('IF ANY ERROR, PLEASE CONTACT im@huhaoyu.com.')
#########################################################
# Main Part #
#########################################################
def tunet_connect(username, password):
ret = 'ip_exist_error'
for count in range(5):
print ('%s attempts to connect...' % times_cnt.get(count + 1))
if ret != tunet_login(username, password):
break
if count == 4:
print ('please try to reconnect after 1 minute')
break
print ('try to reconnect after %s seconds' %sleep_time)
time.sleep(sleep_time)
print ()
PYTUNET
#########################################################
# Welcome #
# Tsinghua University Internet Connector in Python #
# Version: v1.2 #
# Date: 2015/04/05 #
# By: Haoyu hu Email: im@huhaoyu.com #
# Address: Tsinghua University #
#########################################################
import pytunet_connect
import pytunet_query
import sys, getopt, getpass, os, re
def pytunet():
relative_path = 'USERNAME_PASSWORD.txt'
file_handler = open(pytunet_query.create_path(relative_path), 'r')
lines = file_handler.readlines()
if len(lines) != 2:
print('%s IS DAMAGED, PLEASE CHECK THE CONTENT FORMAT IN THE FILE:' %relative_path)
print('CONTENT FORMAT AS FOLLOWS:')
print('username=huhy14\npassword=123456')
exit(1)
username = re.sub('\s', '', lines[0])
password = re.sub('\s', '', lines[1])
_, username = username.split('=')
_, password = password.split('=')
file_handler.close()
try:
options, args = getopt.getopt(sys.argv[1:], 'achiop:qu:v', ['help', 'login', 'logout', 'check', 'version', 'query'])
except getopt.GetoptError:
pytunet_connect.tunet_others()
sys.exit(1)
want_login = False
want_query = False
flag = False
name, value = None, None
for name, value in options:
if name in ('-h', '--help'):
pytunet_connect.tunet_help()
sys.exit(0)
elif name in ('-v', '--version'):
pytunet_connect.tunet_version()
sys.exit(0)
elif name == '-a':
flag = True
elif name == '-u':
username = value
elif name == '-p':
password = value
elif name in ('-i', '--login'):
want_login = True
elif name in ('-o', '--logout'):
pytunet_connect.tunet_logout()
sys.exit(0)
elif name in ('-c', '--check'):
pytunet_connect.tunet_check()
sys.exit(0)
elif name in ('-q', '--query'):
want_query = True
if flag:
username = input('username: ')
password = getpass.getpass('password: ')
print (password)
if want_query:
pytunet_query.tunet_query(username, password)
if want_login or not want_query and not want_login:
pytunet_connect.tunet_connect(username, password)
# if not want_query and not want_login:
# print ('WARNING: YOU JUST DIDN\'T DO ANYTHING! IF YOU WANT TO CONNECT TO THE CAMPUS NETWORK, THE COMMAND MUST INCLUDE -i OR --login')
# print()
# pytunet_connect.tunet_help()
if __name__ == '__main__':
pytunet()