尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

软考成绩自动查询小助手:Python + Selenium 实现定时监控

软考成绩自动查询小助手:Python + Selenium 实现定时监控
📅 发布时间:2026/7/1 19:19:01

软考成绩自动查询小助手:Python + Selenium 实现定时监控

  • 软考成绩自动查询小助手:Python + Selenium 实现定时监控
    • 📌 背景与痛点
    • 🛠️ 技术栈与核心依赖
    • 🔐 敏感性处理:如何保护账号密码与本地路径
      • 1. 使用环境变量(推荐)
      • 2. 使用配置文件(如 `.env` 或 `config.ini`)
    • 🧩 功能模块详解
      • 1. 浏览器驱动初始化(`get_driver`)
      • 2. 登录流程(`login`)
      • 3. 成绩查询(`query_score`)
      • 4. 定时任务(`job`)
      • 5. 主程序
    • 🚀 使用步骤
    • ⚠️ 注意事项
    • 📝 脱敏后的完整代码
    • 📢 最后的话

软考成绩自动查询小助手:Python + Selenium 实现定时监控

还在每天手动刷新软考官网看成绩出了没?不如写个脚本替你盯着,一旦发布立刻通知你!
本文将分享一个基于 Python + Selenium 的自动化查询工具,并重点讲解如何对敏感信息进行安全处理。


📌 背景与痛点

每年软考(计算机技术与软件专业技术资格)成绩公布时,考生们总忍不住反复登录官网刷新页面,既耗费精力又容易错过第一时间。
其实,这种重复性工作完全可以用自动化脚本代替——只要我们能让脚本自动登录、定时查询,并在检测到成绩时及时提醒即可。

本脚本正是为此而生,它使用Selenium模拟浏览器操作,配合schedule库实现定时循环查询,一旦发现“成绩已发布”或“合格”字样,就会在日志中高亮提示。


🛠️ 技术栈与核心依赖

  • Python 3.7+
  • Selenium– 浏览器自动化驱动
  • Edge WebDriver– 与 Microsoft Edge 浏览器配合(亦可改用 Chrome)
  • schedule– 轻量级定时任务调度
  • logging– 日志记录,方便追踪运行状态

安装命令:

pipinstallselenium schedule

同时请确保下载与本地 Edge 版本匹配的 Edge WebDriver,并将其所在目录加入系统 PATH。


🔐 敏感性处理:如何保护账号密码与本地路径

原代码中直接硬编码了用户名、密码和本地用户数据目录,这存在严重的安全隐患(例如代码泄露或版本控制意外提交)。
改进方案:将敏感信息移至环境变量或外部配置文件,并在代码中动态读取。

1. 使用环境变量(推荐)

在系统或虚拟环境中设置:

exportRUANKAO_USERNAME="your_id"exportRUANKAO_PASSWORD="your_password"exportRUANKAO_USER_DATA_DIR="/path/to/profile"

然后在 Python 中通过os.environ.get()获取。

2. 使用配置文件(如.env或config.ini)

若不想设置环境变量,也可用configparser读取本地配置文件(需将配置文件加入.gitignore)。

本文示例将采用环境变量方式,既简单又安全。


🧩 功能模块详解

1. 浏览器驱动初始化(get_driver)

  • 加载 Edge 选项,关闭自动化控制特征(防止被网站识别为爬虫)。
  • 启用用户数据目录(user-data-dir),用于持久化保存登录会话和 Cookie,避免每次重复登录。
  • 执行 JS 隐藏navigator.webdriver属性,进一步降低检测风险。

2. 登录流程(login)

  • 访问登录页,检测当前是否已登录(通过判断 URL 或页面元素)。
  • 若未登录,则:
    1. 点击“切换账号密码登录”(因为默认可能为扫码)。
    2. 输入用户名和密码。
    3. 触发滑动验证码(div.tncode),此时脚本暂停并等待用户手动滑动。
    4. 用户完成后按回车继续,点击登录按钮。
  • 登录成功后,后续查询可直接复用会话。

⚠️为何验证码必须手动?
滑动验证码通常包含复杂的行为轨迹分析,自动破解成本高且违反网站条款,故采用“半自动”方式——脚本触发验证,人工完成,既合规又稳定。

3. 成绩查询(query_score)

  • 访问成绩查询页。
  • 若页面显示“考区列表”,则自动点击“浙江”(可根据需要修改)进入具体考区。
  • 检查页面源码中是否包含“成绩暂未发布”、“合格”或“分数”等关键词。
  • 若找到成绩信息,则记录日志并返回成功标志;否则返回False或None(表示会话过期)。

4. 定时任务(job)

  • 每次执行前检查是否处于登录状态,若掉线则自动重登。
  • 调用query_score并根据返回值决定是否重试。

5. 主程序

  • 首次启动时先登录。
  • 立即执行一次查询。
  • 通过schedule.every(1).minutes.do(job, driver)设置固定间隔(本文设为 1 分钟,可调整)。
  • 保持主循环运行,直到用户按Ctrl+C退出。

🚀 使用步骤

  1. 克隆/创建脚本文件,将下方脱敏后的代码保存为query_ruankao.py。
  2. 安装依赖:pip install selenium schedule
  3. 下载 Edge WebDriver并确保可执行。
  4. 设置环境变量(或直接在代码中临时替换):
    exportRUANKAO_USERNAME="你的证件号"exportRUANKAO_PASSWORD="你的密码"exportRUANKAO_USER_DATA_DIR="./edge_profile"# 任意本地路径
  5. 运行脚本:
    python query_ruankao.py
  6. 首次运行会打开浏览器,若未登录,则脚本会停留在滑动验证码处,手动完成滑动后按回车继续。
  7. 之后脚本会定时自动查询,日志会输出每次的结果。

⚠️ 注意事项

  • 验证码处理:每次登录都可能需要手动滑动,若会话保持良好(通过user-data-dir),则后续无需重复登录。
  • 页面结构变化:软考官网可能会更新 HTML 结构,届时需调整 CSS 选择器或 XPath。
  • 查询间隔:建议不要过于频繁(至少 1 分钟),避免给服务器造成压力。
  • 运行环境:需有图形界面(Windows / Linux with X11 / macOS),因为 Selenium 需要真实浏览器。
  • 隐私安全:切勿将包含真实账号的代码上传至公开仓库。

📝 脱敏后的完整代码

以下代码已将所有敏感信息替换为环境变量读取,并添加了详细的注释。你可以直接复制使用,只需正确设置环境变量即可。

importosimportloggingimporttimeimportschedulefromseleniumimportwebdriverfromselenium.common.exceptionsimportNoSuchElementException,TimeoutExceptionfromselenium.webdriver.common.byimportByfromselenium.webdriver.edge.optionsimportOptionsfromselenium.webdriver.supportimportexpected_conditionsasECfromselenium.webdriver.support.uiimportWebDriverWait# ---------- 从环境变量读取敏感配置 ----------USERNAME=os.environ.get("RUANKAO_USERNAME")PASSWORD=os.environ.get("RUANKAO_PASSWORD")USER_DATA_DIR=os.environ.get("RUANKAO_USER_DATA_DIR","./edge_profile")# 默认相对路径ifnotUSERNAMEornotPASSWORD:raiseValueError("请设置环境变量 RUANKAO_USERNAME 和 RUANKAO_PASSWORD")LOGIN_URL="https://bm.ruankao.org.cn/sign/in"QUERY_URL="https://bm.ruankao.org.cn/report/query"CHECK_INTERVAL_MINUTES=1# 查询间隔(分钟)logging.basicConfig(level=logging.INFO,format="%(asctime)s - %(levelname)s - %(message)s")defget_driver():"""启动 Edge 浏览器,使用持久化用户目录"""options=Options()options.add_argument("--disable-gpu")options.add_argument("--no-sandbox")options.add_argument("--disable-blink-features=AutomationControlled")options.add_experimental_option("excludeSwitches",["enable-automation"])options.add_experimental_option("useAutomationExtension",False)options.add_argument("--start-maximized")options.add_argument(f"--user-data-dir={USER_DATA_DIR}")driver=webdriver.Edge(options=options)# 隐藏自动化特征driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")returndriverdefis_logged_in(driver):"""检测是否已登录(通过检查当前URL或页面元素)"""current_url=driver.current_urlif"sign/in"incurrent_url:returnFalsetry:# 查找用户头像菜单,如果存在则认为已登录driver.find_element(By.CSS_SELECTOR,".layui-nav-item img.layui-nav-img")returnTrueexceptNoSuchElementException:returnFalsedeflogin(driver):"""执行登录(若已登录则跳过)"""logging.info(f"正在访问登录页:{LOGIN_URL}")driver.get(LOGIN_URL)time.sleep(2)ifnotis_logged_in(driver):logging.info("未登录,开始执行登录流程...")wait=WebDriverWait(driver,10)# 1. 切换到账号密码登录try:change_btn=wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,"a.change_login")))driver.execute_script("arguments[0].click();",change_btn)logging.info("已切换到账号密码登录")time.sleep(1.5)exceptTimeoutException:logging.info("未找到切换按钮,可能已经在账号密码模式")# 2. 填写账号和密码try:username_input=wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,".layui-input.username")))password_input=driver.find_element(By.CSS_SELECTOR,".layui-input.password.pwd1")username_input.clear()username_input.send_keys(USERNAME)password_input.clear()password_input.send_keys(PASSWORD)logging.info("账号密码已填写")exceptNoSuchElementExceptionase:logging.error(f"找不到账号或密码输入框:{e}")raise# 3. 处理滑动验证码(需人工干预)try:tncode_div=driver.find_element(By.CSS_SELECTOR,"div.tncode")driver.execute_script("arguments[0].click();",tncode_div)logging.info("已触发滑动验证码,请在浏览器中手动完成滑动")input("完成滑动验证后,在此按回车继续...")time.sleep(1)exceptNoSuchElementException:logging.info("未找到滑动验证码元素,可能无需验证")# 4. 点击登录按钮try:submit_btn=driver.find_element(By.CSS_SELECTOR,".layui-btn.loginBtn")driver.execute_script("arguments[0].click();",submit_btn)logging.info("已点击登录按钮")exceptNoSuchElementExceptionase:logging.error(f"找不到登录按钮:{e}")raisetime.sleep(5)if"sign/in"indriver.current_url:logging.error("登录失败,请检查账号密码或验证码")returnFalseelse:logging.info("登录成功")returnTrueelse:logging.info("检测到已登录,无需重复登录")returnTruedefquery_score(driver):"""访问成绩查询页面,处理考区列表页的跳转"""logging.info(f"正在访问成绩查询页面:{QUERY_URL}")driver.get(QUERY_URL)time.sleep(5)# 检查是否进入考区列表页page_source=driver.page_sourceif"机构名称"inpage_sourceand"报名有效时间"inpage_source:logging.warning("检测到考区列表页,尝试点击'浙江'进入...")try:# 定位“浙江”对应的“进入”按钮zhejiang_entry=driver.find_element(By.XPATH,"//td[contains(text(),'浙江')]/following-sibling::td/a[contains(text(),'进入')]")driver.execute_script("arguments[0].click();",zhejiang_entry)logging.info("已点击'浙江'的'进入'按钮")time.sleep(3)page_source=driver.page_sourceexceptExceptionase:logging.error(f"点击'浙江'进入按钮失败:{e}")returnFalseelse:logging.info("当前页面不是考区列表页,直接检查成绩状态")# 检查成绩状态if"成绩暂未发布"inpage_source:logging.info("⏳ 成绩暂未发布,继续等待...")returnFalseelif"合格"inpage_sourceor"分数"inpage_sourceor"成绩"inpage_source:logging.info("🎉 成绩已发布!")try:score_element=driver.find_element(By.CSS_SELECTOR,".score-result")score_text=score_element.text logging.info(f"成绩详情:{score_text}")except:logging.info("请手动查看浏览器中的成绩页面。")returnTrueelse:if"sign/in"indriver.current_url:logging.warning("会话过期,需要重新登录")returnNoneelse:logging.info("未知状态,可能页面未完全加载或结构已变化")returnFalsedefjob(driver):"""定时任务"""logging.info("========== 执行定时查询 ==========")try:if"sign/in"indriver.current_url:logging.warning("检测到在登录页面,尝试重新登录...")ifnotlogin(driver):logging.error("重新登录失败,停止任务")returnresult=query_score(driver)ifresultisNone:logging.warning("会话过期,尝试重新登录...")iflogin(driver):query_score(driver)else:logging.error("重新登录失败")exceptExceptionase:logging.error(f"查询任务异常:{e}")if__name__=="__main__":driver=get_driver()try:ifnotlogin(driver):logging.error("首次登录失败,退出")driver.quit()exit()query_score(driver)schedule.every(CHECK_INTERVAL_MINUTES).minutes.do(job,driver)logging.info(f"定时任务已启动,每{CHECK_INTERVAL_MINUTES}分钟查询一次")whileTrue:schedule.run_pending()time.sleep(1)exceptKeyboardInterrupt:logging.info("用户中断,关闭浏览器")finally:driver.quit()

📢 最后的话

这个脚本已经在我自己的环境中稳定运行了几天,完美实现了“无人值守,成绩秒知”的目标。当然,它也存在一些局限性(如依赖浏览器界面、验证码需人工),但作为一个辅助工具已经足够实用。

如果你也正在等待软考成绩,不妨一试。记得保护好你的账号信息,用环境变量或配置文件隔离敏感数据。
如果你有更好的改进建议(例如接入邮件/微信通知),欢迎在评论区交流!


Happy Coding & Good Luck!🍀

相关新闻

  • Python数据分析课程期末考试判断题联系题100题
  • 5分钟搞定:PC版微信QQ防撤回终极方案,让重要消息永不消失
  • 3步开启智能办公:UI-TARS桌面AI助手实战指南

最新新闻

  • Playwright自动化测试覆盖率实战:从Istanbul插桩到CI集成
  • Selenium多语言站点自动化测试:数据驱动与框架设计实战
  • 基于Playwright的UI自动化测试平台:从架构设计到工程实践
  • 如何高效使用Bilibili Toolkit:终极B站辅助工具箱实战指南
  • 基于pytest与YAML的数据驱动接口自动化测试框架设计与实践
  • 西门子博图V15.1六层电梯单步运行PLC控制工程包(含HMI与完整调试文件)

日新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

周新闻

  • Windows字体自定义终极方案:No!! MeiryoUI完全指南
  • Deepin Boot Maker:告别命令行,3分钟制作Linux启动盘的智能解决方案
  • Plain Craft Launcher 2:重新定义你的Minecraft游戏体验

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号