吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2130|回复: 16
收起左侧

[Python 原创] Python 学习通(二)功能实现

[复制链接]
7c丶陪你 发表于 2024-5-30 22:48
接上文,修正Base64是编码,说成加密了{:1_925:}。上文Post登录后获取了Cookie和Userid后,Get课程空间后,获取CourseId、ClazzId、PersonId三个参数,为后面做准备。
1717077093538.jpg
前面的代码环节:用到lxml和fake_useragent库
[Python] 纯文本查看 复制代码
from fake_useragent import UserAgent
import requests as re
from lxml import html

def GetUser_agent():
    user_agent = UserAgent()
    return user_agent.random
def Get_Header():
    Header = {
        'user-agent': GetUser_agent(),
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        'Accept-Encoding': 'gzip, deflate, br',
    }
    return Header
def Get_Courselist(Cookie):
    header = Get_Header()
    header.update({'Host': 'mooc1-1.chaoxing.com'})
    Url = 'https://mooc1-1.chaoxing.com/mooc-ans/visit/courselistdata'
    Data = {
        'courseType': '1',
        'courseFolderId': '0',
        'baseEducation': '0',
        'superstarClass': '',
        'courseFolderSize': '0'
    }
    respones = re.post(url=Url, headers=header, data=Data, cookies=Cookie)
    if respones.status_code == 200:
        Htmltext = html.fromstring(respones.text)
        CourseLists = Htmltext.xpath('//*[@id="courseList"]/li')
        print(f'获取到{str(len(CourseLists))}个课程,分别是:')
        if len(CourseLists) != 0:
            Courseid = []
            Clazzid = []
            Personid = []
            for Count in range(len(CourseLists)):
                CourseTitle = Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/div[@class="course-info"]/h3/a/span/text()')[0]
                CourseTeacher = Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/div[@class="course-info"]/p[@class="line2"]/text()')[0]
                Courseid.append(Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/@courseid')[0])
                Clazzid.append(Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/@clazzid')[0])
                Personid.append(Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/@personid')[0])
                print(
                    f'{str(Count + 1)}、 第{str(Count + 1)}门课程名称:{CourseTitle}  教师:{CourseTeacher}')
            return True, Courseid, Clazzid, Personid
        else:
            print(f'课程数为{len(CourseLists)},无法继续进行下一步操作!')
            return False, "", "", ""
    else:
        print(f'获取课程信息失败,错误代码:{respones.status_code}')
        return False, "", "", ""



获取到CourseId、ClazzId、PersonId三个参数后,Get课程获取章节内容信息并判断当前课程是否有任务点和有多少个小节、获取ENC参数:
1717078975274.jpg

[Python] 纯文本查看 复制代码
def GetNotice(CourseChoose, UserId, Courseid, Clazzid, Personid, Cookie, SaveMP4, SavePPT, FinshPPTTask, FinshVideTask):
    Url = f'https://mooc2-ans.chaoxing.com/mooc2-ans/mycourse/studentcourse?courseid={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&cpi={Personid[int(CourseChoose) - 1]}&ut=s&t={str(Get_13Time())}'
    header = Get_Header()
    header.update({'Host': 'mooc2-ans.chaoxing.com'})
    respones = re.get(url=Url, headers=header, cookies=Cookie)
    if respones.status_code == 200:
        Htmltext = html.fromstring(respones.text)
        FishTask = int(Htmltext.xpath(
            '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_head clearfix"]/h2/span/text()')[0])
        AllTask = int(Htmltext.xpath(
            '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_head clearfix"]/h2/text()')[1].replace("/", ""))
        if FishTask < AllTask:
            ChapterNum = Htmltext.xpath(
                '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_body xs_table"]/div[@class="chapter_td"]/div[@class="chapter_unit"]/div[@class="catalog_level"]/ul/li/div/@id')
            if len(ChapterNum) > 0:
                Enc = Htmltext.xpath('//*[@id="enc"]/@value')[0]
                print(f'获取Enc成功:{Enc}')
                print(f'该课程下有{str(len(ChapterNum))}个小节')



课程ENC获取到了之后,就该到章节的小节了,接着写顺带获取OpenEnc参数(进入小节会进行重定向),用于后面视频任务点的完成:
1717079112988.jpg


[Python] 纯文本查看 复制代码
import re as refind
def get_textafter(text, keyword):
    pattern = refind.compile(f"{refind.escape(keyword)}(.*)")
    match = pattern.search(text)
    if match:
        return match.group(1)  # 返回匹配到的内容
    else:
        return ""

def GetNotice(CourseChoose, UserId, Courseid, Clazzid, Personid, Cookie, SaveMP4, SavePPT, FinshPPTTask, FinshVideTask):
    Url = f'https://mooc2-ans.chaoxing.com/mooc2-ans/mycourse/studentcourse?courseid={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&cpi={Personid[int(CourseChoose) - 1]}&ut=s&t={str(Get_13Time())}'
    header = Get_Header()
    header.update({'Host': 'mooc2-ans.chaoxing.com'})
    respones = re.get(url=Url, headers=header, cookies=Cookie)
    if respones.status_code == 200:
        Htmltext = html.fromstring(respones.text)
        FishTask = int(Htmltext.xpath(
            '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_head clearfix"]/h2/span/text()')[0])
        AllTask = int(Htmltext.xpath(
            '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_head clearfix"]/h2/text()')[1].replace("/", ""))
        if FishTask < AllTask:
            ChapterNum = Htmltext.xpath(
                '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_body xs_table"]/div[@class="chapter_td"]/div[@class="chapter_unit"]/div[@class="catalog_level"]/ul/li/div/@id')
            if len(ChapterNum) > 0:
                Enc = Htmltext.xpath('//*[@id="enc"]/@value')[0]
                print(f'获取Enc成功:{Enc}')
                print(f'该课程下有{str(len(ChapterNum))}个小节')
                for Chaptercount in range(len(ChapterNum)):
                    Url = f'https://mooc1.chaoxing.com/mycourse/transfer?moocId={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&ut=s&refer='+quote(
                        f'https://mooc1.chaoxing.com/mycourse/studentstudy?chapterId={ChapterNum[Chaptercount].replace("cur", "")}&courseId={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&cpi={Personid[int(CourseChoose) - 1]}&enc={Enc}&mooc2=1', encoding='utf-8')
                    header = Get_Header()
                    header.update({'Host': 'mooc1.chaoxing.com'})
                    respones = re.get(url=Url, headers=header,
                                      cookies=Cookie, allow_redirects=False)
                    if respones.status_code == 302:
                        StudyUrl = respones.headers.get('Location')
                        OpenEnc = get_textafter(StudyUrl, 'openc=')


接着判断小节内现在存在未完成的任务点,以及即将实现的PPT和video文件下载(之前的selenium写过,PPT是把图片爬下来后合并pdf,视频链接也是从html文档里获取的):
获取小节PPT和Vide任务点的参数,Video参数:LiveId、Jobid;   PPT参数:Objectid
1717079402261.jpg

这个图片内容也是Html里面的,截图这个内容其实可以用json库去解析的(后面才发现的),可以自行改一下。
上代码:
[Python] 纯文本查看 复制代码
def get_textmiddle(Start, End, Text):
    Pattern = rf"{Start}(.*?){End}"
    result = refind.findall(Pattern, Text)
    if result:
        return result
    else:
        return ""

def GetNotice(CourseChoose, UserId, Courseid, Clazzid, Personid, Cookie, SaveMP4, SavePPT, FinshPPTTask, FinshVideTask):
    Url = f'https://mooc2-ans.chaoxing.com/mooc2-ans/mycourse/studentcourse?courseid={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&cpi={Personid[int(CourseChoose) - 1]}&ut=s&t={str(Get_13Time())}'
    header = Get_Header()
    header.update({'Host': 'mooc2-ans.chaoxing.com'})
    respones = re.get(url=Url, headers=header, cookies=Cookie)
    if respones.status_code == 200:
        Htmltext = html.fromstring(respones.text)
        FishTask = int(Htmltext.xpath(
            '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_head clearfix"]/h2/span/text()')[0])
        AllTask = int(Htmltext.xpath(
            '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_head clearfix"]/h2/text()')[1].replace("/", ""))
        if FishTask < AllTask:
            ChapterNum = Htmltext.xpath(
                '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_body xs_table"]/div[@class="chapter_td"]/div[@class="chapter_unit"]/div[@class="catalog_level"]/ul/li/div/@id')
            if len(ChapterNum) > 0:
                Enc = Htmltext.xpath('//*[@id="enc"]/@value')[0]
                print(f'获取Enc成功:{Enc}')
                print(f'该课程下有{str(len(ChapterNum))}个小节')
                for Chaptercount in range(len(ChapterNum)):
                    Url = f'https://mooc1.chaoxing.com/mycourse/transfer?moocId={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&ut=s&refer='+quote(
                        f'https://mooc1.chaoxing.com/mycourse/studentstudy?chapterId={ChapterNum[Chaptercount].replace("cur", "")}&courseId={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&cpi={Personid[int(CourseChoose) - 1]}&enc={Enc}&mooc2=1', encoding='utf-8')
                    header = Get_Header()
                    header.update({'Host': 'mooc1.chaoxing.com'})
                    respones = re.get(url=Url, headers=header,
                                      cookies=Cookie, allow_redirects=False)
                    if respones.status_code == 302:
                        StudyUrl = respones.headers.get('Location')
                        OpenEnc = get_textafter(StudyUrl, 'openc=')
                        Url = f'https://mooc1.chaoxing.com/mooc-ans/knowledge/cards?clazzid={Clazzid[int(CourseChoose) - 1]}&courseid={Courseid[int(CourseChoose) - 1]}&knowledgeid={ChapterNum[Chaptercount].replace("cur", "")}&num=0&ut=s&cpi={Personid[int(CourseChoose) - 1]}'
                        respones = re.get(
                            url=Url, headers=header, cookies=Cookie)
                        if respones.status_code == 200:
                            TaskNum = int(respones.text.count('"enc":"'))
                            print(f'第{Chaptercount + 1 }个章节的任务数量:{TaskNum}')
                            # 判断是否存在直播视频,存在则不等于0   不存在则等于0
                            LiveId, Objectid,  = '', ''
                            docJosid, docJosToken, docknowledgeid, docClazzid, docCourseId, _dc = '', '', '', '', '', ''
                            videoisPassed, videoOtherInfo, videoJosid, videoobjectid, videoclazzId, videocourseid, videouserid, videofid,  videoduration, videoFaceCaptureEnc, videoknowledgeid = '', '', '', '', '', '', '', '', '', '', ''
                            if int(respones.text.count('","type":"live","')) != 0:
                                LiveId = get_textmiddle(
                                    'liveId":', ',"streamName', respones.text)
                                if LiveId != '':
                                    JobId = f'live-{LiveId}'
                                else:
                                    print('获取LiveId失败!')
                            if int(respones.text.count('","type":".pdf","')) != 0:
                                Objectid = get_textmiddle(
                                    '","objectid":"', '","_jobid":"', respones.text)
                                PPTname = get_textmiddle(
                                    '","name":"', '","mid":"', respones.text)
                            if SaveMP4 == 'True':
                                print('已开启自动保存mp4视频,将开始自动下载视频文件!')
                                print(f'当前章节视频文件数量为:{str(len(LiveId))}个文件')
                                if LiveId != '':
                                    for Livecount in range(len(LiveId)):
                                        Url = 'https://mooc1.chaoxing.com/ananas/live/liveinfo'
                                        querystring = {"liveid": LiveId[Livecount], "userid": UserId, "clazzid": Clazzid[int(
                                            CourseChoose) - 1], "knowledgeid": ChapterNum[Chaptercount].replace("cur", ""), "courseid": Courseid[int(CourseChoose) - 1], "jobid": JobId, "ut": "s"}
                                        respones = re.get(
                                            url=Url, headers=header, cookies=Cookie, params=querystring)
                                        if respones.status_code == 200:
                                            JsonData = respones.json()
                                            LiveTitle = JsonData['temp']['data']['title']
                                            LiveMp4url = JsonData['temp']['data']['mp4Url']
                                            File_size = down_from_url(
                                                LiveMp4url, Livevideo_path + f'\{LiveTitle}.mp4')
                                            if File_size != 0:
                                                print(
                                                    f'{LiveTitle}.mp4 视频下载完成!')
                                            else:
                                                print('章节视频下载异常,未知文件大小!')
                                        else:
                                            print('获取直播回放视频信息失败!')
                                else:
                                    print('当前章节不存在视频内容!')
                            else:
                                print('未开启mp4视频自动保存,将取消自动下载操作!')
                            if SavePPT == 'True':
                                print('已开启自动保存PPT文件,将开始自动下载PPT文件!')
                                print(f'当前章节PPT文件数量为:{str(len(Objectid))}个文件')
                                for pptcount in range(len(Objectid)):
                                    Url = 'https://mooc1.chaoxing.com/ananas/status/' + \
                                        Objectid[pptcount]
                                    header.update(
                                        {'Referer': 'https://mooc1.chaoxing.com/ananas/modules/pdf/index.html'})
                                    querystring = {
                                        "flag": "normal", "_dc": Get_13Time()}
                                    respones = re.get(
                                        url=Url, headers=header, cookies=Cookie, params=querystring)
                                    if respones.status_code == 200:
                                        JsonData = respones.json()
                                        PDFurl = JsonData['pdf']
                                        Filename = JsonData['filename']
                                        File_size = down_from_url(
                                            PDFurl, ppt_path + f'\{Filename}')
                                        if File_size != 0:
                                            print(f'{Filename} PPT下载完成!')
                                        else:
                                            print('章节PPT下载异常,未知文件大小!')
                                    else:
                                        print('获取PPT文件信息失败!')
                            else:
                                print('未开启PPT文件自动保存,将取消自动下载操作!')



接着获取秒完成PPT任务点的参数:jtoken、jobid、knowledgeid、courseid、clazzid、_dc(这个秒完成任务现在还没有校验,后面的秒完成视频有校验也还没解决,暂时不放了,个人感觉是这个参数的问题videoFaceCaptureEnc)
由于PPT任务点都完成了,抓包参数截不到图了。
1717079812663.jpg

[Python] 纯文本查看 复制代码
                            if FinshPPTTask == 'True':  # 秒完成PPT任务点
                                Tasktype = get_textmiddle(
                                    'type":".', '","pagenum', respones.text)
                                if Tasktype != '':
                                    docJosToken = get_textmiddle(
                                        '"jtoken":"', '","property"', respones.text)[0]
                                    docJosid = get_textmiddle(
                                        'jobid":"', '","otherInfo', respones.text)[0]
                                    docknowledgeid = ChapterNum[Chaptercount].replace(
                                        "cur", "")
                                    docCourseId = Courseid[int(
                                        CourseChoose) - 1]
                                    docClazzid = Clazzid[int(CourseChoose) - 1]
                                    _dc = str(Get_13Time())
                                    Url = f'https://mooc1.chaoxing.com/ananas/job/document'
                                    Querystring = {"jobid": docJosid,
                                                   "knowledgeid": docknowledgeid,
                                                   "courseid": docCourseId,
                                                   "clazzid": docClazzid,
                                                   "jtoken": docJosToken,
                                                   "checkMicroTopic": "true",
                                                   "microTopicId": "undefined",
                                                   "_dc": _dc}
                                    respones = re.get(
                                        url=Url, headers=header, cookies=Cookie, params=Querystring, data="")
                                    if respones.status_code == 200:
                                        docJson = respones.json()
                                        docstatus = docJson['status']
                                        if docstatus == True:
                                            print('PPT任务点完成!')
                                        else:
                                            print('PPT任务点完成失败!')
                            sleep(
                                0.5)#延迟提交



视频任务点提交的参数:
1717080171294.jpg


啰嗦了一些,全部代码放出来(试过,现在依然可用,但是秒完成PPT哪里一定要延迟,不然抛个500 给你。

[Python] 纯文本查看 复制代码
import json
import os
from fake_useragent import UserAgent
from time import sleep, time
import re as refind
from urllib.parse import quote
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import requests as re
import random
from lxml import html
import pyperclip
from tqdm import tqdm


def set_clipboard_text(text):
    pyperclip.copy(text)
    print("文本已成功设置到剪贴板!")


def GetUser_agent():
    user_agent = UserAgent()
    return user_agent.random


def get_textafter(text, keyword):
    pattern = refind.compile(f"{refind.escape(keyword)}(.*)")
    match = pattern.search(text)
    if match:
        return match.group(1)  # 返回匹配到的内容
    else:
        return ""


def get_textmiddle(Start, End, Text):
    Pattern = rf"{Start}(.*?){End}"
    result = refind.findall(Pattern, Text)
    if result:
        return result
    else:
        return ""


def Get_13Time():
    return int(time()*1000)


def Get_Header():
    Header = {
        'user-agent': GetUser_agent(),
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        'Accept-Encoding': 'gzip, deflate, br',
    }
    return Header


def EncryptAES(TransferKey, Encryptcontent):
    AesKey = TransferKey.encode('utf-8')
    Iv = TransferKey.encode('utf-8')
    Encrypttext = Encryptcontent.encode('utf-8')
    EncryptMode = AES.MODE_CBC
    Cipher = AES.new(key=AesKey, mode=EncryptMode, IV=Iv)
    EncrData = Cipher.encrypt(pad(Encrypttext, 16, 'pkcs7'))
    Data = base64.b64encode(EncrData).decode('utf-8')
    return Data


def LoginXXT(Username, Userpassword, TransferKey):
    username = EncryptAES(TransferKey, Username)
    userpassword = EncryptAES(TransferKey, Userpassword)
    Url = 'https://passport2.chaoxing.com/fanyalogin'
    header = Get_Header()
    header.update({'Host': 'passport2.chaoxing.com'})
    Data = {
        'fid': '-1',
        'uname': username,
        'password': userpassword,
        'refer': 'http://i.chaoxing.com',
        't': 'true',
        'forbidotherlogin': '0',
        'validate': '',
        'doubleFactorLogin': '0',
        'independentId': '0',
        'independentNameId': '0'
    }
    respones = re.post(url=Url, headers=header, data=Data)
    if respones.status_code == 200:
        JsonData = respones.json()
        Cause = JsonData['status']
        if Cause:
            Cookies = respones.cookies
            Cookie = re.utils.dict_from_cookiejar(Cookies)
            UserId = Cookie['_uid']
            return Cookie, UserId
        else:
            Cause = JsonData['msg2']
            print(f'登录失败,原因:{Cause}')
            return "", ""
    else:
        print(f'登录失败,POST错误代码:{respones.status_code}')
        return "", ""


def Get_Courselist(Cookie):
    header = Get_Header()
    header.update({'Host': 'mooc1-1.chaoxing.com'})
    Url = 'https://mooc1-1.chaoxing.com/mooc-ans/visit/courselistdata'
    Data = {
        'courseType': '1',
        'courseFolderId': '0',
        'baseEducation': '0',
        'superstarClass': '',
        'courseFolderSize': '0'
    }
    respones = re.post(url=Url, headers=header, data=Data, cookies=Cookie)
    if respones.status_code == 200:
        Htmltext = html.fromstring(respones.text)
        CourseLists = Htmltext.xpath('//*[@id="courseList"]/li')
        print(f'获取到{str(len(CourseLists))}个课程,分别是:')
        if len(CourseLists) != 0:
            Courseid = []
            Clazzid = []
            Personid = []
            for Count in range(len(CourseLists)):
                CourseTitle = Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/div[@class="course-info"]/h3/a/span/text()')[0]
                CourseTeacher = Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/div[@class="course-info"]/p[@class="line2"]/text()')[0]
                Courseid.append(Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/@courseid')[0])
                Clazzid.append(Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/@clazzid')[0])
                Personid.append(Htmltext.xpath(
                    f'//*[@id="courseList"]/li[{str(Count + 1)}]/@personid')[0])
                print(
                    f'{str(Count + 1)}、 第{str(Count + 1)}门课程名称:{CourseTitle}  教师:{CourseTeacher}')
            return True, Courseid, Clazzid, Personid
        else:
            print(f'课程数为{len(CourseLists)},无法继续进行下一步操作!')
            return False, "", "", ""
    else:
        print(f'获取课程信息失败,错误代码:{respones.status_code}')
        return False, "", "", ""


def down_from_url(url, dst):
    # 设置stream=True参数读取大文件
    response = re.get(url, stream=True)
    # 通过header的content-length属性可以获取文件的总容量
    file_size = int(response.headers['content-length'])
    if os.path.exists(dst):
        # 获取本地已经下载的部分文件的容量,方便继续下载,如果不存在就从头开始下载。
        first_byte = os.path.getsize(dst)
    else:
        first_byte = 0
    # 如果大于或者等于则表示已经下载完成,否则继续
    if first_byte >= file_size:
        return file_size
    header = {"Range": f"bytes={first_byte}-{file_size}"}

    pbar = tqdm(total=file_size, initial=first_byte,
                unit='B', unit_scale=True, desc=dst)
    req = re.get(url, headers=header, stream=True)
    with open(dst, 'ab') as f:
        # 每次读取一个1024个字节
        for chunk in req.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)
                pbar.update(1024)
    pbar.close()
    return file_size


def videoEncode_enc(clazzid, userid, jobid, objectId, playtime, duration):
    import hashlib
    data = "[{0}][{1}][{2}][{3}][{4}][{5}][{6}][0_{7}]".format(
        clazzid, userid, jobid, objectId, playtime*1000, "d_yHJ!$pdA~5", duration*1000, duration)
    # [clazzid][userid][jobid][objectId][playtime*1000]["d_yHJ!$pdA~5"][duration*1000][0_duration]
    return hashlib.md5(data.encode()).hexdigest()


def UpVideoAsk(videoclazzId, videouserid, videoJobid, videoobjectid, playingTime, videoduration,videoOtherInfo,videocourseid,isdrag,videoFaceCaptureEnc,Url,VideoHeader,Cookie,Askupcount,upcount):
    videoEnc = videoEncode_enc(
        videoclazzId, videouserid, videoJobid, videoobjectid, playingTime, videoduration)
    Querystring = {"clazzId": videoclazzId,
                   "playingTime": playingTime,
                   "duration": videoduration,
                   "clipTime": "0_" + str(videoduration),
                   "objectId": videoobjectid,
                   "otherInfo": videoOtherInfo,
                   "courseId": videocourseid,
                   "jobid": videoJobid,
                   "userid": videouserid,
                   "isdrag": isdrag,
                   "view": "pc",
                   "enc": videoEnc,
                   "rt": "0.9",
                   "videoFaceCaptureEnc": videoFaceCaptureEnc,
                   "dtype": "Video",
                   "_t": str(Get_13Time())}
    print(Querystring)
    response = re.request(
        "GET", Url, headers=VideoHeader, params=Querystring, cookies=Cookie)
    if response.status_code == 200:
        Askstate = get_textmiddle(
            '"isPassed":', ',"videoTimeLimit"', response.text)
        if Askstate == True:
            print(
                '完成视频任务点!')
        else:
            print(f'已提交视频任务{Askupcount + 1}次,预计共需提交{upcount}次')
            sleep(
                random.randint(1, 3))
    else:
        print(
            f'请求任务失败{response.status_code}')
        sleep(
            random.randint(1, 3))


def GetNotice(CourseChoose, UserId, Courseid, Clazzid, Personid, Cookie, SaveMP4, SavePPT, FinshPPTTask, FinshVideTask):
    Url = f'https://mooc2-ans.chaoxing.com/mooc2-ans/mycourse/studentcourse?courseid={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&cpi={Personid[int(CourseChoose) - 1]}&ut=s&t={str(Get_13Time())}'
    header = Get_Header()
    header.update({'Host': 'mooc2-ans.chaoxing.com'})
    respones = re.get(url=Url, headers=header, cookies=Cookie)
    if respones.status_code == 200:
        Htmltext = html.fromstring(respones.text)
        FishTask = int(Htmltext.xpath(
            '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_head clearfix"]/h2/span/text()')[0])
        AllTask = int(Htmltext.xpath(
            '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_head clearfix"]/h2/text()')[1].replace("/", ""))
        if FishTask < AllTask:
            ChapterNum = Htmltext.xpath(
                '//*[@id="fanyaChapter"]/div[@class="fanyaChapterWhite"]/div[@class="chapter_body xs_table"]/div[@class="chapter_td"]/div[@class="chapter_unit"]/div[@class="catalog_level"]/ul/li/div/@id')
            if len(ChapterNum) > 0:
                Enc = Htmltext.xpath('//*[@id="enc"]/@value')[0]
                print(f'获取Enc成功:{Enc}')
                print(f'该课程下有{str(len(ChapterNum))}个小节')
                for Chaptercount in range(len(ChapterNum)):
                    Url = f'https://mooc1.chaoxing.com/mycourse/transfer?moocId={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&ut=s&refer='+quote(
                        f'https://mooc1.chaoxing.com/mycourse/studentstudy?chapterId={ChapterNum[Chaptercount].replace("cur", "")}&courseId={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&cpi={Personid[int(CourseChoose) - 1]}&enc={Enc}&mooc2=1', encoding='utf-8')
                    header = Get_Header()
                    header.update({'Host': 'mooc1.chaoxing.com'})
                    respones = re.get(url=Url, headers=header,
                                      cookies=Cookie, allow_redirects=False)
                    if respones.status_code == 302:
                        StudyUrl = respones.headers.get('Location')
                        OpenEnc = get_textafter(StudyUrl, 'openc=')
                        Url = f'https://mooc1.chaoxing.com/mooc-ans/knowledge/cards?clazzid={Clazzid[int(CourseChoose) - 1]}&courseid={Courseid[int(CourseChoose) - 1]}&knowledgeid={ChapterNum[Chaptercount].replace("cur", "")}&num=0&ut=s&cpi={Personid[int(CourseChoose) - 1]}'
                        respones = re.get(
                            url=Url, headers=header, cookies=Cookie)
                        if respones.status_code == 200:
                            TaskNum = int(respones.text.count('"enc":"'))
                            print(f'第{Chaptercount + 1 }个章节的任务数量:{TaskNum}')
                            # 判断是否存在直播视频,存在则不等于0   不存在则等于0
                            LiveId, Objectid,  = '', ''
                            docJosid, docJosToken, docknowledgeid, docClazzid, docCourseId, _dc = '', '', '', '', '', ''
                            videoisPassed, videoOtherInfo, videoJosid, videoobjectid, videoclazzId, videocourseid, videouserid, videofid,  videoduration, videoFaceCaptureEnc, videoknowledgeid = '', '', '', '', '', '', '', '', '', '', ''
                            if int(respones.text.count('","type":"live","')) != 0:
                                LiveId = get_textmiddle(
                                    'liveId":', ',"streamName', respones.text)
                                if LiveId != '':
                                    JobId = f'live-{LiveId}'
                                else:
                                    print('获取LiveId失败!')
                            if int(respones.text.count('","type":".pdf","')) != 0:
                                Objectid = get_textmiddle(
                                    '","objectid":"', '","_jobid":"', respones.text)
                                PPTname = get_textmiddle(
                                    '","name":"', '","mid":"', respones.text)
                            if SaveMP4 == 'True':
                                print('已开启自动保存mp4视频,将开始自动下载视频文件!')
                                print(f'当前章节视频文件数量为:{str(len(LiveId))}个文件')
                                if LiveId != '':
                                    for Livecount in range(len(LiveId)):
                                        Url = 'https://mooc1.chaoxing.com/ananas/live/liveinfo'
                                        querystring = {"liveid": LiveId[Livecount], "userid": UserId, "clazzid": Clazzid[int(
                                            CourseChoose) - 1], "knowledgeid": ChapterNum[Chaptercount].replace("cur", ""), "courseid": Courseid[int(CourseChoose) - 1], "jobid": JobId, "ut": "s"}
                                        respones = re.get(
                                            url=Url, headers=header, cookies=Cookie, params=querystring)
                                        if respones.status_code == 200:
                                            JsonData = respones.json()
                                            LiveTitle = JsonData['temp']['data']['title']
                                            LiveMp4url = JsonData['temp']['data']['mp4Url']
                                            File_size = down_from_url(
                                                LiveMp4url, Livevideo_path + f'\{LiveTitle}.mp4')
                                            if File_size != 0:
                                                print(
                                                    f'{LiveTitle}.mp4 视频下载完成!')
                                            else:
                                                print('章节视频下载异常,未知文件大小!')
                                        else:
                                            print('获取直播回放视频信息失败!')
                                else:
                                    print('当前章节不存在视频内容!')
                            else:
                                print('未开启mp4视频自动保存,将取消自动下载操作!')
                            if SavePPT == 'True':
                                print('已开启自动保存PPT文件,将开始自动下载PPT文件!')
                                print(f'当前章节PPT文件数量为:{str(len(Objectid))}个文件')
                                for pptcount in range(len(Objectid)):
                                    Url = 'https://mooc1.chaoxing.com/ananas/status/' + \
                                        Objectid[pptcount]
                                    header.update(
                                        {'Referer': 'https://mooc1.chaoxing.com/ananas/modules/pdf/index.html'})
                                    querystring = {
                                        "flag": "normal", "_dc": Get_13Time()}
                                    respones = re.get(
                                        url=Url, headers=header, cookies=Cookie, params=querystring)
                                    if respones.status_code == 200:
                                        JsonData = respones.json()
                                        PDFurl = JsonData['pdf']
                                        Filename = JsonData['filename']
                                        File_size = down_from_url(
                                            PDFurl, ppt_path + f'\{Filename}')
                                        if File_size != 0:
                                            print(f'{Filename} PPT下载完成!')
                                        else:
                                            print('章节PPT下载异常,未知文件大小!')
                                    else:
                                        print('获取PPT文件信息失败!')
                            else:
                                print('未开启PPT文件自动保存,将取消自动下载操作!')
                            if FinshPPTTask == 'True':  # 秒完成PPT任务点
                                Tasktype = get_textmiddle(
                                    'type":".', '","pagenum', respones.text)
                                if Tasktype != '':
                                    docJosToken = get_textmiddle(
                                        '"jtoken":"', '","property"', respones.text)[0]
                                    docJosid = get_textmiddle(
                                        'jobid":"', '","otherInfo', respones.text)[0]
                                    docknowledgeid = ChapterNum[Chaptercount].replace(
                                        "cur", "")
                                    docCourseId = Courseid[int(
                                        CourseChoose) - 1]
                                    docClazzid = Clazzid[int(CourseChoose) - 1]
                                    _dc = str(Get_13Time())
                                    Url = f'https://mooc1.chaoxing.com/ananas/job/document'
                                    Querystring = {"jobid": docJosid,
                                                   "knowledgeid": docknowledgeid,
                                                   "courseid": docCourseId,
                                                   "clazzid": docClazzid,
                                                   "jtoken": docJosToken,
                                                   "checkMicroTopic": "true",
                                                   "microTopicId": "undefined",
                                                   "_dc": _dc}
                                    respones = re.get(
                                        url=Url, headers=header, cookies=Cookie, params=Querystring, data="")
                                    if respones.status_code == 200:
                                        docJson = respones.json()
                                        docstatus = docJson['status']
                                        if docstatus == True:
                                            print('PPT任务点完成!')
                                        else:
                                            print('PPT任务点完成失败!')
                            sleep(
                                0.5)#延迟提交
                            if FinshVideTask == 'True':  # 完成视频观看任务点
                                Url = 'https://mooc1.chaoxing.com/mooc-ans/knowledge/cards'
                                Querystring = {"clazzid": Clazzid[int(CourseChoose) - 1],
                                               "courseid": Courseid[int(CourseChoose) - 1],
                                               "knowledgeid": ChapterNum[Chaptercount].replace("cur", ""),
                                               "num": "0",
                                               "ut": "s",
                                               "cpi": Personid[int(CourseChoose) - 1],
                                               "v": "20160407-3",
                                               "mooc2": "1"}
                                Videoheader = Get_Header()
                                Videoheader.update(
                                    {'Referer': f'https://mooc1.chaoxing.com/mycourse/studentstudy?chapterId={ChapterNum[Chaptercount].replace("cur", "")}&courseId={Courseid[int(CourseChoose) - 1]}&clazzid={Clazzid[int(CourseChoose) - 1]}&cpi={Personid[int(CourseChoose) - 1]}&enc={Enc}&mooc2=1&openc={OpenEnc}'})
                                Videoheader.update(
                                    {'Upgrade-Insecure-Requests': '1'})
                                responses = re.request(
                                    "GET", Url, data="", headers=Videoheader, params=Querystring, cookies=Cookie)
                                if responses.status_code == 200:
                                    AskInfo = get_textmiddle(
                                        'mArg = ', ',"isErya":0,"ut":"s"};', responses.text)[0] + ',"isErya":0,"ut":"s"}'
                                    JsonTaskData = json.loads(AskInfo)
                                    for Taskcount in range(len(JsonTaskData['attachments'])):
                                        Tasktype = JsonTaskData['attachments'][Taskcount]['type']
                                        if Tasktype == 'video':
                                            try:
                                                videoisPassed = JsonTaskData['attachments'][Taskcount]['isPassed']
                                                if videoisPassed == True:
                                                    print(
                                                        f'视频任务点完成状态:{videoisPassed}')
                                                elif videoisPassed == False:
                                                    raise Exception(
                                                        '当前任务未开始观看!')
                                            except:
                                                videoJobid = JsonTaskData['attachments'][Taskcount]['property']['_jobid']
                                                videoobjectid = JsonTaskData['attachments'][Taskcount]['property']['objectid']
                                                videoclazzId = JsonTaskData['defaults']['clazzId']
                                                videoknowledgeid = JsonTaskData['defaults']['knowledgeid']
                                                videocourseid = JsonTaskData['defaults']['courseid']
                                                videoFaceCaptureEnc = JsonTaskData['attachments'][
                                                    Taskcount]['videoFaceCaptureEnc']
                                                videoOtherInfo = JsonTaskData['attachments'][Taskcount]['otherInfo'].replace(
                                                    f"&courseId={videocourseid}", "")
                                                videouserid = UserId
                                                videofid = JsonTaskData['defaults']['fid']
                                                reportUrl = JsonTaskData['defaults']['reportUrl']
                                                Url = 'https://mooc1.chaoxing.com/mooc-ans/courseapi/getvideohotdata'
                                                Querystring = {"_dc": str(Get_13Time()),
                                                               "clazzid": videoclazzId,
                                                               "knowledgeid": videoknowledgeid,
                                                               "objectid": videoobjectid,
                                                               "courseid": videocourseid,
                                                               "cpi": Personid[int(CourseChoose) - 1],
                                                               "ut": "s"}
                                                VideoHeader = header
                                                VideoHeader.update(
                                                    {'Referer': 'https://mooc1.chaoxing.com/ananas/modules/video/index.html'})
                                                response = re.request(
                                                    "GET", Url, cookies=Cookie, headers=VideoHeader, params=Querystring)
                                                if response.status_code == 200:
                                                    JsonData = json.loads(
                                                        response.text)
                                                    restatus = JsonData['status']
                                                    if restatus == True:
                                                        
                                                        Url = r'https://mooc1.chaoxing.com/ananas/status/' + videoobjectid
                                                        Querystring = {"k": videofid,
                                                                       "flag": "normal",
                                                                       "_dc": str(Get_13Time())}
                                                        respones = re.get(
                                                            url=Url, headers=VideoHeader, cookies=Cookie, params=Querystring, data="")
                                                        if respones.status_code == 200:
                                                            JsonData = respones.json()
                                                            videoduration = JsonData['duration']
                                                            upcount = round(videoduration / 59)
                                                            countduration = videoduration
                                                            videodtoken = JsonData['dtoken']
                                                            Url = reportUrl + r'/' + videodtoken
                                                            Askupcount = 0
                                                            while True:
                                                                if Askupcount == 0:
                                                                    playingTime = 0
                                                                    isdrag = 3
                                                                    Askupcount += 1
                                                                    UpVideoAsk(videoclazzId, videouserid, videoJobid, videoobjectid, playingTime, videoduration,videoOtherInfo,videocourseid,isdrag,videoFaceCaptureEnc,Url,VideoHeader,Cookie,Askupcount,upcount)
                                                                else:
                                                                    Countnum = countduration - playingTime
                                                                    if Countnum >= 59:
                                                                        playingTime += 59
                                                                        isdrag = 4
                                                                        Askupcount += 1
                                                                        UpVideoAsk(videoclazzId, videouserid, videoJobid, videoobjectid, playingTime, videoduration,videoOtherInfo,videocourseid,isdrag,videoFaceCaptureEnc,Url,VideoHeader,Cookie,Askupcount,upcount)
                                                                    else:
                                                                        playingTime += Countnum
                                                                        isdrag = 4
                                                                        Askupcount += 1
                                                                        UpVideoAsk(videoclazzId, videouserid, videoJobid, videoobjectid, playingTime, videoduration,videoOtherInfo,videocourseid,isdrag,videoFaceCaptureEnc,Url,VideoHeader,Cookie,Askupcount,upcount)
                                                                        break
                                                        else:
                                                            print('获取提交次数失败!')
                                                    else:
                                                        print('请求获取提交次数失败!')

                            if FinshBroadcastTask == 'True':  # 完成直播回放观看
                                pass

                        else:
                            print('学习界面信息获取失败!')
                            return False
                    else:
                        print('获取OpenEnc失败!')
                        return False
                return True
            else:
                print('该课程下无章节内容!')
                return False
        elif FishTask == AllTask:
            print('任务点已全部完成!')
            return False
        elif FishTask > AllTask:
            print('未知错误!')
            return False
    else:
        print('获取课程章节信息失败!')
        return False


def Main(Username, Userpassword, TransferKey, SavePPT, SaveMP4, FinshPPTTask, FinshVideTask):
    Cookie, UserId = LoginXXT(Username, Userpassword, TransferKey)
    if Cookie != '' and UserId != '':
        print(f'获取UserId成功:{UserId}')
        print('登录成功,欢迎使用!正在获取课程内容,请稍等!(附随机延迟)')
        sleep(random.randint(1, 5))
        Boot, Courseid, Clazzid, Personid = Get_Courselist(Cookie)
        print(Personid)
        if Boot == True:
            CourseChoose = input('请选择您需要操作的课程:')
            Boot = GetNotice(
                CourseChoose, UserId, Courseid, Clazzid, Personid, Cookie, SaveMP4, SavePPT, FinshPPTTask, FinshVideTask)
            if Boot == True:
                print('已完成该课程全部任务!')
            else:
                print('获取课程信息失败!')
        else:
            print('获取课程内容失败!')


if __name__ == '__main__':
    global Livevideo_path, ppt_path
    File_path = os.path.join(os.path.dirname(__file__), 'Config.json')
    with open(File_path, 'r', encoding='utf8') as f:
        data = json.load(f)
    f.close()
    Livevideo_path = os.path.dirname(__file__) + '\Livevideo'
    ppt_path = os.path.dirname(__file__) + '\PPT'
    for Info in data['UserInfo']:
        Username = Info['Username']
        Userpassword = Info['Userpassword']
        SavePPT = Info['SavePPT']
        SaveMP4 = Info['SaveMP4']
        FinshPPTTask = Info['FinshPPTTask']
        FinshVideTask = Info['FinshVideTask']
        FinshBroadcastTask = Info['FinshBroadcastTask']
        if Username != '' and Userpassword != '':
            TransferKey = Info['TransferKey']
            if TransferKey != '':
                Main(Username, Userpassword, TransferKey, SavePPT, SaveMP4,
                     FinshPPTTask, FinshVideTask)
            else:
                print('加密密钥为空,无法登录!')
        else:
            print('账号或密码为空,无法登录!')



最后,有那个大佬把秒完成视频哪里解决了麻烦告知一下,谢谢!这个就停了,不再更新了,去年本来还有一个查互评的,硬盘坏了,懂的....

免费评分

参与人数 4吾爱币 +8 热心值 +4 收起 理由
junjia215 + 1 + 1 谢谢@Thanks!
wushaominkk + 5 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Bob5230 + 1 + 1 热心回复!
aigc + 1 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

k452b 发表于 2024-5-31 00:35
我也搞了个学堂在线的, 不过直接是写在油猴了,弄了个网页的按钮。
iFinD 发表于 2024-5-30 23:14
编程天下 发表于 2024-5-30 23:37
huliuwa 发表于 2024-5-31 07:45
牛蛙,感谢分享
DLxiaolei 发表于 2024-5-31 08:19
感谢大神,非常详细
Lengxiy 发表于 2024-5-31 09:07
很不错,正好用得到
余律师 发表于 2024-5-31 09:36
谢谢您的分享!
clever18 发表于 2024-5-31 11:03
有现成的吗
onepiecelibing 发表于 2024-5-31 16:33

谢谢您的分享!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 19:14

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表