第一步:登录模拟
登录是第一个拦路虎。通过抓包发现,登录接口是/login/login.ajaxLogin.do,返回state: S表示成功。但直接调用API需要处理动态的hyperEspCode参数,这个参数是由前端JavaScript生成的,逆向成本高。于是我选择使用Selenium模拟真实用户登录,这样还能自动处理“继续登录”按钮等异常情况。
# 核心登录代码(简化)username_input = wait.until(EC.presence_of_element_located((By.ID, "loginName")))password_input = driver.find_element(By.ID, "password")...login_button.click()
登录成功后,通过/os/html/desktopItem/desktopItem.todayTaskContextJson.do获取用户信息,动态更新CURRENT_APP_ID等参数,这样即使平台调整应用ID,程序也能自适应。
第二步:获取课程列表
课程列表接口返回的是HTML而非JSON,需要用BeautifulSoup解析。我从中提取了每个课程的ID、标题,并根据class中包含innercan还是innerpass判断是否需要学习。
soup = BeautifulSoup(html, 'html.parser')ul = soup.find('ul', class_='track-dialog-inner-list')for li in ul.find_all('li', class_=lambda c: c and ('innercan' in c or 'innerpass' in c)): a = li.find('a', class_='goCourseByStudy') course_id = a['id'] need_study = 'innercan' in li['class']

同时,我在返回中增加了all_finished标志,通过检测页面中是否出现“您已完成所有阶段的学习”文本来判断整体学习是否完成。
第三步:进入课程播放页
每个课程都有一个“进入学习”的URL,但实际播放地址需要二次请求。通过/els/html/courseInfo/courseinfo.checkMsUrl.do接口,传入courseId和基础URL,就能获得最终的播放地址。
play_url = api_utils.get_course_play_url(course_id, base_enter_url)driver.get(play_url)
在播放页中,我发现真正的视频信息藏在一个iframe里,其src包含了关键的sourceId和providerCorpCode,这两个参数是后续所有请求的基础。
iframe = driver.find_element(By.ID, "aliPlayerFrame")src = iframe.get_attribute("src")# 解析出 sourceId 和 providerCorpCode
第四步:获取章节资源
每个课程可能有多个章节,每个章节可能包含多个视频。通过/tbc-rms/course/showCourseChapter接口,传入sourceId和providerCorpCode,就能获得完整的章节和资源列表。
items = api_utils.get_course_chapters(source_id, provider_corp_code)# 每个item包含 chapterId, resourceId, timeToFinish(秒), minStudyTime等
第五步:创建学习记录
对于未学习的章节,getStudyRecordList接口返回的记录列表为空。此时需要先发送一次updateCourseRecord请求,且recordId设为null,currentPosition设为0,让服务器生成学习记录。等待2秒后再次获取记录列表,就能拿到真实的recordId。
# 创建记录success = api_utils.report_progress(record_id=None, ...)time.sleep(2)# 重新获取记录列表records = api_utils.get_study_record_list(...)
第六步:循环上报进度
有了recordId后,就可以循环调用updateCourseRecord接口,每次增加currentPosition(步长和间隔可在GUI中动态调整),直到达到总时长timeToFinish。这样模拟了真实观看视频的过程,不会被服务器检测为异常。
while current < total: current = min(current + step, total) api_utils.report_progress(record_id=record_id, current_position=current, ...) time.sleep(interval)
第七步:自动评价
学习完所有章节后,还需要对课程进行评价。通过两个接口完成:
第八步:进度显示与完成判断
登录后自动刷新进度,显示总课程数、已完成数及百分比。点击“刷新进度”可手动更新。最重要的是,当服务器返回“您已完成所有阶段的学习”时,进度直接跳到100%,并停止学习。