2025年9月5日星期五

三节课自动学习任务脚本

1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/PfsP97若失效,可用地址

1.购买服务器

阿里云:

服务器购买地址

https://t.aliyun.com/U/PfsP97

若失效,可用地址

https://www.aliyun.com/activity/wuying/dj?source=5176.29345612&userCode=49hts92d

腾讯云:

https://curl.qcloud.com/wJpWmSfU

若失效,可用地址

https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=ad201ee2ef3b771157f72ee5464b1fea&from=console

华为云

https://activity.huaweicloud.com/cps.html?fromacct=64b5cf7cc11b4840bb4ed2ea0b2f4468&utm_source=V1g3MDY4NTY=&utm_medium=cps&utm_campaign=201905

2.部署教程

2024年最新青龙面板跑脚本教程(一)持续更新中

3.代码如下

# -*- coding:utf-8 -*-import timeimport randomfrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.common.action_chains import ActionChainsfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.common.exceptions import NoSuchElementExceptionfrom selenium.common.exceptions import TimeoutExceptionfrom selenium.webdriver.chrome.options import Optionsimport configparser
# 读取配置文件config = configparser.ConfigParser()config.read("config.ini", encoding="utf-8")
# 获取用户名和密码USERNAME = config.get("login""username")PASSWORD = config.get("login""password")
# 获取学习课程类型course_type = config.get("course_type","type")
class AutoCourseBot:    def __init__(self, username, password):        # 配置Chrome选项,启用静音        chrome_options = Options()        chrome_options.add_argument("--mute-audio")        self.driver = webdriver.Chrome(options=chrome_options)        self.driver.maximize_window()        self.wait = WebDriverWait(self.driver, 15)        self.username = username        self.password = password
    # ========== 工具函数 ==========    # def handle_popup(self):    #     """处理学习过程中的弹窗"""    #     try:    #         popup_btn = self.driver.find_element(By.CSS_SELECTOR, "div.score-popup button.close-btn")    #         if popup_btn.is_displayed():    #             popup_btn.click()    #             print(" 弹窗已关闭,继续学习")    #             time.sleep(3)    #     except NoSuchElementException:    #         pass    def handle_popup(self):        """处理学习过程中的弹窗(优化版)"""        try:            # 关键:等待弹窗按钮出现(最多等10秒),确保弹窗已加载            popup_btn = WebDriverWait(self.driver, 5).until(                EC.element_to_be_clickable((By.CSS_SELECTOR, "div.score-popup button.close-btn"))            )
            # 确认按钮可见且可点击            if popup_btn.is_displayed() and popup_btn.is_enabled():                popup_btn.click()                print(" 弹窗已关闭,继续学习")                # 等待弹窗消失(避免后续操作受影响)                WebDriverWait(self.driver, 10).until(                    EC.invisibility_of_element_located((By.CSS_SELECTOR, "div.score-popup"))                )                time.sleep(3)        except Exception:            pass
    def handle_leave_page_tip(self, wait_time=5):        try:            # 等待弹窗容器出现,最多等待wait_time秒            modal_container = WebDriverWait(self.driver, wait_time).until(                EC.presence_of_element_located((By.CSS_SELECTOR, "div.leave-page-tip-modal-container"))            )
            # 确认弹窗可见            if modal_container.is_displayed():                print("检测到学习状态中断提醒弹窗")
                # 查找并点击"继续学习"按钮                continue_button = modal_container.find_element(                    By.CSS_SELECTOR, "button.button"                )                continue_button.click()                print("已点击继续学习按钮")
                # 等待弹窗消失                WebDriverWait(self.driver, wait_time).until(                    EC.invisibility_of_element_located((By.CSS_SELECTOR, "div.leave-page-tip-modal-container"))                )        except TimeoutException:            pass        # except Exception as e:        #     print(f"处理弹窗时发生错误: {str(e)}")        try:            play_btn = WebDriverWait(self.driver, 5).until(                EC.element_to_be_clickable((By.CSS_SELECTOR, "xg-play .xgplayer-icon-play"))            )            play_btn.click()        except NoSuchElementException:            print(f"出现中断弹窗后,点击播放时出现异常!")
    def click_ai_option(self):        try:            # 此try中的代码为规避系统检测            # 找出AI题目标签            quiz_main = self.driver.find_element(By.CSS_SELECTOR,                                            "div.quiz-main")            time.sleep(2)            if quiz_main:                # 获取所有选项标签                options = quiz_main.find_elements(By.TAG_NAME, "li")
                # 随机选择一个选项                random_option = random.choice(options)
                # 点击选项中的单选按钮(quiz-radio元素)                # 优先点击单选按钮区域,更符合实际交互逻辑                # radio_button = random_option.find_element(By.CLASS_NAME, "quiz-radio")                random_option.click()        except NoSuchElementException:            pass
    def set_playback_rate_to_2x(self, wait_time=5):
        try:            # 等待播放速度控制元素出现            playbackrate_element = WebDriverWait(self.driver, wait_time).until(                EC.presence_of_element_located((By.CSS_SELECTOR, "xg-playbackrate.xgplayer-playbackrate"))            )
            # 点击播放速度控制元素,展开速度选择列表            playbackrate_element.click()            print("已点击播放速度控制器,展开选择列表")
            # 查找并点击2倍速选项(cname="2"的li元素)            two_x_element = WebDriverWait(self.driver, wait_time).until(                EC.element_to_be_clickable((By.CSS_SELECTOR, "xg-playbackrate.xgplayer-playbackrate li[cname='2']"))            )            two_x_element.click()            print("已设置播放速度为2倍速")        except TimeoutException:            print("超时:未找到播放速度控制元素或2倍速选项")        except NoSuchElementException:            print("未找到播放速度控制元素或2倍速选项")        except Exception as e:            print(f"设置播放速度时发生错误: {str(e)}")
    def have_cretificate(self):        try:            # 查找父标签            parent_element = self.driver.find_element(By.CSS_SELECTOR,"div.course-left")            try:                # 在父标签下查找目标子标签                parent_element.find_element(By.CSS_SELECTOR, "div.certInfo")                # 如果找到子标签,返回True                return True            except NoSuchElementException:                # 未找到子标签                return False        except NoSuchElementException:            # 未找到父标签            return False
    def is_video_playing_normally(self, timeout=5):
        try:            pause_icon = WebDriverWait(self.driver, timeout).until(                EC.visibility_of_element_located(                    (By.CSS_SELECTOR, "xg-play .xgplayer-icon .xgplayer-icon-pause")  # 暂停图标                )            )            return pause_icon.is_displayed()
        except TimeoutException:            # 超时说明任一条件未满足(加载中/未播放/控件未出现)            return False
    def get_progress(self):        """获取课程进度(已完成节数,总节数)"""        try:            finished_text = self.driver.find_element(By.CSS_SELECTOR, "span.section-finish").text            finished_num = int("".join(filter(str.isdigit, finished_text)))        except:            finished_num = 0        total_text = self.driver.find_element(By.CSS_SELECTOR, "span.section-total").text        total_num = int("".join(filter(str.isdigit, total_text)))
        return finished_num, total_num
    # ========== 核心功能 ==========    def login(self):        self.driver.get("https://sntelelearning.b.sanjieke.cn/login/sign_in")
        username_input = self.wait.until(            EC.presence_of_element_located((By.CSS_SELECTOR, "input#rc_select_0"))        )        username_input.send_keys(self.username)
        password_input = self.wait.until(            EC.presence_of_element_located((By.CSS_SELECTOR, "input.input-text[type='password']"))        )        password_input.send_keys(self.password)
        login_btn = self.wait.until(            EC.element_to_be_clickable((By.CSS_SELECTOR, "button.confirm-btn"))        )        login_btn.click()        print(" 登录成功")
    def get_all_course_links(self, course_type):        """翻页获取所有课程链接"""        card_module = self.wait.until(            EC.presence_of_element_located((By.CSS_SELECTOR, "div.card-item-container"))        )        time.sleep(5)        # 找到课程卡片里的所有入口 <a class="card-item">        course_links = card_module.find_elements(By.CSS_SELECTOR, "a.card-item")        if course_links:            # 0为通用 1为专业            course_links[int(course_type) - 1].click()            print("点击第一个课程入口,进入学习页面。")            time.sleep(5)            # 获取所有 a 标签            all_links = []  # 存储所有 a 标签        while True:            self.wait.until(EC.presence_of_all_elements_located((By.TAG_NAME, "a")))            a_tags = self.driver.find_elements(By.TAG_NAME, "a")            for a in a_tags:                href = a.get_attribute("href")                text = a.text.strip()                if href and "/course/" in href:                    all_links.append((text, href))            # 翻页            try:                next_btn = self.driver.find_element(By.CLASS_NAME, "ant-pagination-next")                if next_btn.get_attribute("aria-disabled") == "true":                    break                else:                    next_btn.click()                    time.sleep(5)            except:                break        return all_links
    def study_chapter(self):        """学习单个章节/小节"""        try:            menu_container = self.driver.find_element(By.CSS_SELECTOR, "div.menu-container")            try:                chapters = menu_container.find_elements(By.CSS_SELECTOR, "div.chapter-container.chapter-item")            except:                chapters=[]            try:                sections = menu_container.find_elements(By.CSS_SELECTOR, "div.chapter-container.chapter-section-item")            except:                sections=[]            # 判断是否是大章节(有子小节)            if len(sections) > 0 :                for sid, section in enumerate(sections, start=1):                    menu_container = self.driver.find_element(By.CSS_SELECTOR, "div.menu-container")                    sections = menu_container.find_elements(By.CSS_SELECTOR,"div.chapter-container.chapter-section-item")                    title = sections[sid - 1].find_element(By.CSS_SELECTOR, ".node-name-con").text.strip()                    print(f" 进入大章节: {title}")                    section_list = sections[sid - 1].find_elements(By.CSS_SELECTOR, ".section-container .node-item")                    time.sleep(1)                    self.driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", sections[sid - 1])                    # 判断是否已点击                    if "chapter-active" not in sections[sid - 1].get_attribute("class"):                        sections[sid - 1].click()                    # 找到子小节                    for sec_idx, section_sec in enumerate(section_list, start=1):                        menu_container = self.driver.find_element(By.CSS_SELECTOR, "div.menu-container")                        sections = menu_container.find_elements(By.CSS_SELECTOR,"div.chapter-container.chapter-section-item")                        sec_list = sections[sid - 1].find_elements(By.CSS_SELECTOR, ".section-container .node-item")                        status_list = sections[sid - 1].find_elements(By.CSS_SELECTOR, ".section-container .status-con")                        sec_title = sec_list[sec_idx - 1].find_element(By.CSS_SELECTOR, ".node-name-con").text.strip()                        if "section-finish" in status_list[sec_idx - 1].get_attribute("class"):                            status = "已完成 "                            print(sec_title, status)                        else:                            status = "未完成 "                            print(sec_title, status, "现在即将学习......")                            self.driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", sec_list[sec_idx - 1])                            time.sleep(2)                            WebDriverWait(self.driver, 5).until(                                EC.element_to_be_clickable((By.CSS_SELECTOR, ".section-container .node-item"))                            )
                            sec_list[sec_idx - 1].click()                            self.play_video(sec_title, 2, sec_idx, sid)
            if len(chapters) > 0:                for idx, chapter in enumerate(chapters, 1):                    menu_container = self.driver.find_element(By.CSS_SELECTOR, "div.menu-container")                    chapters = menu_container.find_elements(By.CSS_SELECTOR, "div.chapter-container.chapter-item")                    title = chapters[idx - 1].find_element(By.CSS_SELECTOR, ".node-name-con").text.strip()                    # 判断是否完成                    if "chapter-finish" in chapters[idx - 1].get_attribute("class"):                        status = "已完成 "                        print(title, status)                    else:                        status = "未完成 "                        print(title, status, "现在即将学习......")                        self.driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", chapters[idx - 1])                        time.sleep(2)
                        WebDriverWait(self.driver, 5).until(                            EC.element_to_be_clickable((By.CSS_SELECTOR, ".chapter-container .node-item"))                        )
                        chapters[idx - 1].click()                        self.play_video(title, 1, idx, 0)        except Exception as e:            print(f"⚠️ 小节异常,跳过: {e}")
    def play_video(self, title, ctype, index, sid):        """通用视频播放逻辑"""        try:            # 点击播放按钮            try:                # 定位视频容器,确保其在可视区域内                try:                    video_container = WebDriverWait(self.driver, 5).until(                        EC.presence_of_element_located((By.CSS_SELECTOR, "div.video-player-container"))  # 视频容器选择器                    )                    # 滚动到视频容器可见(scrollIntoView() 会自动将元素滚动到可视区域)                    self.driver.execute_script(                        "arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});",                        video_container                    )                    time.sleep(0.5)  # 短暂等待滚动完成                except:                    pass                play_btn = WebDriverWait(self.driver, 5).until(                    EC.element_to_be_clickable((By.CSS_SELECTOR, "xg-start .xgplayer-icon-play"))                )                play_btn.click()                time.sleep(1)                self.set_playback_rate_to_2x()            except:                play_btn = WebDriverWait(self.driver, 5).until(                    EC.element_to_be_clickable((By.CSS_SELECTOR, "xg-play .xgplayer-icon-play"))                )                play_btn.click()                time.sleep(1)                self.set_playback_rate_to_2x()            print(f" {title} 播放中...")            if not self.is_video_playing_normally():                return            # 模拟学习            # 增加最大播放时长限制(避免无限循环,可根据视频实际时长调整)            max_play_time = 1800  # 1小时超时            start_time = time.time()            while True:                # 检查是否超时                if time.time() - start_time > max_play_time:                    print(f" {title} 播放超时(超过{max_play_time}秒)")                    break                time.sleep(random.uniform(23))                # 检测是否出现评价弹窗                self.handle_popup()                # 检测是否出现中断学习弹窗                try:                    self.handle_leave_page_tip()                except:                    pass                # 如果有AI选择                self.click_ai_option()                # 判断是什么类型的课程 section or chapter                menu_container = self.driver.find_element(By.CSS_SELECTOR, "div.menu-container")                if ctype == 1:                    chapters = menu_container.find_elements(By.CSS_SELECTOR, "div.chapter-container")                    if "chapter-finish" in chapters[index - 1].get_attribute("class"):                        print(f" {title} 已完成")                        break                else:                    sections = menu_container.find_elements(By.CSS_SELECTOR, "div.chapter-container.chapter-section-item")                    section_list = sections[sid - 1].find_elements(By.CSS_SELECTOR, ".section-container .node-item")                    # 检查是否完成                    if len(section_list[index - 1].find_elements(By.CSS_SELECTOR, "div.status-con.section-finish")) == 1:                        print(f" {title} 已完成")                        break
        except Exception as e:            print(f" {title} 播放失败: {e}")
    def study_course(self, href):        """学习单个课程"""        self.driver.execute_script("window.open(arguments[0]);", href)        time.sleep(5)        # 切换到新标签页操作        self.driver.switch_to.window(self.driver.window_handles[-1])        try:            if self.have_cretificate():                print("该课程已完成!")            else:                self.driver.switch_to.window(self.driver.window_handles[-1])                h1_text = self.driver.find_element(By.TAG_NAME, "h1").text                study_btn = self.wait.until(                    EC.element_to_be_clickable((By.CSS_SELECTOR, "a.course-study-button"))                )                study_btn.click()                print(f" 开始学习课程: {h1_text}")                time.sleep(5)                finished_num, total_num = self.get_progress()                if finished_num >= total_num:                    print(f" 课程 {h1_text} 已完成")                else:                    self.study_chapter()
        except Exception as e:            print(f" 课程异常,跳过: {href}, 错误: {e}")        finally:            self.driver.close()            self.driver.switch_to.window(self.driver.window_handles[0])
if __name__ == "__main__":    bot = AutoCourseBot(USERNAME, PASSWORD)    bot.login()    links = bot.get_all_course_links(course_type)    for t, href in links:        bot.study_course(href)

解析

该脚本为三节课自动学习课程(刷时长)脚本,主要作用包括:

  • 使用 Selenium + Chrome 自动登录学习平台(sntelelearning.b.sanjieke.cn),

  • 进入课程列表页,按配置选择课程类型(通用/专业),

  • 逐个打开课程页,自动进入学习界面,

  • 自动播放视频、倍速设置(2x)、周期性处理弹窗(中断提示/评价弹窗/AI题),

  • 监控章节或小节的完成状态,循环播放直至"已完成"

  • 支持翻页收集全部课程链接并逐一学习,直到完成或发生异常。

配置来源:config.ini(读取 login.username/password 与 course_type.type

主要方法

类:AutoCourseBot

封装全部自动学习流程的核心类。

__init__(self, username, password)

  • 初始化 Chrome WebDriver(静音模式 --mute-audio),

  • 最大化窗口、创建 WebDriverWait

  • 保存登录凭据。

登录与课程入口

  • login(self)
    打开登录页,输入账号密码,点击登录按钮。成功后进入平台首页。

  • get_all_course_links(self, course_type)
    在课程卡片入口中点击对应分类(0:通用/1:专业,代码里用 int(course_type)-1),
    然后在课程列表页遍历所有分页抓取包含 /course/ 的课程链接 (标题, href) 并返回。

学习流程控制

  • study_course(self, href)
    打开单个课程的新标签页 → 若已有证书直接跳过 → 否则点击"开始学习",
    读取完成进度,如未完成则进入 study_chapter() 执行章节学习。
    结束后关闭标签并回到列表页。

  • study_chapter(self)
    定位左侧目录树,分别处理两种结构:

    • 大章节(有小节):逐个展开章节并遍历其中的小节;未完成的小节则点击进入并调用 play_video()

    • 普通章节:直接点击未完成的章节并调用 play_video()
      过程中根据元素 class(如 section-finish / chapter-finish)判断完成状态。

  • play_video(self, title, ctype, index, sid)
    通用的视频播放逻辑:

    • 评价弹窗handle_popup),

    • "学习状态中断"弹窗handle_leave_page_tip),

    • AI题随机选择click_ai_option);

    • 每轮判断章节/小节是否已出现"完成"标记,完成则退出;

    • 设有最长播放时长上限(默认 1800s)以免死循环。

    1. 滚动至视频区域,点击播放(尝试 xg-start 与 xg-play 两种播放按钮);

    2. 设为 2 倍速set_playback_rate_to_2x);

    3. 循环"学习中":定时(2~3s)检查并处理

页面元素与状态工具

  • handle_popup(self)
    处理"评价/得分"等浮层:等待关闭按钮可点 → 点击 → 等待弹窗消失。

  • handle_leave_page_tip(self, wait_time=5)
    处理"学习中断提醒"的弹窗:点击"继续学习",并补一次播放按钮。

  • click_ai_option(self)
    如页面出现"AI题"(div.quiz-main),随机点击一个选项(规避系统检测的拟人化操作)。

  • set_playback_rate_to_2x(self, wait_time=5)
    打开播放速度选择器并选择 cname="2" 的 2x 项。

  • have_cretificate(self)
    在课程左侧信息区 (div.course-left) 内查找 div.certInfo,判断课程是否已有证书(已完成)。

  • is_video_playing_normally(self, timeout=5)
    通过可见的暂停图标(播放中通常显示"暂停"按钮)判断视频是否处于播放状态。

  • get_progress(self)
    从页面读取已完成节数总节数(解析 span.section-finishspan.section-total 文本中的数字)。

运行主流程

if __name__ == "__main__":    bot = AutoCourseBot(USERNAME, PASSWORD)    bot.login()    links = bot.get_all_course_links(course_type)    for t, href in links:        bot.study_course(href)

  1. 登录 → 2) 获取全部课程链接 → 3) 逐门学习,自动播放并处理弹窗/倍速,直至章节完成。



注意

本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。


历史脚本txt文件获取>>
服务器搭建,人工服务咨询>>

没有评论:

发表评论

嘉信国际注册开户攻略|嘉信证券注册流程 I W-8BEN表格填写更新+Wise绑卡教程 内地CRS无忧

之前给大家分享过免疫CRS铁拳 盈透证券IBKR开户全攻略|附港卡入金教程,但是近期盈透US提升了开户门槛,需 之前给大家分享过 免疫CRS铁拳 盈透证券IBKR开户全攻略|附港卡入金教程 , 但是近期盈透US提升了开户门槛,需要海外存量证明,相当于对内地用户关上了大门。 那...