栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

广州大学gzhu抢课脚本

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

广州大学gzhu抢课脚本

** 编写背景:**
曾经在网上找了一下广大的抢课脚本,发现不是太老了没法用(因为更新了新教务系统),就是只能抢一门课(无语了,只能抢一门课,我要你这个脚本有什么用?)。

** 编写原因 :**
1.广大选课系统的土豆服务器每次选课都要崩溃。
2.每次当我进入系统之后都至少是抢课开始之后的半个小时了。
3.我每次都只能选其他同学选剩下的课,这点最气。
4.最近选课系统开放,然后因为刚刚开学的原因又比较闲。
所以用两天时间肝出了一个选课脚本出来。

** 实现流程:**
1.在选课系统试运行的时候,准备发包的data表单的内容。
2.在抢课开始前5到6分钟左右时更新cookie。
3.在抢课快要开始时使用异步协程向服务器发送要选课程的包。
所以脚本至少要运行3次,在上述三个时间节点。

** 实现思路:**
服务器在正式开放选课时并不会结束session,一般的cookie都能使用1200秒,所以5到6分钟前更新的cookie还能继续使用。
另外因为选课服务器不靠谱,要崩溃,所以只能采用循环轰炸的方式多次向服务器发包,凭借数量优势,希望能选上课吧。

** 实现细节:**
1.脚本使用selenium模拟登录,查找网页上的信息。
2.使用了多进程,一个进程更新cookie,一个进程异步发包抢课。
3.使用了异步协程。

看得懂代码的同学可以自己调一下包的数量,但是出了事可不能找我哈。

脚本的使用不需要什么门槛,只要会安装python环境就差不多够了。

脚本的使用教程放在github上了。
github链接
教程的图片太多,很多显示不了,这里不一一插入了,请自行到上面的github链接查看。

# 适用于gzhu新教务系统
# 谨献给745各位靓仔
# 邮箱 lihao_deng@qq.com
# 本人不对因使用此脚本而产生的任何后果或损失负责
# 如果遇到bug,重新运行脚本或者重启电脑可能可以解决问题
import json
import re
import sys
import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.common.by import By
import selenium.webdriver
from multiprocessing import Process
import os
from requests.cookies import RequestscookieJar
import urllib.parse
from selenium.webdriver.common.action_chains import ActionChains
import asyncio
import aiohttp
# 设置为全局变量方便更改
driver_path = r"D:environmentvariablemsedgedriver.exe"


def cookies_prepare(xuhao, mima):
    while True:
        # edge无头模式
        edge = {
            "ms:edgeOptions": {
                'extensions': [],
                'args': [
                    '--headless',
                    '--disable-gpu'
                ]}
        }
        driver = selenium.webdriver.Edge(driver_path, capabilities=edge)
        try:
            driver.get('https://newcas.gzhu.edu.cn/'
                       'cas/login?service=https%3A%2F%2Fnewmy.gzhu.edu.cn%2Fup%2Fview%3Fm%3Dup')
            try:
                # 智能等待
                WebDriverWait(driver, 10, 0.5).until(ec.visibility_of_element_located((By.ID, 'un')))
            except Exception as e:
                print(e)
            driver.find_element_by_id('un').send_keys(xuhao)
            driver.find_element_by_id('pd').send_keys(mima)
            driver.find_element_by_id('index_login_btn').click()
            try:
                WebDriverWait(driver, 10, 0.5).
                    until(ec.visibility_of_element_located((By.XPATH,
                                                            '//img[@src="/up/resource/image/home/gz/app/jwxt.png"]')))
            except Exception as e:
                print(e)
            driver.find_element_by_xpath('//img[@src="/up/resource/image/home/gz/app/jwxt.png"]').click()
            driver.get('http://jwxt.gzhu.edu.cn/jwglxt/'
                       'xsxk/zzxkyzb_cxZzxkYzbIndex.html?gnmkdm=N253512&layout=default&su='+xuhao)
            try:
                WebDriverWait(driver, 10, 0.5).until(ec.visibility_of_element_located
                                                     ((By.XPATH, '//div[@]')))
            except Exception as e:
                print(e)
            # 得到dict的cookie
            dictcookies = driver.get_cookies()
            # json.dumps和json.loads分别是将字典转换为字符串和将字符串转换为字典的方法
            # json.loads仅支持元素用双引号括住的字典
            jsoncookies = json.dumps(dictcookies)
            with open('./cookies.txt', 'w') as file:
                # 将字符串cookie保存至txt文件中
                file.write(jsoncookies)
                file.close()
                print('cookies updated')
            # 等待1100秒,差不多20分钟更新一次cookie
            time.sleep(1100)
            driver.quit()
        except Exception as e:
            print(e)
            print('cookies updating failed!')
            driver.quit()


# 准备学号与密码
def xuehao_mima():
    xuhao_path = './xuhao.txt'
    mima_path = './mima.txt'
    xuhao_txt = os.path.exists(xuhao_path)
    mima_txt = os.path.exists(mima_path)
    # 如果没有xuhao.txt就要求用户输入学号与密码
    if not xuhao_txt:
        xuhao = input('请输入学号:')
        mima = input('请输入密码:')
        with open(xuhao_path, 'w') as xuhao_file:
            xuhao_file.write(xuhao)
            xuhao_file.close()
        with open(mima_path, 'w') as mima_file:
            mima_file.write(mima)
            mima_file.close()
    # 如果没有mima.txt就要求用户输入学号与密码
    elif not mima_txt:
        xuhao = input('请输入学号:')
        mima = input('请输入密码:')
        with open(xuhao_path, 'w') as xuhao_file:
            xuhao_file.write(xuhao)
            xuhao_file.close()
        with open(mima_path, 'w') as mima_file:
            mima_file.write(mima)
            mima_file.close()
    # 如果xuhao.txt与mima.txt都存在,就读取这两个文件中储存的学号密码
    else:
        with open('./xuhao.txt', 'r') as xuhao_file:
            xuhao = xuhao_file.read()
            xuhao_file.close()
        with open('./mima.txt', 'r') as mima_file:
            mima = mima_file.read()
            mima_file.close()
    return xuhao, mima


def main():
    xuhao, mima = xuehao_mima()
    data_txt = os.path.exists('./data.txt')
    # 如果没有data.txt选课信息表单,就要求用户输入选课信息,生成表单
    if not data_txt:
        edge = {
            "ms:edgeOptions": {
                'extensions': [],
                'args': [
                    '--headless',
                    '--disable-gpu'
                ]}
        }
        driver = selenium.webdriver.Edge(driver_path, capabilities=edge)
        driver.get(
            'https://newcas.gzhu.edu.cn/cas/login?service=https%3A%2F%2Fnewmy.gzhu.edu.cn%2Fup%2Fview%3Fm%3Dup')
        try:
            WebDriverWait(driver, 10, 0.5).until(ec.visibility_of_element_located((By.ID, 'un')))
        except Exception as e:
            print(e)
        driver.find_element_by_id('un').send_keys(xuhao)
        driver.find_element_by_id('pd').send_keys(mima)
        driver.find_element_by_id('index_login_btn').click()
        try:
            WebDriverWait(driver, 10, 0.5). 
                until(ec.visibility_of_element_located((By.XPATH,
                                                        '//img[@src="/up/resource/image/home/gz/app/jwxt.png"]')))
        except Exception as e:
            print(e)
        page = driver.page_source
        judge = re.findall('融合门户', page)
        if len(judge) != 0:
            print('融合门户登录成功!')
        try:
            driver.find_element_by_xpath('//img[@src="/up/resource/image/home/gz/app/jwxt.png"]').click()
        except Exception as e:
            print(e)
            if len(judge) == 0:
                print('融合门户登录失败!')
                print('请检查学号密码是否输入正确,n如输入错误,请删除当前目录下xuhao.txt和mima.txt文件n然后重新运行程序!')
            else:
                print('unknown error!')
                print('已成功登录融合门户,但不能找到教务系统图标按钮!')
                print('重新运行程序或重启电脑或许能解决问题!')
            sys.exit(0)
        # get的网址是选课网站的网址
        driver.get(
            'http://jwxt.gzhu.edu.cn/jwglxt/xsxk/zzxkyzb_cxZzxkYzbIndex.html?gnmkdm=N253512&layout=default&su='
            + xuhao)
        print('正在转到选课页面>>>')
        try:
            WebDriverWait(driver, 10, 0.5).until(ec.visibility_of_element_located((By.XPATH,
                                                                                   '//div[@]')))
        except Exception as e:
            print(e)

        dictcookies = driver.get_cookies()
        jsoncookies = json.dumps(dictcookies)
        with open('./cookies.txt', 'w') as file:
            file.write(jsoncookies)
            file.close()
            print('cookies updated')
        # j表示data表单生成成功,0为假,1为真。
        j = 0
        # i表示是第一次循环.0为假,1为真
        i = 1
        while True:
            # 第一次循环,判断是否处于选课阶段
            if i == 1:
                source = driver.page_source
                # 通过页面信息判断是否处于选课阶段
                judge = re.findall("不是选课阶段", source)
                if len(judge) != 0:
                    break
            # 通过课程名称进行选课操作
            course_name = input('请完整复制课程名并粘贴于此处,示例:(180111005)地理教学技能 - 1.0 学分n注意!课程名的左右不要留有空格!n')
            # kch_id为课程名称中的数字id,如:180111005
            kch_id = course_name.split(')')[0][1:]
            try:
                WebDriverWait(driver, 10, 0.5).until(ec.visibility_of_element_located((By.XPATH,
                                                                                       "//button[@name='reset']")))
            except Exception as e:
                print(e)
            # execute_script可以在selenium中执行js命令
            driver.execute_script('document.getElementsByName("reset")[0].click();')
            course_classification = int(input('请输入课程类别:n主修课程请输入1,板块课体育请输入2,通识选修请输入3,其他特殊课程请输入4n'))
            if course_classification == 1:
                driver.find_element_by_xpath('//ul[@]/li[1]').click()
            elif course_classification == 2:
                driver.find_element_by_xpath('//ul[@]/li[2]').click()
            elif course_classification == 3:
                driver.find_element_by_xpath('//ul[@]/li[3]').click()
            elif course_classification == 4:
                driver.find_element_by_xpath('//ul[@]/li[4]').click()
            sendkeys_button = driver.find_element_by_xpath(
                '//input[@placeholder="请输入课程号或课程名称或教学班名称查询!"]')
            # ActionChains能模拟鼠标移动,点击,拖拽,长按,双击等等操作...
            ActionChains(driver).move_to_element(sendkeys_button).click().send_keys(kch_id).perform()
            driver.find_element_by_xpath('//button[@name="query"]').click()
            try:
                WebDriverWait(driver, 10, 0.5). 
                    until(ec.visibility_of_element_located((By.XPATH, "//tr[1]/td[@class='jsxmzc']")))
            except Exception as e:
                print(e)
            # 网页源代码
            page = driver.page_source
            # 在网页代码中找到教学班的个数
            jxb_numbers = re.findall('教学班个数.*">([1-9])', page)
            if len(jxb_numbers) == 0:
                print('未找到教学班信息,请检查信息是否输入正确')
                print('教学班名称示例:(180111005)地理教学技能 - 1.0 学分n注意!名称的左右不要留有空格!n注意!请检查课程类别是否正确!')
                print('请在程序提示后,重新输入信息!')
                continue
            jxb_numbers = jxb_numbers[0]
            i = 1
            while i <= int(jxb_numbers):
                # 不同的教学班的信息在不同序号的tr标签下,依次打印各个教学班的信息
                # 老师名字与职称
                teacher = driver.find_element_by_xpath("//tr[%d]/td[@class='jsxmzc']" % i).text
                # 上课时间
                course_time = driver.find_element_by_xpath("//tr[%d]/td[@class='sksj']" % i).text
                # 教学班号
                course_number = driver.find_element_by_xpath("//tr[%d]/td[@class='jxbmc']" % i).text
                print('教学班%d,老师:%s,上课时间:%s,教学班号:%sn' % (i, teacher, course_time, course_number))
                i += 1
            # jxbmc为教学班号
            jxbmc = input('请从上面的教学班中选择并复制粘贴要选择的教学班的教学班号,'
                          '示例:(2021-2022-2)-131800701-1n注意!教学班号的左右不要留有空格!n')
            # 通过教学班号找到jxb_ids的信息
            tobeprocessed_jxb_ids = driver.find_element_by_xpath(
                '//td[@ and contains(text(), "%s")]/../td[@]/button' % jxbmc)
                .get_attribute('onclick')
            jxb_ids = tobeprocessed_jxb_ids.split(',')[1][1:-1]
            # 下面是处理得到kcmc的函数
            course_name = course_name.split(')')
            course_name[0] = course_name[0] + ')'
            strings = course_name[1].split(' ')
            strings1 = urllib.parse.quote(strings[0])
            strings2 = urllib.parse.quote(strings[-1])
            # kcmc通过urlencode编码,但是,kcmc只有部分编码,需要注意
            kcmc = course_name[0] + strings1 + '+-+1.0+' + strings2
            # 下面为通过js找到属性值的函数
            rwlx = driver.execute_script("document.getElementById('rwlx')['value']")
            rlkz = driver.execute_script("document.getElementById('rlkz')['value']")
            rlzlkz = driver.execute_script("document.getElementById('rlzlkz')['value']")
            xkxnm = driver.execute_script("document.getElementById('xkxnm')['value']")
            xkxqm = driver.execute_script("document.getElementById('xkxqm')['value']")
            xklc = driver.execute_script("document.getElementById('xklc')['value']")
            kklxdm = driver.execute_script("document.getElementById('kklxdm')['value']")
            zyh_id = driver.execute_script("document.getElementById('zyh_id')['value']")
            njdm_id = driver.execute_script("document.getElementById('njdm_id')['value']")
            xkkz_id = driver.execute_script("document.getElementById('xkkz_id')['value']")
            # 下面是用xpath找属性值的函数
            cxbj = driver.find_element_by_xpath("//input[@name='cxbj']").get_attribute('value')
            xxkbj = driver.find_element_by_xpath("//input[@name='xxkbj']").get_attribute('value')
            # 下面是完整的data表单的内容
            # sxbj与qz的属性没有在页面中找到,通过抓包获得
            data = {
                "jxb_ids": jxb_ids,
                "kch_id": kch_id,
                "kcmc": kcmc,
                "rwlx": rwlx,
                "rlkz": rlkz,
                "rlzlkz": rlzlkz,
                "sxbj": "1",
                "xxkbj": xxkbj,
                "qz": "0",
                "cxbj": cxbj,
                "xkkz_id": xkkz_id,
                "njdm_id": njdm_id,
                "zyh_id": zyh_id,
                "kklxdm": kklxdm,
                "xklc": xklc,
                "xkxnm": xkxnm,
                "xkxqm": xkxqm}
            # 存储data表单
            with open('./data.txt', 'a') as data_file:
                # dict类型的内容不能用write函数
                data_file.write(str(data) + 'n')
                data_file.close()
            # j=1 表示抢课信息录入成功
            j = 1
            # i=0表示不是第一循环
            i = 0
            print('选课内容添加成功!')
            judge_break = input('是否继续添加选课内容[y/n]?:')
            if judge_break == 'n':
                break
        driver.quit()
        if j == 1:
            print('data表单准备完成,抢课信息录入完毕。')
        elif j == 0:
            print('选课系统未开放,无法录入抢课信息,请在选课系统开放后再运行此脚本')
    # 如果有抢课信息表单,则继续运行程序
    else:
        print('已存在抢课信息,如需重新选择抢课信息,请停止运行程序n并删除此脚本当前目录下的"data.txt"文件,然后重新运行程序')
    # 创建两个进程,一个用来每二十分钟更新一次cookie, 一个用来发送表单抢课
    process = [Process(target=cookies_prepare, args=(xuhao, mima)),
               Process(target=qiangke, args=(xuhao,))]
    [p.start() for p in process]
    [p.join() for p in process]


def qiangke(xuhao):
    print('准备开始抢课!')
    # 读取保存的cookie
    cookie_txt = os.path.exists('./cookies.txt')
    if not cookie_txt:
        time.sleep(20)
    with open('./cookies.txt', 'r') as file:
        listcookies = json.loads(file.read())
        file.close()
    jar = RequestscookieJar()
    jar.set(listcookies[0]['name'], listcookies[0]['value'])
    # 读取保存的data表单,并通过async异步的方式发送
    with open('./data.txt', 'r') as data_file:
        tobeprocessed_data = data_file.read()
        data_file.close()
    datas = tobeprocessed_data.split('n')
    while True:
        tasks = []
        n = 0
        while n < 10:
            i = 0
            while i < len(datas)-1:
                data = eval(datas[i])
                coroutine = submit_package(xuhao, data, jar)
                task = asyncio.ensure_future(coroutine)
                tasks.append(task)
                i += 1
            n += 1
        loop = asyncio.get_event_loop()
        result_datas = loop.run_until_complete(asyncio.wait(tasks))
        # i表示cookie失效,需要重新发包
        i = 0
        for result_data in result_datas[0]:
            if result_data.result() == 'cookie out of date':
                i = 1
                break
        if i == 1:
            with open('./cookies.txt', 'r') as file:
                listcookies = json.loads(file.read())
                file.close()
            jar = RequestscookieJar()
            jar.set(listcookies[0]['name'], listcookies[0]['value'])
        else:
            break
    loop.close()
    print('抢课完毕!')


async def submit_package(xuhao, data, jar):
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                             "Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62 ",
               "refer": "http://jwxt.gzhu.edu.cn/jwglxt/xsxk/zzxkyzb_cxZzxkYzbIndex.html?"
                        "gnmkdm=N253512&layout=default&su="+xuhao}
    url = "http://jwxt.gzhu.edu.cn/jwglxt/xsxk/zzxkyzbjk_xkBcZyZzxkYzb.html?gnmkdm=N253512&su="+xuhao
    params = {"gnmkdm": "N253512",
              "su": xuhao}
    try:
        # ClientSession别忘了跟()
        async with aiohttp.ClientSession() as session:
            async with await session.post(url, headers=headers, data=data, params=params, cookies=jar, timeout=5) 
                    as response:
                contant = await response.text()
                contant = contant[-4:]
                if contant == '-1"}':
                    print('对不起,该教学班已无余量,不可选!')
                elif contant == '"0"}':
                    print('所选教学班的上课时间与其他教学班有冲突!')
                elif contant == '"1"}':
                    print('恭喜你,选课成功!')
                elif contant == 'tml>':
                    print('cookie已失效!请等待cookie更新')
                    # 等待另一个进程更新cookie
                    await asyncio.sleep(10)
                    return 'cookie out of date'
                else:
                    print(contant)
                    await asyncio.sleep(5)
                    # 未知内容,重新运行程序发送表单
                    await submit_package(xuhao, data, jar)
    except asyncio.TimeoutError:
        # 超时服务器仍未返回值,则重新运行程序发送表单
        await submit_package(xuhao, data, jar)
    except Exception as e:
        print(e)
        await asyncio.sleep(5)
        # 未知错误,重新运行程序发送表单
        await submit_package(xuhao, data, jar)


if __name__ == '__main__':
    main()

广州大学gzhu抢课脚本

适用于广大新版教务系统 https://newcas.gzhu.edu.cn/cas/login?service=https%3A%2F%2Fnewmy.gzhu.edu.cn%2Fup%2F

谨献给745宿舍全体靓仔,祝各位靓仔学业顺利

邮箱 lihao_deng@qq.com

本人不对因使用此脚本而产生的任何后果或损失负责

如果遇到bug,重新运行脚本或者重启电脑可能可以解决问题

运行环境:

python 3.9

需要安装的库

requests

selenium

os

用如下代码安装(如果安装不了,请自行百度):

pip3 install requests
pip3 install selenium
pip3 install os

如果想使用anaconda ,请自行百度

下面是使用此脚本的教程:
    转到edge://settings/help 查看你的Microsoft Edge版本。

    访问"Microsoft Edge驱动程序"。

    在页面的"获取最新版本"部分,找到与你的Microsoft Edge的版本编号相匹配的,然后选择其x64版本并下载。

    下载完成后,将可执行 msedgedriver.exe 文件放到任意位置(建议直接放到D盘根目录)。

    右键单击可执行msedgedriver.exe文件,选择复制文件地址

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P5JDdS4s-1645974306589)(image-20220126003123925.png)]

6.复制粘贴文件地址,覆盖driver_path = r"D:environmentvariablemsedgedriver.exe"里的"D:environmentvariablemsedgedriver.exe"。如图,位置可能在selenium_course_selector.py文件的第22行,也有可能在selenium_course_selector.py文件的第8行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qiHoQRPb-1645974306590)(image-20220227152531167.png)]

7.在自己的浏览器登录教务系统选课界面,找到所有自己想选的课程,并完整复制其名称

如图所示,示例:(130101303)学术研究与交流 - 1.0 学分

注意!不要把两边的空格复制进去!从"("开始复制,到"学分"的"分"字结束。

可以把课程名称先保存在txt文件中,方便后面运行程序时复制粘贴。

因为运行脚本时如果使用浏览器登录自己的教务系统账号,脚本的登录状态将会失效。

同时需要记住该门课程的类别:是主修课程,板块课体育,通识选修还是其他特殊课程?需要记住。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8E0sRpFL-1645974306590)(image-20220226164903042.png)]

8.运行selenium_course_selector.py程序。

9.根据提示输入学号和密码(学号与密码保存在本地,即selenium_course_selector.py同级目录下)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6wXfxVsm-1645974306590)(image-20220226165425474.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-feJzXWWZ-1645974306591)(image-20220226165445385.png)]

如果输入错误,请停止运行程序,并在selenium_course_selector.py同级目录下手动删除xuhao.txt与mima.txt文件,然后重新运行程序。

10.等待一段时间,出现提示后,根据提示操作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fVQzadzA-1645974306591)(image-20220227153712981.png)]

11.请在选课开始前几天,选课系统试运行的时候,提前运行一次脚本录入信息,以方便在抢课开始时迅速开始抢课。

12.请在正式选课开始前5到6分钟时使用一次脚本,以更新cookie。

11.请在选课开始前几天,选课系统试运行的时候,提前运行一次脚本录入信息,以方便在抢课开始时迅速开始抢课。

12.请在正式选课开始前5到6分钟时使用一次脚本,以更新cookie。

13.然后在正式选课开始时前一分钟运行脚本进行抢课。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/747180.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号