1.前言
最近开始选课了,就用python写了个不成熟的选课系统
2.源码
#!/usr/bin/env python
import hashlib
import json
import sys
import time
import threading
import getpass
from urllib import request
from urllib import error
from urllib import parse
from http import cookiejar
from bs4 import BeautifulSoup
#线程类
class MyThread(threading.Thread):
def __init__(self,t,func,args):
threading.Thread.__init__(self)
self.func=func
self.args=args
self.t=t
self.flag=True
def run(self):
print('后台正在觊觎该课程...')
while(self.flag):
self.f=self.func(*self.args)
self.res=self.f['result']
print(self.f['msg'])
time.sleep(self.t)
def stop(self):
self.flag=False
listIng.remove(self)
# 打印本线程所承载的课程信息
def printInfo(self, i):
print("课程序列:" + str(i) + "课程号:" + self.args[0] + "课序号:" + self.args[1])
#打印已成功选取的课程信息
def printSuccessInfo(self,i):
if(self.flag==False):
self.printInfo(i)
#打印正在爬取的课程信息
def printIngInfo(self,i):
if(self.flag==True):
self.printInfo(i)
# 链接教务系统并保存cookie
# 一个公共的header信息
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0',
'Connection': 'keep-alive','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Host':'bkjwxk.sdu.edu.cn'}
loginUrl = "http://bkjwxk.sdu.edu.cn/b/ajaxLogin"
#输入用户名密码等信息
def getInfo():
name=getpass.getpass('请输入教务系统用户名\n')
password=getpass.getpass('请输入教务系统密码\n')
return (name,password)
# 登录教务系统取得cookie
def getCookie(a):
print('正在登陆...')
n=a[0]
p=a[1]
data = {}
data['j_username'] = n
data['j_password'] = encrypt(p)
loginData = parse.urlencode(data).encode('utf-8')
cookie = cookiejar.CookieJar()
cookie_support = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(cookie_support)
req = request.Request(url=loginUrl, data=loginData, headers=header)
try:
res = opener.open(req)
result = res.read().decode('utf-8')
if (result == '"success"'):
return cookie;
else:
return None;
except error.URLError as e:
print(e)
return cookie
#查看我的必修
def checkObligatory(cookie):
url='http://bkjwxk.sdu.edu.cn/f/xk/xs/jxjhkc/%E5%BF%85%E4%BF%AE'
handler=request.HTTPCookieProcessor(cookie)
opener=request.build_opener(handler)
req=request.Request(url=url,headers=header)
res=opener.open(req)
result = res.read().decode('utf-8')
return result
#查看我选择的课程
def checkSelected(cookie):
url="http://bkjwxk.sdu.edu.cn/f/xk/xs/yxkc"
handler=request.HTTPCookieProcessor(cookie)
opener=request.build_opener(handler)
req=request.Request(url=url,headers=header)
res=opener.open(req)
result=res.read().decode('utf-8')
return result
# 选择某门课程
def selectClass(kch, kxh,cookie):
url = 'http://bkjwxk.sdu.edu.cn/b/xk/xs/add/'+str(kch) + "/" + str(kxh)
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
req = request.Request(url=url, headers=header)
res = opener.open(req)
result = res.read().decode('utf-8')
return json.loads(result)
#退选某门课程
def deleteClass(kch,kxh,cookie):
url='http://bkjwxk.sdu.edu.cn/b/xk/xs/delete'
data={}
data['aoData']=''
data['kchkxh']=kch+"|"+kxh
queryData=parse.urlencode(data).encode('utf-8')
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
req = request.Request(url=url,data=queryData,headers=header)
res = opener.open(req)
result = res.read().decode('utf-8')
return json.loads(result)['msg']
#查看我的限选
def checkLimitative(cookie):
url="http://bkjwxk.sdu.edu.cn/f/xk/xs/jxjhkc/%E9%99%90%E9%80%89"
handler=request.HTTPCookieProcessor(cookie)
opener=request.build_opener(handler)
req=request.Request(url=url,headers=header)
res=opener.open(req)
result=res.read().decode('utf-8')
return result
#将必修信息解析
def analyzeObligatory(html):
soup=BeautifulSoup(html,'lxml')
resultList=soup.select('tr')
list=[]
for i in range(1,len(resultList)):
eachHtml=resultList[i]
#解析
soup2=BeautifulSoup(str(eachHtml),'lxml')
resultList2 = soup2.find_all("td")
each={}
each['KCH']=resultList2[1].string
each['KCM']=resultList2[2].string
list.append(each)
return list
#解析我已经选择的课程
def analyzeSelected(html):
soup=BeautifulSoup(str(html),'lxml')
resultList=soup.select('tr')
list=[]
for i in range(1,len(resultList)):
eachHtml=resultList[i]
soup2=BeautifulSoup(str(eachHtml),'lxml')
resultList2=soup2.find_all("td")
each={}
each['KCH']=resultList2[2].string
each['KCM']=resultList2[3].string
each['KXH']=resultList2[4].string
each['XF']=resultList2[5].string
each['SJDD']=resultList2[6].string
each['JSM']=resultList2[7].string
each['KCLBMC']=resultList2[8].string
each['KKXSM']=resultList2[9].string
list.append(each)
return list
def analyzeLimitative(html):
soup = BeautifulSoup(str(html), 'lxml')
resultList = soup.select('tr')
list = []
for i in range(1, len(resultList)):
eachHtml = resultList[i]
soup2 = BeautifulSoup(str(eachHtml), 'lxml')
resultList2 = soup2.find_all("td")
each = {}
if(len(resultList2)<8):
for eachObj in getCoursebyKx(resultList2[1].string,1,cookie):
list.append(eachObj)
else:
each['KCH'] = resultList2[1].string
each['KCM'] = resultList2[2].string
each['KXH'] = resultList2[3].string
each['XF'] = resultList2[4].string
each['SJDD'] = resultList2[5].string
each['kyl']=resultList2[6].string
each['JSM'] = resultList2[7].string
each['KCLBMC'] = resultList2[8].string
each['KKXSM'] = resultList2[9].string
list.append(each)
return list
#根据课序号查询必须课程信息
def getCoursebyKxOb(kch,cookie):
url="http://bkjwxk.sdu.edu.cn/b/xk/xs/jxjhkc/%E5%BF%85%E4%BF%AE/"+str(kch)
cookie_support = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(cookie_support)
req = request.Request(url=url, headers=header)
try:
res = opener.open(req)
result = res.read().decode('utf-8')
return json.loads(result)['object']
except error.URLError as e:
print(e)
#根据课序号查询课程具体信息
def getCoursebyKx(kch,page,cookie):
queryUrl="http://bkjwxk.sdu.edu.cn/b/xk/xs/kcsearch"
#组装参数
data={}
data['type']='kc'
data['currentPage']=page
data['kch']=kch
data['jsh']=''
data['skxq']=''
data['skjc']=''
data['kkxsh']=''
queryData = parse.urlencode(data).encode('utf-8')
cookie_support = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(cookie_support)
req = request.Request(url=queryUrl, data=queryData, headers=header)
try:
res = opener.open(req)
result = res.read().decode('utf-8')
return json.loads(result)['object']['resultList']
except error.URLError as e:
print(e)
# 根据关键词查询课程信息 返回包裹课程信息的json对象
def getCoursebyKey(k, cookie):
queryUrl = "http://bkjwxk.sdu.edu.cn/b/xk/xs/kcapkc/sarchkcm?keyword=" + parse.quote(k)
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
req = request.Request(url=queryUrl, headers=header)
res = opener.open(req)
result=res.read().decode('utf-8')
jsonObj=json.loads(result)
return jsonObj['object']
#打印出单个课程详细信息 para->{}
def printAll_single(each):
print("课程号:" + each['KCH'])
print("课程名称:" + each['KCM'])
if 'KXH' in each.keys():
print("课序号:" + str(each['KXH']))
print("学分:" + str(each['XF']))
print("上课时间/地点:" + each['SJDD'])
if 'kyl' in each.keys():
print("课余量:" + str(each['kyl']))
if 'JSM' in each.keys():
print("任课教师:" +str(each['JSM']))
print("课程类别:" + each['KCLBMC'])
print("开设学院:" + each['KKXSM'] + "\n\n\n\n")
#打印出课程详细信息
def printAll(jsonObj):
for i in range(0,len(jsonObj)):
each=jsonObj[i]
print('课程序列:' + str(i + 1))
printAll_single(each)
return inputControl('输入课程序列号以对该门课程进行选课,退选操作,"-1"返回上一层',-1,len(jsonObj)+1)
#打印出课程简略信息
def printSimp(jsonObj):
for i in range(0,len(jsonObj)):
json=jsonObj[i]
print("课程序列:"+str(i+1)+"\t\t课程号:"+json['KCH']+"\t\t课程名:"+json['KCM'])
return inputControl('输入课程序列号查看课程详细信息,输入"-1"即可返回上一层',-1,len(jsonObj)+1)
#提示信息
def printInfo():
return inputControl("1.查看我的必修课程\n2.查看我的限选课程\n3.课程搜索\n4.查看我已选择的课程\n5.查看我觊觎的课程\n6.退出",1,6)
#判断输入的数据是否为数字
def isdigest(str):
try:
int(str)
return True
except ValueError:
return False
#用户进行某一操作完毕后输出提示信息,并返回下一指令 info->提示语句 begin->指令的起点 end->指令的终点
def inputControl(info,begin,end):
controlStr = input(info+"\n")
if isdigest(controlStr) and int(controlStr)>=begin and int(controlStr)<=end:
return int(controlStr)
else:
print("指令有误,请重新输入")
return inputControl(info,begin,end)
# 加密手段
def encrypt(s):
md5 = hashlib.md5()
md5.update(s.encode(encoding='utf-8'))
return md5.hexdigest()
#用户查看必修信息
def seeObligatory(cookie):
listSimp = analyzeObligatory(checkObligatory(cookie))
simpNext = printSimp(listSimp)
if simpNext == -1:
init(cookie)
else:
simpNext -= 1
seeAll(listSimp[simpNext]['KCH'],"1",cookie,-1,False)
#查看详细信息函数 f->是否为搜索状态
def seeAll(kch,page,cookie,flag,f=True):
if(f):
listDetail = getCoursebyKx(kch, page, cookie)
else:
listDetail=getCoursebyKxOb(kch,cookie)
if(flag==-1):
detailNext = printAll(listDetail)
else:
detailNext=flag
if detailNext == -1:
seeObligatory(cookie)
else:
detailNext -= 1
print(str(detailNext)+"!"+str(len(listDetail)))
print('当前操作课程:\t')
printAll_single(listDetail[detailNext])
Elective(ElectiveInfo(),kch,listDetail[detailNext]['KXH'],cookie)
#用户选择选课or退课
def ElectiveInfo():
return inputControl('1.选课\n2.退课\n3.觊觎该课程\n4.返回上一层\n',1,4)
#选课,退课 flag==1选课 flag==2退课 flag==-1返回上一层
def Elective(flag,kc,kx,cookie):
#选课
if flag==1:
print(selectClass(kc,kx,cookie)['msg'])
init(cookie)
elif flag==2:
print(deleteClass(kc,kx,cookie))
init(cookie)
elif flag==3:
covetClass(30,kc,kx,cookie)
init(cookie)
elif flag==4:
seeAll(kc,"1",cookie,-1)
else:
sys.exit(0)
#用户查看限选信息
def seeLimitative(cookie):
listAll = analyzeLimitative(checkLimitative(cookie))
allNext = printAll(listAll)
if allNext == -1:
init(cookie)
else:
allNext -= 1
Elective(ElectiveInfo(), listAll[allNext]['KCH'], listAll[allNext]['KXH'], cookie)
#用户查看我已选择的课程
def seeMySelect(cookie):
listAll=analyzeSelected(checkSelected(cookie))
if(len(listAll)==0):
print('当前没有已选择的课程')
return
allNext=printAll(listAll)
if allNext==-1:
init(cookie)
else:
allNext-=1
Elective(ElectiveInfo(),listAll[allNext]['KCH'],listAll[allNext]['KXH'],cookie)
#课程搜索
def searchClass(cookie):
control=inputControl("1.按课程号搜索\n2.按关键词搜索\n3.返回上一层",1,3)
if control==1:
kx=input('请输入课程号\n')
listAll=getCoursebyKx(kx,"1",cookie)
seeSearchAll(printAll(listAll),listAll,cookie,0)
elif control==2:
key=input("请输入课程关键词\n")
listSimp=getCoursebyKey(key,cookie)
seeSearchAll(printSimp(listSimp),listSimp,cookie,1)
else:
init(cookie)
#课程搜索查看详细信息
def seeSearchAll(flag,list,cookie,mode):
if flag==-1:
searchClass(cookie)
else:
if(mode==0):
seeAll(list[flag-1]['KCH'],'1',cookie,flag)
else:
seeAll(list[flag - 1]['KCH'], '1', cookie, -1)
#查看正在觊觎的课程信息
def seeWantClass(cookie):
if(len(listIng)==0):
print('当前没有正在觊觎的课程!!\n\n')
init(cookie)
return
print("当前正在觊觎的课程如下\n")
print(len(listIng))
for i in range(0,len(listIng)):
each=listIng[i]
each.printIngInfo(i+1)
control=inputControl("输入课程序列号即可对正在觊觎的课程进行操作,-1返回上一层",-1,len(listIng)+1)
if(control==-1):
init(cookie)
else:
control2=inputControl("1.取消对该课程的觊觎\n2.返回上一层\n",1,2)
if(control2==2):
seeWantClass(cookie)
else:
print("成功取消对该课程的觊觎")
listIng[control-1].stop()
init(cookie)
#觊觎某课程 time->时间间隔
def covetClass(time,kch,kxh,cookie):
t=MyThread(time,selectClass,(kch,kxh,cookie))
listIng.append(t)
t.start()
#用户第一次登录函数
def init(cookie):
control = printInfo()
if control == 1:
seeObligatory(cookie)
elif control == 2:
seeLimitative(cookie)
elif control == 3:
searchClass(cookie)
elif control == 4:
seeMySelect(cookie)
elif control == 5:
seeWantClass(cookie)
else:
sys.exit(0)
if __name__ == '__main__':
print('欢迎登陆选课系统')
info=getInfo()
cookie = getCookie(info)
listIng=[]
listSucc=[]
while (cookie == None):
print('登录失败,用户名或密码错误,请检查后重新输入')
cookie = getCookie(getInfo())
print('登录成功!')
init(cookie)
input()