博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
考试安排查询脚本(CUP)
阅读量:5242 次
发布时间:2019-06-14

本文共 4131 字,大约阅读时间需要 13 分钟。

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

brew install python3pip3 install requestspip3 install tkinterpip3 install fuzzywuzzypip3 install xlrd

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

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

打开以后:

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

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

代码:

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 Nonedef countPoint(UrlPart):    cnt = 0    for i in UrlPart:        if i != '.':            break        cnt += 1    return cntdef getNewXls(url):    html = get_one_page(url, headers=headers)    if not html:        return False    als = re.findall('

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

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

 

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

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)

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

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

间隔匹配:

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的第三方库,只有间隔匹配失败后才会使用模糊匹配)

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

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

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

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 + '\n'        res += '课程名称:' + line[name_col] + '\n'        res += '授课教师:' + line[teacher_col].replace('\n', ',') + '\n'        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 += '\n' + ' ' * 9            else:                linkstr += ','        res += '主修班级:' + linkstr + '\n'        day = "%04d年%02d月%02d日" % xldate_as_tuple(line[4], 0)[:3]        res += '考试时间:' + day + '(周%s) ' % line[2] + line[5] + '\n'        res += '考试地点:' + line[-1].replace('\n', ',') + '\n'    return res

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

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

大功告成~!

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

 

转载于:https://www.cnblogs.com/Rhythm-/p/11273708.html

你可能感兴趣的文章
前台freemark获取后台的值
查看>>
log4j.properties的作用
查看>>
游戏偶感
查看>>
Leetcode: Unique Binary Search Trees II
查看>>
C++ FFLIB 之FFDB: 使用 Mysql&Sqlite 实现CRUD
查看>>
Spring-hibernate整合
查看>>
c++ map
查看>>
exit和return的区别
查看>>
discuz 常用脚本格式化数据
查看>>
洛谷P2777
查看>>
PHPStorm2017设置字体与设置浏览器访问
查看>>
Django 相关
查看>>
git init
查看>>
训练记录
查看>>
IList和DataSet性能差别 转自 http://blog.csdn.net/ilovemsdn/article/details/2954335
查看>>
Hive教程(1)
查看>>
第16周总结
查看>>
C#编程时应注意的性能处理
查看>>
Fragment
查看>>
比较安全的获取站点更目录
查看>>