Python Selenium自动化教务系统评教脚本开发实战指南
1. 项目概述与核心需求解析
教务系统自动评教,这个想法估计在不少大学生和技术爱好者的脑子里都闪过。每到学期末,面对那几十门课程、上百个评价项,重复点击、机械打分,一坐就是大半天,确实是个枯燥的体力活。手动评教不仅耗时,还容易因为疲劳导致评价不准确,甚至漏评。更重要的是,这种重复性劳动,正是自动化脚本大显身手的地方。这个项目的核心,就是利用Python编程语言,结合Selenium等自动化测试工具,模拟真人操作浏览器,自动登录教务系统,遍历待评课程,并按照预设的逻辑完成所有评价项的填写与提交。
它解决的痛点非常明确:解放人力,提升效率,确保评教任务按时、无遗漏地完成。无论是为了节省自己的时间,还是出于技术探索的兴趣,这个项目都极具实践价值。它适合有一定Python基础,对网页自动化感兴趣的同学。你不需要是爬虫或测试专家,只要会安装Python库、能看懂基本的HTML结构,就能跟着一步步实现。整个过程,你会接触到浏览器自动化、网页元素定位、模拟用户交互等核心技能,这些技能在数据采集、UI自动化测试等领域都是相通的。
2. 技术选型与工具准备
要实现自动评教,我们需要一套能“操纵”浏览器的工具。这里,Selenium是当之无愧的首选。它是一个强大的浏览器自动化框架,支持多种浏览器(Chrome, Firefox, Edge等),可以模拟几乎所有的用户操作:点击、输入、下拉选择、滚动等。相比于直接使用requests库模拟HTTP请求,Selenium操作的是真实的浏览器环境,能更好地处理JavaScript动态加载的页面、验证码(虽然本项目不涉及复杂验证码破解,但框架支持)以及基于Cookie/Session的登录状态保持,这对于需要登录且交互复杂的教务系统来说更加可靠和稳定。
我们的技术栈非常简单清晰:
- 编程语言:Python 3.7+。Python语法简洁,库生态丰富,是自动化任务的绝佳选择。
- 核心库:Selenium。通过
pip install selenium即可安装。 - 浏览器驱动:WebDriver。这是Selenium控制浏览器的桥梁。你需要根据你使用的浏览器版本,下载对应的驱动(如ChromeDriver for Chrome, geckodriver for Firefox, msedgedriver for Edge)。驱动版本必须与浏览器版本匹配,这是新手最容易踩的坑之一。
- 集成开发环境(IDE):推荐使用VSCode或PyCharm。它们能提供代码提示、调试等功能,提升开发效率。对于纯新手,从IDLE或简单的文本编辑器开始也完全可以。
注意:下载WebDriver后,需要将其所在目录添加到系统的PATH环境变量中,或者将驱动文件直接放在Python的安装目录下(与python.exe同级),这样Selenium才能找到它。一个更稳妥的做法是在代码中指定驱动的绝对路径。
除了这些,你还需要准备好你的教务系统登录账号和密码。强烈建议在项目初期使用测试账号,或者确保你的脚本逻辑足够稳健,避免因脚本错误导致账号被锁或提交异常数据。
3. 环境搭建与Selenium配置实战
光说不练假把式,我们立刻开始动手搭建环境。假设我们选择最流行的Chrome浏览器作为自动化载体。
3.1 安装Python与Selenium库
首先,确保你的电脑上安装了Python。打开命令行(CMD或Terminal),输入python --version检查。如果没有安装,去Python官网下载安装包,安装时务必勾选“Add Python to PATH”。
安装Selenium库只需一行命令:
pip install selenium如果下载速度慢,可以使用国内镜像源,例如:
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple3.2 下载与配置ChromeDriver
- 查看Chrome版本:打开Chrome浏览器,点击右上角三个点 -> 帮助 -> 关于Google Chrome,记下版本号(例如:124.0.6367.91)。
- 下载对应驱动:访问ChromeDriver的官方下载站点或国内镜像站。找到与你的Chrome浏览器主版本号(例如124)完全一致的ChromeDriver版本进行下载。
- 配置驱动:
- 方法一(推荐,灵活):将下载的
chromedriver.exe文件放在一个固定的、你容易记住的目录,比如D:\WebDriver\。然后在Python代码中,使用绝对路径初始化。 - 方法二(简单):将
chromedriver.exe直接复制到Python的安装目录下(例如C:\Users\你的用户名\AppData\Local\Programs\Python\Python39\)。
- 方法一(推荐,灵活):将下载的
3.3 编写第一个自动化测试脚本
让我们写一个简单的脚本来验证环境是否配置成功。这个脚本会打开百度,搜索一个关键词。
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys import time # 指定ChromeDriver的路径(如果已加入PATH,则不需要此句) driver_path = r‘D:\WebDriver\chromedriver.exe‘ # 请修改为你的实际路径 # 创建Chrome浏览器驱动实例 driver = webdriver.Chrome(executable_path=driver_path) # 如果驱动在PATH中,直接 webdriver.Chrome() try: # 打开百度首页 driver.get(‘https://www.baidu.com‘) print(‘当前页面标题:‘, driver.title) # 定位搜索框,输入关键词 search_box = driver.find_element(By.ID, ‘kw‘) # 百度搜索框的id是‘kw‘ search_box.send_keys(‘Selenium自动化‘) search_box.send_keys(Keys.RETURN) # 模拟按下回车键 # 等待2秒,查看结果 time.sleep(2) print(‘搜索后页面标题:‘, driver.title) finally: # 等待5秒后关闭浏览器 time.sleep(5) driver.quit()运行这个脚本,如果能看到Chrome浏览器自动打开、访问百度、输入文字并搜索,最后自动关闭,那么恭喜你,Selenium环境配置成功!
实操心得:在开发调试阶段,可以在
driver.quit()前加上time.sleep(30)之类的长等待,方便你观察页面状态,检查元素定位是否正确。正式脚本中应使用更智能的等待方式(后面会讲)。
4. 教务系统页面分析与元素定位策略
环境搭好了,接下来是最关键的一步:分析你的教务系统页面。不同的学校可能使用不同的系统(如强智、清元优软、金智等),但评教流程大同小异。你需要手动走一遍评教流程,并用浏览器的开发者工具(F12打开)仔细观察。
4.1 登录页面分析
打开教务系统登录页,分析登录表单。
- 找到用户名和密码输入框:右键点击输入框,选择“检查”。在Elements面板中,查看该输入框的HTML属性。常见的定位依据有:
id:最理想的定位方式,如id=“username”。name:如name=“userAccount”。class name:但class可能不唯一,需谨慎。XPath或CSS Selector:当元素没有明显唯一标识时使用。
- 找到登录按钮:同样检查其属性。
- 注意验证码:如果系统有验证码,本项目暂不处理复杂图像识别。你可以考虑:
- 手动输入验证码,通过
time.sleep(30)给脚本预留手动操作时间。 - 研究验证码接口,但难度较大,且可能违反系统规定。
- 手动输入验证码,通过
4.2 评教主页面与课程列表分析
登录成功后,找到“教学评价”或“学生评教”入口并进入。你会看到一个待评价课程列表。
- 课程列表结构:通常是一个
<table>或一系列<div>/<li>。你需要找到包裹每个课程项的HTML元素。 - “评价”或“进入”按钮:每个课程旁会有一个按钮。检查这个按钮的定位信息。通常可以通过课程名称的相邻关系或列表索引来定位。
4.3 评价表单页面分析
点击进入某门课程的评价页面。这是最复杂的部分。
- 评价项:通常是多个评分题(如“教学态度”、“教学内容”),形式可能是单选按钮(
<input type=“radio”>)、下拉列表(<select>)或滑块。你需要找出每个评分题对应的所有选项。 - 选项定位:对于单选按钮,它们通常有相同的
name属性(代表同一道题),不同的value属性(代表不同分值)。例如:name=“q1” value=“A”(对应优秀),name=“q1” value=“B”(对应良好)。 - 文本域:可能还有主观评价的文本框(
<textarea>)。 - 提交按钮:最后是“提交”或“保存”按钮。
4.4 Selenium元素定位方法详解
Selenium提供了多种定位元素的方法,对应By类的不同属性:
| 定位方式 | 示例代码 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|---|
| By.ID | find_element(By.ID, “username”) | 元素有唯一id属性时 | 定位最快、最准确 | 依赖id存在且唯一 |
| By.NAME | find_element(By.NAME, “password”) | 表单元素常用 | 较为常见和稳定 | 可能不唯一 |
| By.CLASS_NAME | find_element(By.CLASS_NAME, “btn-submit”) | 通过CSS类定位 | 可直接使用样式类名 | 类名常不唯一,需组合使用 |
| By.TAG_NAME | find_element(By.TAG_NAME, “input”) | 定位特定标签类型 | 简单 | 通常返回多个元素,需进一步筛选 |
| By.LINK_TEXT | find_element(By.LINK_TEXT, “教学评价”) | 精确匹配超链接文本 | 对链接定位直接 | 文本必须完全匹配 |
| By.PARTIAL_LINK_TEXT | find_element(By.PARTIAL_LINK_TEXT, “评价”) | 模糊匹配链接文本 | 容错性稍好 | 可能匹配到多个 |
| By.XPATH | find_element(By.XPATH, ‘//*[@id=“courseList”]/div[1]/button’) | 功能最强大的定位方式 | 非常灵活,可定位几乎任何元素 | 语法相对复杂,路径可能因页面微小改动而失效 |
| By.CSS_SELECTOR | find_element(By.CSS_SELECTOR, “#courseList .btn-evaluate”) | 类似CSS选择器 | 语法简洁,效率通常比XPATH高 | 需要了解CSS选择器语法 |
核心技巧:优先使用
ID和NAME,因为它们通常最稳定。如果不行,尝试组合CSS_SELECTOR,例如“input[name=‘q1’][value=‘A’]”可以精准定位到名为q1且值为A的单选按钮。XPATH是最后的杀手锏,但尽量使用相对路径和属性结合,避免使用绝对路径(如/html/body/div[5]/div[2]/...),因为绝对路径极其脆弱。
5. 自动评教脚本核心逻辑与代码实现
掌握了定位方法,我们就可以开始构建完整的自动评教脚本了。脚本的逻辑流程如下:
- 初始化浏览器驱动,打开登录页。
- 定位并填写用户名、密码,点击登录。
- 等待页面跳转,定位并点击“教学评价”入口。
- 在评价列表页面,获取所有待评价课程的元素列表。
- 循环遍历每个课程: a. 定位并点击该课程的“进入评价”按钮。 b. 在新打开的标签页或页面中,定位所有评价项。 c. 根据预设评分逻辑(如全部选“优秀”,或随机选择),对每个评价项进行操作(点击单选按钮、选择下拉选项等)。 d. 定位并点击“提交”按钮。 e. 处理提交后的确认对话框(如果有)。 f. 关闭当前评价标签页或返回列表页。
- 所有课程评价完毕后,关闭浏览器。
下面是一个高度简化的代码框架,展示了核心步骤。请注意,其中的选择器(ID、XPath等)需要你根据自己学校的教务系统实际情况进行替换。
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time # 初始化浏览器 driver = webdriver.Chrome() # 假设驱动已在PATH中 driver.implicitly_wait(10) # 设置隐式等待10秒 wait = WebDriverWait(driver, 15) # 设置显式等待对象,最长等15秒 # 1. 打开登录页 login_url = ‘你的教务系统登录页地址‘ driver.get(login_url) # 2. 登录 username_input = driver.find_element(By.ID, ‘usernameInputId‘) # 替换为实际ID password_input = driver.find_element(By.ID, ‘passwordInputId‘) # 替换为实际ID login_button = driver.find_element(By.ID, ‘loginButtonId‘) # 替换为实际ID username_input.send_keys(‘你的学号‘) password_input.send_keys(‘你的密码‘) login_button.click() # 3. 进入评教模块 (示例:通过链接文本点击) try: eval_link = wait.until(EC.element_to_be_clickable((By.LINK_TEXT, ‘教学评价‘))) eval_link.click() except Exception as e: print(“未找到‘教学评价’链接,尝试其他方式...“) # 可以尝试通过XPath或CSS定位 # driver.find_element(By.XPATH, ‘//a[contains(@href, “evaluate”)]‘).click() # 4. 获取待评课程列表 (示例:假设每个课程项是一个class为‘course-item’的div) time.sleep(3) # 等待列表加载,实际应用应使用显式等待 course_items = driver.find_elements(By.CLASS_NAME, ‘course-item‘) # 替换为实际选择器 print(f“找到 {len(course_items)} 门待评价课程“) # 5. 遍历课程进行评价 for index, item in enumerate(course_items): print(f“正在处理第 {index+1} 门课程...“) # 在列表页点击“进入评价”按钮 (假设按钮在course-item内部) try: # 重新定位当前课程项的按钮,防止元素过时 eval_btn = item.find_element(By.CLASS_NAME, ‘btn-evaluate‘) # 替换为实际选择器 eval_btn.click() except Exception as e: print(f“第 {index+1} 门课程找不到评价按钮,跳过。错误:{e}“) continue # 等待新窗口/页面打开,并切换到新窗口 time.sleep(2) original_window = driver.current_window_handle for window_handle in driver.window_handles: if window_handle != original_window: driver.switch_to.window(window_handle) break # 现在在新页面(评价表单页) try: # 示例:评价项1 - 教学态度,选择‘优秀’ (value=‘A’) q1_radio = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, “input[name=‘q1‘][value=‘A‘]“))) # 如果单选按钮不可见,可能需要先滚动到元素位置 driver.execute_script(“arguments[0].scrollIntoView(true);“, q1_radio) time.sleep(0.5) q1_radio.click() # 示例:评价项2 - 教学内容,选择‘良好’ (value=‘B’) q2_radio = driver.find_element(By.CSS_SELECTOR, “input[name=‘q2‘][value=‘B‘]“) q2_radio.click() # 示例:主观评价文本框(如果有) try: comment_box = driver.find_element(By.NAME, ‘suggestions‘) comment_box.send_keys(‘老师讲课认真,内容充实。‘) # 预设评语 except: print(“未找到主观评价框,跳过。“) # 提交评价 submit_btn = driver.find_element(By.ID, ‘submitButtonId‘) # 替换为实际ID submit_btn.click() # 处理可能的确认弹窗 time.sleep(1) try: alert = driver.switch_to.alert alert.accept() # 点击确认 print(“已处理提交确认弹窗。“) except: pass # 没有弹窗则继续 print(f“第 {index+1} 门课程评价提交成功!“) except Exception as e: print(f“第 {index+1} 门课程评价过程中出错:{e}“) finally: # 关闭当前评价页,切换回主窗口 driver.close() driver.switch_to.window(original_window) # 等待列表页稳定 time.sleep(2) # 6. 所有课程评价完成 print(“\n所有课程评价已完成!“) time.sleep(3) driver.quit()6. 高级技巧与稳定性优化
上面的基础脚本能跑起来,但要在各种网络波动、页面加载速度不同的真实环境中稳定运行,还需要加入一些“润滑剂”和“安全气囊”。
6.1 智能等待策略
time.sleep()是固定等待,效率低下且不可靠。Selenium提供了更优的等待方式:
- 隐式等待 (Implicit Wait):
driver.implicitly_wait(10)设置一个全局超时时间。在查找任何元素时,如果元素没有立即出现,WebDriver会轮询DOM最多10秒。注意:设置一次即可对整个driver生命周期生效,但和显式等待混用可能导致超时时间叠加。 - 显式等待 (Explicit Wait):针对某个特定条件进行等待,更加灵活精准。这是推荐的主要等待方式。
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC wait = WebDriverWait(driver, 15) # 最长等待15秒 # 等待元素可点击 button = wait.until(EC.element_to_be_clickable((By.ID, “myButton“))) # 等待元素出现在DOM中 element = wait.until(EC.presence_of_element_located((By.NAME, “myElement“))) # 等待元素可见 element = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, “myClass“))) button.click()
6.2 处理动态加载与iframe
- 动态加载内容:有些列表是滚动到底部才加载更多(懒加载)。此时,简单的
find_elements可能只能获取到初始的一部分。你需要模拟滚动操作:driver.execute_script(“window.scrollTo(0, document.body.scrollHeight);“) time.sleep(2) # 等待新内容加载 # 再次查找元素 - iframe/框架页:如果评价表单嵌在
<iframe>里,你必须先切换到该iframe内,才能操作其中的元素。# 通过ID或索引切换 driver.switch_to.frame(‘iframe_id‘) # 或者 driver.switch_to.frame(0) # 切换到第一个iframe # 在iframe内操作... # 操作完毕后切回主文档 driver.switch_to.default_content()
6.3 评分逻辑的多样化与人性化
全部打满分(优秀)可能过于明显。可以设计更“人性化”的评分逻辑:
- 随机评分:在“优秀”、“良好”之间随机选择,模拟真实评价的波动。
import random options = [‘A‘, ‘B‘, ‘C‘] # 对应优秀、良好、中等 selected_value = random.choice(options) driver.find_element(By.CSS_SELECTOR, f“input[name=‘q1‘][value=‘{selected_value}‘]“).click() - 权重评分:让“优秀”的概率更高,但偶尔出现“良好”。
selected_value = random.choices([‘A‘, ‘B‘], weights=[0.8, 0.2])[0] - 主观评语库:准备一个评语列表,每次随机选取一条填入文本框,避免千篇一律。
6.4 异常处理与日志记录
健壮的程序必须能处理异常,并记录下发生了什么。
import logging logging.basicConfig(level=logging.INFO, format=‘%(asctime)s - %(levelname)s - %(message)s‘) for index, item in enumerate(course_items): try: # ... 评价操作 ... logging.info(f“第 {index+1} 门课程评价成功。“) except NoSuchElementException as e: logging.error(f“第 {index+1} 门课程:找不到页面元素。错误信息:{e}“) # 可以截图保存,便于事后分析 driver.save_screenshot(f‘error_course_{index+1}.png‘) continue # 跳过当前课程,继续下一个 except TimeoutException as e: logging.warning(f“第 {index+1} 门课程:页面加载超时,重试中...“) # 可以加入重试逻辑 continue except Exception as e: logging.critical(f“第 {index+1} 门课程:发生未知错误:{e}“) # 严重错误,可能考虑中断脚本 break7. 常见问题排查与实战避坑指南
在实际操作中,你几乎一定会遇到下面这些问题。这里我把踩过的坑和解决方案整理出来。
7.1 元素定位失败(NoSuchElementException)
这是最常见的问题。
- 原因1:页面尚未加载完成。
- 解决:在
find_element操作前增加等待。务必使用显式等待(WebDriverWait)代替固定的time.sleep。
- 解决:在
- 原因2:定位器(Selector)写错了或已过时。
- 解决:使用浏览器开发者工具的
Console面板测试你的定位器。例如,在Console中输入$$(“input[name=‘q1‘]”)(对应CSS)或$x(“//input[@name=‘q1‘]”)(对应XPath),看是否能正确选中元素。确保定位器能唯一标识目标元素。
- 解决:使用浏览器开发者工具的
- 原因3:元素在iframe或shadow DOM内。
- 解决:检查元素是否在
<iframe>标签内,如果是,先用driver.switch_to.frame()切换进去。
- 解决:检查元素是否在
- 原因4:元素是动态生成的,DOM结构发生了变化。
- 解决:尝试使用更稳定的定位方式,例如通过父元素的稳定ID或属性,结合相对路径来定位子元素。避免使用绝对索引(如
div[3])。
- 解决:尝试使用更稳定的定位方式,例如通过父元素的稳定ID或属性,结合相对路径来定位子元素。避免使用绝对索引(如
7.2 点击或交互无效(ElementNotInteractableException)
- 原因1:元素被遮挡(例如被弹窗、其他元素覆盖)。
- 解决:等待遮挡物消失,或者使用JavaScript直接点击:
driver.execute_script(“arguments[0].click();“, element)。
- 解决:等待遮挡物消失,或者使用JavaScript直接点击:
- 原因2:元素不可见(例如在视窗外,或
style=“display: none;”)。- 解决:先滚动到元素所在位置:
driver.execute_script(“arguments[0].scrollIntoView(true);“, element),然后再操作。对于display:none的元素,通常无法直接交互,需要检查是否有其他触发其显示的按钮。
- 解决:先滚动到元素所在位置:
- 原因3:页面有多个相同定位的元素,你操作的不是目标。
- 解决:
find_element只返回第一个匹配项。使用find_elements获取列表,通过索引或遍历找到正确的那个。
- 解决:
7.3 浏览器被检测为自动化工具
一些网站会检测浏览器是否被Selenium等工具控制。
- 现象:无法登录,或登录后立即跳转/退出。
- 解决:
- 使用
undetected-chromedriver库:这是一个修改版的ChromeDriver,可以规避一些常见的检测。安装:pip install undetected-chromedriver,使用时导入import undetected_chromedriver as uc,然后用driver = uc.Chrome()启动。 - 添加实验性选项:在启动Chrome时添加一些参数,隐藏自动化特征。
from selenium.webdriver.chrome.options import Options options = Options() options.add_argument(‘--disable-blink-features=AutomationControlled‘) options.add_experimental_option(“excludeSwitches“, [“enable-automation“]) options.add_experimental_option(‘useAutomationExtension‘, False) driver = webdriver.Chrome(options=options) # 同时执行一个JavaScript来覆盖navigator.webdriver属性 driver.execute_script(“Object.defineProperty(navigator, ‘webdriver‘, {get: () => undefined})“) - 使用
7.4 验证码处理
如果登录或提交时有验证码,会极大增加自动化难度。
- 简单数字/字母验证码:可以考虑使用OCR库(如
pytesseract)进行识别,但识别率受图片复杂度影响很大,且需要额外处理图像(二值化、去噪等)。 - 复杂验证码(滑块、点选、语序):基本超出了简单自动化脚本的范畴,可能需要借助第三方打码平台(涉及费用和稳定性),或者考虑半自动化方案。
- 半自动化方案(推荐):在脚本运行到验证码步骤时,暂停并提示用户手动输入。可以通过
input()函数在控制台等待输入,或者用time.sleep(30)留出足够时间手动操作浏览器。
7.5 网络不稳定或页面超时
- 解决:合理设置WebDriver的超时时间,并加入重试机制。
from selenium.common.exceptions import TimeoutException import time max_retries = 3 for attempt in range(max_retries): try: driver.get(url) # ... 后续操作 ... break # 成功则跳出重试循环 except TimeoutException: print(f“第{attempt+1}次尝试超时,{‘重试中...‘ if attempt < max_retries-1 else ‘已超过最大重试次数。‘}“) if attempt == max_retries - 1: raise # 重试次数用尽,抛出异常 time.sleep(2) # 等待一下再重试
8. 脚本的封装、调度与安全建议
一个完整的项目,不仅仅是写一段脚本,还要考虑如何方便地使用和维护它。
8.1 配置与代码分离
不要把账号密码、网址等敏感信息硬编码在脚本里。创建一个config.py或config.ini文件来管理配置。
# config.py USERNAME = ‘你的学号‘ PASSWORD = ‘你的密码‘ LOGIN_URL = ‘https://jwxt.yourschool.edu.cn‘在主脚本中导入配置:
import config username_input.send_keys(config.USERNAME)8.2 使用函数和类进行封装
将不同功能模块化,使代码更清晰、易维护。
class JwxtAutoEvaluator: def __init__(self, username, password): self.driver = None self.username = username self.password = password self.wait = None def setup_driver(self): # 初始化浏览器和等待对象 options = webdriver.ChromeOptions() # ... 添加选项 ... self.driver = webdriver.Chrome(options=options) self.driver.implicitly_wait(10) self.wait = WebDriverWait(self.driver, 15) def login(self): # 登录逻辑 pass def get_course_list(self): # 获取课程列表逻辑 pass def evaluate_single_course(self, course_element): # 评价单门课程逻辑 pass def run(self): # 主运行逻辑 self.setup_driver() try: self.login() courses = self.get_course_list() for course in courses: self.evaluate_single_course(course) finally: self.driver.quit() if __name__ == ‘__main__‘: evaluator = JwxtAutoEvaluator(config.USERNAME, config.PASSWORD) evaluator.run()8.3 定时任务与自动化调度
如果你希望脚本在特定时间(如评教期开始后)自动运行,可以使用系统级的任务调度。
- Windows:使用“任务计划程序”。
- macOS/Linux:使用
cron。 你需要创建一个批处理文件(.bat)或Shell脚本(.sh)来调用你的Python脚本,然后在任务计划中设置它。
8.4 重要的安全与合规提醒
这是最重要的一部分,请务必仔细阅读:
- 遵守校规:在运行任何自动化脚本前,务必仔细阅读你所在学校关于教务系统使用的规定。明确是否允许自动化操作。本教程仅供技术学习交流,请勿用于任何可能违反规定或干扰系统正常运行的用途。
- 尊重服务器负载:在脚本中加入随机延迟(
time.sleep(random.uniform(1, 3))),模拟真人操作间隔,避免高频请求对服务器造成压力。 - 保护个人隐私:妥善保管包含账号密码的配置文件,不要上传到公开的代码仓库(如GitHub)。使用
.gitignore文件忽略配置文件。 - 责任自负:自动化操作存在风险,如因脚本逻辑错误导致评价数据异常(如全部零分、重复提交等),后果需自行承担。请在运行前充分测试,可以先对一两门不重要的课程进行试运行。
最后,技术是工具,如何使用它取决于你。通过这个项目,你不仅学会了Selenium自动化,更重要的是掌握了分析问题、分解流程、编写稳健代码的思维方式。在实际操作中,耐心和细致是成功的关键,多使用print语句输出调试信息,多利用浏览器的开发者工具进行观察和分析,遇到问题就回到这里来对照排查。
