吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1432|回复: 11
收起左侧

[Web逆向] 实现某方正教务系统抢课

  [复制链接]
血海修罗 发表于 2023-12-28 16:47
本帖最后由 血海修罗 于 2023-12-30 11:30 编辑

某方正教务系统抢课


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

功能实现


1.实现登录 具体思路请参考下帖:
女朋友教务系统抢课老抢不上,写个代码解决这个问题
https://www.52pojie.cn/thread-1739086-1-1.html
(出处: 吾爱破解论坛)

2.实现选课
即本帖内容

分析网页


选课嘛,我们先随便选一门看看有什么东西
1.jpg
很明显的可以看到浏览器发送了两个请求,那我们就看看这俩分别有哪些参数
2.jpg
3.jpg
可以看到无论是第一个请求还是第二个请求都有jxb_ids、kch_id、zyh_id这三个参数,很明显这仨很重要,那就想方设法的获取一下这仨参数

获取zyh_id和xkkz_id
不管这几个参数多复杂,我们先去网页源代码看看,万一真的简单的放在了源代码里呢?
9.jpg
12.jpg
经过楼主的一通操作,发现源代码里的确有存放其中的几个参数,那就是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
于是就找到了这串代码
10.jpg
很明显基本上所有的参数都是在这个函数里生成的,但是楼主水平不够,不知道怎么通过这个函数获取这些参数,所以采用了一个比较迂回的办法,有兴趣的大佬可以看看怎么从这里获得参数。
下面是楼主的思路:
我们知道选课可以搜索,搜索就必然要返回给我们数据,我们还知道,每门课程都有一个与其唯一对应的教学班编号,那我们就搜一下呗
11.jpg
如图所示,搜索之后给了我们两条数据,打开一看,里面就正好有我们想要的jxb_ids和kch_id
8.jpg
7.jpg
那知道这俩参去哪获取了,同样的去爬一下就可以了,不同的是这里的参数是通过搜索获得的,所以需要通过两个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
嗯还是可以的,至于这个图里的内容有个编号,因为我们获取参数的时候是通过搜索教学班编号完成的  所以在通过代码选课的时候仍然需要这个教学班编号,这个每个学校选课前应该会发个文件,里面就有。

结语


对于不同的学校选课时的参数可能会有细微的差别,各位同学可以对比着自己修改一下
因为楼主是小白,只是简单的学习了下爬虫和python,所以思路可能有些混乱,代码可能有很多问题,希望各位大佬不吝赐教

代码


以下是原代码
code_show.zip (25.75 KB, 下载次数: 37)
这个代码是楼主前两天选课的时候用的,只是把域名和学号密码用*替换了,大家可能要自己改一下才能用
里面的yhm是学号,mm是密码。

免费评分

参与人数 2威望 +1 吾爱币 +21 热心值 +2 收起 理由
yuanyou + 1 + 1 谢谢@Thanks!
涛之雨 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

zjb1314 发表于 2024-1-6 14:32
抢课已经有了,有没有无痕改期末分数
my菠菜 发表于 2024-1-3 13:04
sdieedu 发表于 2024-1-2 20:43
xiaolei1314555 发表于 2024-1-8 16:54


非常感谢            谢谢分享
hua111 发表于 2024-1-13 10:19
非常谢谢分享
hymnmx 发表于 2024-1-13 12:36
vocal   我们就是这个系统,虽然我已经修完了选修  但是还是感谢楼主分享
戮之使 发表于 2024-2-18 16:14

之前分析我们学校的抢课系统,也写过油猴插件和软件,github上也有一个API文档写了一些分析。参数全都在js的异步请求上写着的,可以去分析一下。

最后的发包参数如下:

变量名 值(示例) 获取途径 注释 是否必须
jxb_ids 7cad8a50a08b2c9...(共257个字符) [具体信息]do_jxb_id 教学班号(动态刷新)
kch_id 45C16EB07F0B1AC3E0530264A8C024C7 [初级搜索]kch_id 课程号
qz 0 ----- 权重
kklxdm 10 [主页面] 10为选修课01为主修课 主修:? 选修:X
zyh_id A4F6C96AD6254D5AE05315C6A8C0XXXX [主页面] 专业代码(若选课对专业有要求则需要,大部分主修课有要求) 主修:? 选修:X
kcmc (66172392)党政机关公文写作 - 1.0 学分 ----- 课程名称(与[初级搜索]返回数据有些许差别) 主修:? 选修:X
rwlx 2 [主页面] 主修:? 选修:X
rlkz 0 [主页面] 主修:? 选修:X
rlzlkz 1 [主页面] 主修:? 选修:X
sxbj 1 如果rlkzrlzlkz为1,则为1,否者为0 主修:? 选修:X
xxkbj 0 [初级搜索] 主修:? 选修:X
cxbj 0 [已选课程]      [初级搜索] 重修标记 主修:? 选修:X
xkkz_id 0CECD6B11EFF2A6BE0630BC6A8C0D106 [主页面]firstXkkzId因为xkkz_id为空 与年级,主修课还是选修课相对应 主修:? 选修:X
xklc 1 [主页面] 主修:? 选修:X
xkxnm 2023 [主页面] 当前学期年份如2023-2024 即2023 主修:? 选修:X
xkxqm 12 [主页面] 主修:? 选修:X
戮之使 发表于 2024-2-18 16:31
还有,jxb_ids是后端动态生成的,有一定的时效性
 楼主| 血海修罗 发表于 2024-2-18 21:32
戮之使 发表于 2024-2-18 16:14
[md]### 之前分析我们学校的抢课系统,也写过油猴插件和软件,github上也有一个API文档写了一些分析。参数 ...

js还在学...... 等学完了再研究研究
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-29 09:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表