Skip to content

Commit

Permalink
Merge pull request #1 from Colorfulshadow/experiment
Browse files Browse the repository at this point in the history
first version worked on 23/9/11
  • Loading branch information
Colorfulshadow authored Sep 11, 2023
2 parents 1dda86d + 2b57dfc commit 46d047e
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 2 deletions.
75 changes: 73 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,73 @@
# buaa_course_enrollment
·旨在自动化北京航空航天大学(BUAA)的课程选课过程。
# BUAA Course Enrollment Automation

## 简介

**`buaa_course_enrollment.py`** 是一个专为北京航空航天大学(BUAA)设计的自动选课脚本。其主要功能是帮助学生在开放选课期间自动选择课程,减轻手动选课的负担和压力。脚本使用Python编写,结合了BeautifulSoup和requests库来实现自动登录和选课功能。

### 主要功能

- 自动登录北京航空航天大学的教务系统。
- 根据用户输入的课程类型和课程代码自动选择课程。
- 能够自动识别当前的学期,并根据学期修改相关参数。
- 在成功选课前持续尝试选课,提高选课成功率。

## 使用方式

### 安装必要的库

首先,确保你已经安装了Python和所需要的库:

```bash
pip install -r requirements
```

### 配置脚本

1. 打开`buaa_course_enrollment.py`文件。
2. 修改脚本顶部的配置部分,填入你的账号、密码、课程类型、课程代码和对应序号。

```python
USERNAME = '你的账号'
PASSWORD = '你的密码'
COURSE_TYPE = '你要选择的课程类型'
COURSE_CODE = '你要选择的课程代码'
SERIAL_CODE= '你要选择的课程序号'
```

对应下图,1、2、3分别为COURSE_TYPE(可以在代码`TYPE_DICT`中找到)、COURSE_CODE和SERIAL_CODE(从001开始)。例如,我希望选择该图中高胜杰老师的足球课,我将填写:

```python
COURSE_TYPE = '体育'
COURSE_CODE = 'B2E333070'
SERIAL_CODE= '003'
```

![sample](Sample/sample.png)

### 运行脚本

在脚本所在的目录打开终端或命令提示符,然后运行以下命令:

```bash
python buaa_course_enrollment.py
```

脚本将自动登录并开始尝试选课。成功选课后,它将退出。

## 注意事项

- 请确保在使用脚本之前已知晓并遵守北京航空航天大学的相关规定和政策。
- 脚本仅用于教育和学习目的,请勿用于任何非法或不道德的用途。

## 贡献

如果你有任何改进或功能增加的建议,请通过Pull Request或Issue来贡献。

## 许可

该项目根据[GNU GENERAL PUBLIC LICENSE许可证](LICENSE)进行许可。

## 特别感谢

本项目参考了[Cauchy1412](https://github.com/Cauchy1412)[BUAAGetCourse](https://github.com/Cauchy1412/BUAAGetCourse)

Binary file added Sample/sample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
requests==2.26.0
beautifulsoup4==4.10.0
120 changes: 120 additions & 0 deletions xuanke.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import time
import requests
from bs4 import BeautifulSoup
from urllib.parse import quote
import re
from datetime import datetime

# 设置配置变量
BASE_URL = 'http://jwxt.buaa.edu.cn:8080/ieas2.1'
LOGIN_URL = 'https://sso.buaa.edu.cn/login?service=' + quote(BASE_URL + '/welcome', 'utf-8')
USERNAME = ''
PASSWORD = ''
COURSE_TYPE = ''
COURSE_CODE = ''
SERIAL_CODE = '001'

TYPE_DICT = {
'一般专业': ('xslbxk', 'ZYL', 'xslbxk'),
'核心专业': ('xslbxk', 'ZYL', 'xslbxk'),
'核心通识': ('xslbxk', 'TSL', 'tsk'),
'一般通识': ('xslbxk', 'TSL', 'qxrx'),
'体育': ('xslbxk', 'TSL', 'ty')
}
VAR1, VAR2, VAR3 = TYPE_DICT[COURSE_TYPE]

def get_current_term():
now = datetime.now()
year = now.year
month = now.month

if month >= 8:
term = f"{year}-{year+1}-1"
short_term = f"{year}{(year+1) % 100}1"
elif month <= 1:
term = f"{year-1}-{year}-1"
short_term = f"{(year-1) % 100}{year % 100}1"
else:
term = f"{year-1}-{year}-2"
short_term = f"{(year-1) % 100}{year % 100}2"

return term, short_term

# 使用这个函数来设置RWH和pageXnxq
term, short_term = get_current_term()
RWH = f'{term}-{COURSE_CODE}-{SERIAL_CODE}'
PAGE_XNXQ = short_term

# 定义获取登陆令牌的函数
def get_login_token(session):
r = session.get(LOGIN_URL)
r.raise_for_status()
soup = BeautifulSoup(r.content, 'html.parser')
return soup.find('input', {'name': 'execution'})['value']

# 定义登陆的函数
def login(session):
formdata = {
'username': USERNAME,
'password': PASSWORD,
'execution': get_login_token(session),
'type': 'username_password',
'_eventId': 'submit',
'submit': '登陆'
}
r = session.post(LOGIN_URL, data=formdata, allow_redirects=True)
soup = BeautifulSoup(r.text, "html.parser")
return not soup.find_all('div', class_='error_txt')

# 定义提取隐藏项的函数
def get_hidden_items(text):
item_pattern = re.compile(r'<input type="hidden" id=".*?" name="(.*?)"\s+value="(.*?)"')
return {item.group(1): item.group(2) for item in item_pattern.finditer(text)}

# 定义提取消息的函数
def extract_message(html_text):
message_pattern = re.compile(r"alert\('(.+?)'\);")
match = message_pattern.search(html_text)
return match.group(1) if match else None

# 定义选课的函数
def choose(session):
list_url = f'{BASE_URL}/xslbxk/queryXsxkList?pageXkmkdm={VAR2}'
response = session.post(list_url, allow_redirects=True)
response.raise_for_status()

payload = get_hidden_items(response.text)
payload.update({
'pageXnxq': PAGE_XNXQ,
'pageXklb': VAR3,
'pageYcctkc': '1',
'rwh': RWH
})

response = session.post(f'{BASE_URL}/{VAR1}/saveXsxk', data=payload)
message = extract_message(response.text)
if message:
print(message)
if "选课成功" in message:
exit()

# 主循环
def main():
if (USERNAME == '' or
PASSWORD == '' or
COURSE_TYPE == '' or
COURSE_CODE == '' or
TEACHER_CODE == ''):

print("请填写USERNAME, PASSWORD, COURSE_TYPE, COURSE_CODE 和 TEACHER_CODE的正确值。")
exit()

session = requests.Session()
login(session)

while True:
choose(session)
time.sleep(6)

if __name__ == "__main__":
main()

0 comments on commit 46d047e

Please sign in to comment.