本文作者:包子也沉默

考试安排查询脚本(CUP)

包子也沉默 3年前 (2019-07-31) ( 07-31 ) 1358 0条评论
摘要: allpython3pip3installrequestspip3installtkinterpip3installfuzzywuzzypip3installxlrd首先,CUP教务处考试安排通知一般是发布在网站的“考试通知”专栏里的。比如:这样的一个通知,通常内部会有一个考试通知的xls表格文件。打开以后:每次考试通知的格式都是一致的。基于此,思路就来了,先输入考试通知发

去年热情高涨的时候心血来潮做了个简易的查询脚本,限于当时技术水平(菜),实现得不是很好,这几天终于想起来填坑了。环境依赖:

道所有clientIdGetChanList-获取所有群聊频道和在线人数GetChanListByClientId(clientId)获取用户参与的所有群聊频道GetChanOnline(频道名)获取

brew install python3
pip3 install requests
pip3 install tkinter
pip3 install fuzzywuzzy
pip3 install xlrd

首先,CUP教务处考试安排通知一般是发布在网站的“考试通知”专栏里的。比如:

Server1订阅redisChanne1imServer2订阅redisChanne2imServer3订阅redisChanne3imServer4订阅redisChanne4业务方(webApi

这样的一个通知,通常内部会有一个考试通知的xls表格文件。

eakres=""forline_numinres_set:line=sheet.row_values(line_num)res+="-"*50+" "

打开以后:

json(历史消息)回执:用户A如何知道消息发送状态(成功或失败或不在线)?imServer端向用户B发送消息时,把状态以消息的方式推给用户A即可(按上面的逻辑),具体请看源码吧。。。发送消息采用re

每次考试通知的格式都是一致的。

ss.extract(aim,data[keys[i]].keys(),limit=3)ts=set()formthinres:ifmth[1]:ts=ts.union(data[keys[i]][m

基于此,思路就来了,先输入考试通知发布网页的地址,然后程序自动获取到文件的下载地址,再自动将文件下载下来,得到考试安排信息。

t;}});ImHelper.EventBus(t=>Console.WriteLine(t.clientId+"上线了"),t=>Console.WriteLine(

代码:

调处理?我们可以这样设定,所有用户的主动行为走业务方(webApi),imServer只负责即时消息推送。什么意思?用户A向好友B发送消息:客户端请求业务方(webApi)接口,由业务方(webApi

def get_one_page(url, headers):
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            response.encoding = response.apparent_encoding
            return response.text
        return None
    except RequestException:
        return None


def countPoint(UrlPart):
    cnt = 0
    for i in UrlPart:
        if i != ".":
            break
        cnt += 1
    return cnt


def getNewXls(url):
    html = get_one_page(url, headers=headers)
    if not html:
        return False
    als = re.findall("<a.*?href="(.*?)"", html, re.S)
    for a in als:
        if a.endswith("xls"):
            cnt = countPoint(a)
            url = "/".join(url.split("/")[:-cnt]) + a[cnt:]
            break
    content = requests.get(url, headers).content
    with open("content.xls", "wb") as f:
        f.write(content)
    return True

在得到考试安排信息后,我分析可以通过“课程&教师&班级”三种条件可以比较精确的搜索到要查询的考试安排。

open("content.xls","wb")asf:f.write(content)returnTrue在得到考试安排信息后,我分析可以通过“课程&am

通过这三个列名,可以建立一个简易的搜索字典:

nekeys=["课程名","上课老师","主修班级"]res_set=set()flag=Falseforiinrange(len(exp)):ifi


  data = {"课程名": {}, "上课老师": {}, "主修班级": {}}

idConfigure(IApplicationBuilderapp){//...ImHelper.Initialization(newImClientOptions{Redis=newCSRedis

def init():
    xls = xlrd.open_workbook("content.xls")
    global name_col, teacher_col, sc_col, sheet
    sheet = xls.sheet_by_index(0)
    keys = sheet.row_values(0)
    for i in range(len(keys)):
        if keys[i] == "课程名":
            name_col = i
        elif keys[i] == "上课教师":
            teacher_col = i
        elif keys[i] == "主修班级":
            sc_col = i
    if not name_col or not teacher_col or not sc_col:
        exit("Unknown xls layout")
    ls = sheet.col_values(name_col)
    for i in range(1, len(ls)):
        if ls[i] not in data["课程名"]:
            data["课程名"][ls[i]] = set()
        data["课程名"][ls[i]].add(i)
    ls = sheet.col_values(teacher_col)
    for i in range(1, len(ls)):
        if ls[i] not in data["上课老师"]:
            data["上课老师"][ls[i]] = set()
        data["上课老师"][ls[i]].add(i)
    ls = sheet.col_values(sc_col)
    for i in range(1, len(ls)):
        cls = ls[i].split(",")
        for cl in cls:
            if cl not in data["主修班级"]:
                data["主修班级"][cl] = set()
            data["主修班级"][cl].add(i)

而考虑查询方便,必然不可能让用户(我)每次都输入精准的信息才能查到结果,这太不酷了。

ver与业务方(webApi)该保持何种关系呢?用户A向好友B发送消息,分析一下:需要判断B是否为A好友;需要判断A是否有权限;等等。。诸如此类业务判断会很复杂,我们试想一下,如果使用imServer

所以我考虑间隔匹配+模糊匹配的方式来得到搜索结果。

href="(.*?)"",html,re.S)forainals:ifa.endswith("xls"):cnt=countPoint(a)url="/".j

间隔匹配:

ract(aim,data[keys[i]].keys(),limit=3)那么如果用户提供了多个搜索条件怎么处理呢?答案是利用集合的并交运算来处理。比如搜索表达式:xx&yy&zz。

def fm(string, ls):
    res = []
    match = ".*?".join([i for i in string])
    for i in ls:
        if re.findall(match, i):
            res.append((i, 100))
    return res

模糊匹配:(这里使用了一个叫fuzzywuzzy的第三方库,只有间隔匹配失败后才会使用模糊匹配)

ns{Redis=newCSRedis.CSRedisClient("127.0.0.1:6379,poolsize=5"),Servers=new[]{"127.0.0

res = fm(aim, data[keys[i]].keys())
if not res:
     res = process.extract(aim, data[keys[i]].keys(), limit=3)

那么如果用户提供了多个搜索条件怎么处理呢?答案是利用集合的并交运算来处理。

server充当消息转发,及维护连接中心,代码万年不变不需要重启维护;WebSocket比较笨的办法是浏览器端使用websocket,其他端socket,这种混乱的设计非常难维护。强烈建议所有端都使用

比如搜索表达式: xx&yy&zz。显然我们通过搜索算法可以得到三个独立集合分别为xx,yy和zz的结果,那么对这三个集合取交即可得到正解。

turnNonedefcountPoint(UrlPart):cnt=0foriinUrlPart:ifi!=".":breakcnt+=1returncntdefgetNewXls(

def search(exp):
    if not pre_check():
        return None
    keys = ["课程名", "上课老师", "主修班级"]
    res_set = set()
    flag = False
    for i in range(len(exp)):
        if i < 3:
            aim = exp[i].strip()
            if not aim:
                continue
            res = fm(aim, data[keys[i]].keys())
            if not res:
                res = process.extract(aim, data[keys[i]].keys(), limit=3)
            ts = set()
            for mth in res:
                if mth[1]:
                    ts = ts.union(data[keys[i]][mth[0]])
            if flag:
                res_set = res_set.intersection(ts)
            else:
                res_set = res_set.union(ts)
                flag = True
        else:
            break
    res = ""
    for line_num in res_set:
        line = sheet.row_values(line_num)
        res += "-" * 50 + "
"
        res += "课程名称:" + line[name_col] + "
"
        res += "授课教师:" + line[teacher_col].replace("
", ",") + "
"
        cls = line[sc_col].split(",")
        linkstr = ""
        for i in range(len(cls)):
            linkstr += cls[i]
            if i + 1 == len(cls):
                break
            elif (i + 1) % 5 == 0:
                linkstr += "
" + " " * 9
            else:
                linkstr += ","
        res += "主修班级:" + linkstr + "
"
        day = "%04d年%02d月%02d日" % xldate_as_tuple(line[4], 0)[:3]
        res += "考试时间:" + day + "(周%s) " % line[2] + line[5] + "
"
        res += "考试地点:" + line[-1].replace("
", ",") + "
"
    return res

到这,脚本的硬核部分就结束了~

*?".join([iforiinstring])foriinls:ifre.findall(match,i):res.append((i,100))returnres模糊匹配:(这里使用了一

然后我们基于这份代码,撸一个GUI出来。

性能、集群即时通讯组件,支持点对点通讯、群聊通讯、上线下线事件消息等众多实用性功能。开源地址:https://github.com/2881099/im,求star~~快速开始dotnetaddpac

大功告成~!

indata["主修班级"]:data["主修班级"][cl]=set()data["主修班级"][cl].add(i)而考虑查询方便,必然不可能让用户

GitHub开源地址:https://github.com/Rhythmicc/CUP_EXAM

e[-1].replace(" ",",")+" "returnres到这,脚本的硬核部分就结束了~然后我们基于这份代码,撸一个GUI出来。大功告成~!

 

器,访问http://127.0.0.1:5000发送群消息设计思路imServer是websocket服务中心,可部署多实例,按clientId分区管理socket连接;webApi或其他应用端,使

文章版权声明:除非注明,否则均为本站原创文章,转载或复制请以超链接形式并注明出处。
分享到:
赞 (0

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

发表评论

快捷回复:

评论列表 (有 0条评论, 1358人围观) 参与讨论