实现某方正教务系统抢课

查看 57|回复 9
作者:血海修罗   
某方正教务系统抢课



前言
今年年初学习了shiyier大佬的帖子:女朋友教务系统抢课老抢不上,写个代码解决这个问题,搞定了登陆的问题,但由于大佬没有给出抢课的代码,身为苦逼大学生的我在暑假简单学习了下python和爬虫,自己实现了抢课的功能,并在近几天经过了实测,赶在今年结束前与大家分享一下思路。
功能实现

1.实现登录 具体思路请参考下帖:

女朋友教务系统抢课老抢不上,写个代码解决这个问题
https://www.52pojie.cn/thread-1739086-1-1.html
(出处: 吾爱破解论坛)
2.实现选课
即本帖内容
分析网页
选课嘛,我们先随便选一门看看有什么东西


1.jpg (222.74 KB, 下载次数: 0)
下载附件
2023-12-28 15:20 上传

很明显的可以看到浏览器发送了两个请求,那我们就看看这俩分别有哪些参数


2.jpg (139.94 KB, 下载次数: 0)
下载附件
2023-12-28 15:21 上传



3.jpg (143.64 KB, 下载次数: 0)
下载附件
2023-12-28 15:21 上传

可以看到无论是第一个请求还是第二个请求都有jxb_ids、kch_id、zyh_id这三个参数,很明显这仨很重要,那就想方设法的获取一下这仨参数
获取zyh_id和
xkkz_id
不管这几个参数多复杂,我们先去网页源代码看看,万一真的简单的放在了源代码里呢?


9.jpg (190.85 KB, 下载次数: 0)
下载附件
2023-12-28 15:24 上传



12.jpg (172.29 KB, 下载次数: 0)
下载附件
2023-12-28 15:45 上传

经过楼主的一通操作,发现源代码里的确有存放其中的几个参数,那就是zyh_id和xkkz_id,很明显zyh_id和xkkz_id就是代表所选的课程分属的版块,那这个简单的爬一下源代码就可以了
下面是代码,里面的yhm是你的学号
[Python] 纯文本查看 复制代码#获取zyh_id
def get_zyh_id(yhm):
    zyh_id_url = 'http://***.**.***.***/jwglxt/xsxk/zzxkyzb_cxZzxkYzbIndex.html?gnmkdm=N253512&layout=default&su=' + str(yhm)
    response = session.get(url=zyh_id_url)
    response.encoding = 'utf-8'
    content = response.text
    tree = etree.HTML(content)
    zyh_id = tree.xpath('//input[@id="zyh_id"]/@value')
    return zyh_id[0]
[Python] 纯文本查看 复制代码#爬取xkkz_id
def course_sort(yhm):
    sort_url = 'http://***.**.***.***/jwglxt/xsxk/zzxkyzb_cxZzxkYzbIndex.html?gnmkdm=N253512&layout=default&su=' + str(yhm)
    response = session.get(url=sort_url,headers=headers1)
    response.encoding = 'utf-8'
    content = response.text
    tree = etree.HTML(content)
    course_sort_id = tree.xpath('//a[@role="tab"]/@onclick')
    return course_sort_id
[Python] 纯文本查看 复制代码#因为xkkz_id不是每次都会发生变化,所以这里把xkkz_id写入到文件里,不用每次都爬取
def get_course_sort_id_true(list):
    pattern = r"queryCourse\(this,'(?:[^']*)','(\w+)'"
    extracted_texts = []
    for text in list:
        match = re.search(pattern, text)
        if match:
            extracted_text = match.group(1)
            extracted_texts.append(extracted_text)
    with open("courese_sort_id.txt", "w") as file:
        for item in extracted_texts:
            file.write(item + '\n')
获取jxb_ids和kch_id
这俩在网页源代码里没有,那么就先搜一下


4.jpg (203.09 KB, 下载次数: 0)
下载附件
2023-12-28 15:30 上传

于是就找到了这串代码


10.jpg (227.76 KB, 下载次数: 0)
下载附件
2023-12-28 15:34 上传

很明显基本上所有的参数都是在这个函数里生成的,但是楼主水平不够,不知道怎么通过这个函数获取这些参数,所以采用了一个比较迂回的办法,有兴趣的大佬可以看看怎么从这里获得参数。
下面是楼主的思路:
我们知道选课可以搜索,搜索就必然要返回给我们数据,我们还知道,每门课程都有一个与其唯一对应的教学班编号,那我们就搜一下呗


11.jpg (220.06 KB, 下载次数: 0)
下载附件
2023-12-28 15:39 上传

如图所示,搜索之后给了我们两条数据,打开一看,里面就正好有我们想要的jxb_ids和kch_id


8.jpg (94.27 KB, 下载次数: 1)
下载附件
2023-12-28 15:43 上传



7.jpg (90.12 KB, 下载次数: 1)
下载附件
2023-12-28 15:43 上传

那知道这俩参去哪获取了,同样的去爬一下就可以了,不同的是这里的参数是通过搜索获得的,所以需要通过两个post请求获得
[Python] 纯文本查看 复制代码#获取kch_id
def get_data_kch_id(zyh_id,yhm):
    serch_url = 'http://***.**.***.***/jwglxt/xsxk/zzxkyzb_cxZzxkYzbPartDisplay.html?gnmkdm=N253512&su=' + str(yhm)
    data = {
#这里的filter_list是你搜索的教学班编号,下同
        'filter_list[0]':filter_list,
        'rwlx':rwlx,
        'xkly':'0',
        'bklx_id':bklx_id,
        'sfkkjyxdxnxq':'0',
        'xqh_id':'05',
        'jg_id':'07',
        'njdm_id_1':'2022',
        'zyh_id_1':str(zyh_id),
        'zyh_id':str(zyh_id),
        'zyfx_id':'wfx',
        'njdm_id':'2022',
        'bh_id':'20220809113',
        'bjgkczxbbjwcx':'0',
        'xbm':'1',
        'xslbdm':'wlb',
        'mzm':'01',
        'xz':'4',
        'ccdm':'3',
        'xsbj':'4294967296',
        'sfkknj':'0',
        'sfkkzy':'0',
        'kzybkxy':'0',
        'sfznkx':'0',
        'zdkxms':'0',
        'sfkxq':'0',
        'sfkcfx':'0',
        'kkbk':'0',
        'kkbkdj':'0',
        'sfkgbcx':'0',
        'sfrxtgkcxd':'0',
        'tykczgxdcs':'0',
        'xkxnm':'2023',
        'xkxqm':'12',
        'kklxdm':kklxdm,
        'bbhzxjxb':'0',
        'rlkz':'0',
        'xkzgbj':'0',
        'kspage':'1',
        'jspage':'10',
        'jxbzb':''
    }
    response = session.post(url=serch_url,data=data,headers=headers1)
    kch_id_1 = response.json()
    with open('kch_id_1.json', 'w', encoding='utf-8') as fp:
        fp.write(str(kch_id_1))
[Python] 纯文本查看 复制代码# 取课程jxb_ids
def get_jxb_ids(yhm,kch_id):
    choice_url = 'http://***.**.***.***/jwglxt/xsxk/zzxkyzbjk_cxJxbWithKchZzxkYzb.html?gnmkdm=N253512&su=' + str(yhm)
    data_beggin = {
        'filter_list[0]':filter_list,
        'rwlx':rwlx,
        'xkly':'0',
        'bklx_id':bklx_id,
        'sfkkjyxdxnxq':'0',
        'xqh_id':'05',
        'jg_id':'07',
        'zyh_id':str(zyh_id),
        'zyfx_id':'wfx',
        'njdm_id':'2022',
        'bh_id':'20220809113',
        'xbm':'1',
        'xslbdm':'wlb',
        'mzm':'01',
        'xz':'4',
        'ccdm':'3',
        'xsbj':'4294967296',
        'sfkknj':'0',
        'sfkkzy':'0',
        'kzybkxy':'0',
        'sfznkx':'0',
        'zdkxms':'0',
        'sfkxq':'0',
        'sfkcfx':'0',
        'bbhzxjxb':'0',
        'kkbk':'0',
        'kkbkdj':'0',
        'xkxnm':'2023',
        'xkxqm':'12',
        'xkxskcgskg':'1',
        'rlkz':'0',
        'kklxdm':kklxdm,
        'kch_id': str(kch_id),
        'jxbzcxskg':'0',
        'xkkz_id': xkkz_id,
        'cxbj':'0',
        'fxbj':'0'
    }
    response = session.post(url=choice_url,data=data_beggin,headers=headers1)
    course = response.json()
    with open('course.json', 'w', encoding='utf-8') as fp:
        fp.write(str(course))
    with open('course.json', 'r', encoding='utf8') as f:
        jxb_id = f.read()
    jxb_id = jxb_id.replace("'", '"')
    jxb_id = jxb_id.replace("False", '"False"')
    jxb_id = jxb_id.replace("True", '"True"')
    jxb_id_data = json.loads(jxb_id)
    jxb_id_true = jsonpath.jsonpath(jxb_id_data, '$..do_jxb_id')
    return jxb_id_true[0]

完成选课

其他的的参数就无伤大雅了,例如xkxnm代表的是学年,xkxqm代表的是学期,以我们学校为例,今年是2023学年,03是上学期,12是下学期,选课前稍微修改一下就可以了
那么我们回到分析网页的第一张截图
选课时发了两个请求,那我们也发送两个请求,实现代码如下
[Python] 纯文本查看 复制代码#发送第一次请求
def choice_course_1(yhm,jxb_ids,kch_id,zyh_id):
    course_url_1 = 'http://***.**.***.***/jwglxt/xsxk/zzxkyzb_cxXkTitleMsg.html?gnmkdm=N253512&su=' + str(yhm)
    data = {
        'jxb_ids': str(jxb_ids),
        'xkxnm': '2023',
        'xkxqm': '12',
        'bj': '7',
        'kch_id': str(kch_id),
        'njdm_id': '2022',
        'zyh_id': str(zyh_id),
        'kklxdm': kklxdm
    }
    response = session.post(url=course_url_1,data=data,headers=headers1)
    course = response.json()
    with open('choice_course_1.json', 'w', encoding='utf-8') as fp:
        fp.write(str(course))
#这里写入course是为了判断是否选课成功
[Python] 纯文本查看 复制代码#发送第二次请求
def choice_course_2(yhm,jxb_ids,kch_id,zyh_id):
    course_url_2 = 'http://***.**.***.***/jwglxt/xsxk/zzxkyzbjk_xkBcZyZzxkYzb.html?gnmkdm=N253512&su=' + str(yhm)
    data = {
        'jxb_ids': str(jxb_ids),
        'kch_id': str(kch_id),
        'rwlx': rwlx,
        'rlkz': '0',
        'rlzlkz': '1',
        'sxbj': '1',
        'xxkbj': '0',
        'qz': '0',
        'cxbj': '0',
        'xkkz_id': xkkz_id,
        'njdm_id': '2022',
        'zyh_id': str(zyh_id),
        'kklxdm': kklxdm,
        'xklc': '1',
        'xkxnm': '2023',
        'xkxqm': '12'
    }
    response = session.post(url=course_url_2,data=data,headers=headers1)
    course = response.json()
    with open('choice_course_2.json', 'w', encoding='utf-8') as fp:
        fp.write(str(course))
#这里写入course是为了判断是否选课成功
写完了简单运行下


QQ截图20231228140923.png (75.59 KB, 下载次数: 0)
下载附件
2023-12-28 16:27 上传

嗯还是可以的,至于这个图里的内容有个编号,因为我们获取参数的时候是通过搜索教学班编号完成的  所以在通过代码选课的时候仍然需要这个教学班编号,这个每个学校选课前应该会发个文件,里面就有。
结语
对于不同的学校选课时的参数可能会有细微的差别,各位同学可以对比着自己修改一下
因为楼主是小白,只是简单的学习了下爬虫和python,所以思路可能有些混乱,代码可能有很多问题,希望各位大佬不吝赐教
代码
以下是原代码

code_show.zip
(25.75 KB, 下载次数: 69)
2023-12-28 18:43 上传
点击文件名下载附件
下载积分: 吾爱币 -1 CB

这个代码是楼主前两天选课的时候用的,只是把域名和学号密码用*替换了,大家可能要自己改一下才能用
里面的yhm是学号,mm是密码。

下载次数, 代码

zjb1314   

抢课已经有了,有没有无痕改期末分数
my菠菜   

非常感谢            谢谢分享
sdieedu   

非常感谢的
xiaolei1314555   

非常感谢            谢谢分享
hymnmx   

vocal   我们就是这个系统,虽然我已经修完了选修  但是还是感谢楼主分享
戮之使   

之前分析我们学校的抢课系统,也写过油猴插件和软件,github上也有一个API文档写了一些分析。参数全都在js的异步请求上写着的,可以去分析一下。
最后的发包参数如下:
[table]
[tr]
[td]变量名[/td]
[td]值(示例)[/td]
[td]获取途径[/td]
[td]注释[/td]
[td]是否必须[/td]
[/tr]
[tr]
[td]jxb_ids
戮之使   

还有,jxb_ids是后端动态生成的,有一定的时效性
血海修罗
OP
  


戮之使 发表于 2024-2-18 16:14
[md]### 之前分析我们学校的抢课系统,也写过油猴插件和软件,github上也有一个API文档写了一些分析。参数 ...

js还在学...... 等学完了再研究研究
血海修罗
OP
  


hua111 发表于 2024-2-28 08:58
有一定的时效性

总的思路是差不多的 可能过段时间其中的参数会发生变化 要相应地改一下
您需要登录后才可以回帖 登录 | 立即注册

返回顶部