• 基于浙江线上大学视频秒过分析


    当代苦逼大学生,人在家中坐,课从天上来.没办法,想偷懒,于是就对目前在上的网课平台进行了分析

    嘿嘿 先来张效果图:

    好勒,废话不多说,上主题

    其实我们在看网课的时候,本地的网页会通过ajax请求定时的发送当前所观看的视频秒数到服务器上,并记载,所以通过拉取本地的进度条是达不到秒过的效果的

    额,因为已经刷好了,不知道为什么就没发送了,不过这张图也能表达意思,通过上面的参数可以发现,有courseId,chapterId,一个固定的server,正确的发送参数还应该有playtime,percent,最后一个是变化的time,
    time后面的值看起来像一个时间

    好了,既然知道发送ajax请求需要的是这些参数,那我们就来找找这些参数从哪里获得的,service好说,固定的参数,我们不用管它,courseId和chapterId顾名思义,
    像这种有代表性的参数,不是在查看该课程的首页出现,就是在观看具体某一章节出现,playtime是当前播放了多少时间,percent是根据当前播放的时间除以总时长的百分比,播放的单位是s,最后一个加密的time就显得尤为重要了,我们要找到这个time是怎么实现的,很明显
    是通过js来生成的

    因为提交的域名是https://www.zjooc.cn/ajax 后面加的就是上面说的4个参数,且是get的请求
    通过对url的全局搜索

    找到了对应time参数的js文件,可以看出time的关键点是一个叫做createAjaxTimestamp的函数调用,通过搜索,成功找到对应的加密函数

    作者的js水平有限,就用python的来模拟js环境来执行对应的函数
    通过这里,已经能实现单个视频

    那么如何实现批量化秒过呢,既然一个章节的视频对应一个chapterId,那肯定可以通过对应的方法拿到所有的chapterId

    通过在课程的首页进行刷新,捕获到一个ajax的数据包,对应的请求和响应数据如下

    • 请求数据

    • 响应数据

    请求的参数也比较单一,courseId是根据不同的课程变化的,还有一个time的参数就是上文中写到过的

    这里的响应体就非常有价值了,里面对应了每个视频的chapterId,名字,还有最重要的duration,在上面的介绍中肯定有小伙伴有疑问,我可以任意编造playtime,但是时长我不知道呀,怎么编写对应的percent

    嘿嘿,这时duration数据就非常重要啦,后文中我们可以通过duration来填写playtime达到秒过的效果

    因为里面的数据太多了,这里我就通过画图来描述一级菜单,二级菜单,三级菜单的结构图

    先给一张实物图

    额,手画的草图

    响应体的数据大致就是这样的菜单结构,再通过实现对应的逻辑,就可以拿到每一个视频的chapterId和duration

    这里就献上本人low逼的代码吧

    # -*- coding: utf-8 -*-
    # @Author : __will__
    
    import time
    
    import requests
    import execjs
    
    
    class Zjooc(object):
    
        node = execjs.get()
        url = 'https://www.zjooc.cn/ajax'
        get_video_playing_server = '/learningmonitor/api/learning/monitor/videoPlaying'
        get_pdf_finished_server = '/learningmonitor/api/learning/monitor/finishTextChapter'
        get_student_course_server = '/jxxt/api/course/courseStudent/getStudentCourseChapters'
    
        def __init__(self, course_id,cookie):
            self.headers = {
                'User-Agent': 'Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14',
                'Cookie': cookie
            }
            self.course_id = course_id
    
    
        def get_student_course_info(self):
            ctx = self.node.compile(open('zjooc.js').read())
            ajax_time = ctx.eval('createTimesatamp(32)')
            ts = ajax_time + str(int(time.time()) * 1000)
            student_params = {
                'time': ts,
                'service': self.get_student_course_server,
                'params[pageNo]': '1',
                'params[courseId]': self.course_id,
                'params[urlNeed]': '0'
            }
            course_info = requests.get(self.url,params=student_params,headers=self.headers).json()
            return course_info
    
        def parse_course_info(self):
            data = self.get_student_course_info()
            single_course_list = []
            course_list = data['data']
            # 获取每个章节
            for item in course_list:
                # 获取每个小章节的事件节点
                chapter_node = item['children']
                for i in chapter_node:
                    children_node = i['children']
                    for child in children_node:
                        course_dict = {}
                        course_dict['id'] = child['id']
                        course_dict['name'] = child['name']
                        course_dict['resourceType'] = child['resourceType']
                        if child['resourceType'] == 1:
                            course_dict['vedioTimeLength'] = child['vedioTimeLength']
                        single_course_list.append(course_dict)
    
    
            return single_course_list
    
        def run(self):
            context = self.node.compile(open('zjooc.js').read())
            single_course_list = self.parse_course_info()
            for item in single_course_list:
                ajax_time = context.eval('createTimesatamp(32)')
                ts = ajax_time + str(int(time.time())+ 600) + '000'
                if item['resourceType'] == 1:
                    video_params = {
                    'time': ts,
                    'service': self.get_video_playing_server,
                    'params[chapterId]': item['id'],
                    'params[courseId]': self.course_id,
                    'params[playTime]': item['vedioTimeLength'],
                    'params[percent]': '100'
                    }
                    result = requests.get(self.url,params=video_params,headers=self.headers).json()
                    if result['resultCode'] == 0:
                        print(item['name']+'的视频''------秒过成功')
                    else:
                        print(item['name']+'的视频''------秒过失败')
                else:
                    pdf_params = {
                        'time': ts,
                        'service': self.get_pdf_finished_server,
                        'params[chapterId]': item['id'],
                        'params[courseId]': self.course_id,
                    }
                    result = requests.get(self.url, params=pdf_params, headers=self.headers).json()
                    if result['resultCode'] == 0:
                        print(item['name'] +'的pdf' '------秒过成功')
                    else:
                        print(item['name'] +'的pdf' '------秒过失败')
    
    

    大功告成,最后,上述内容只供学习使用,

  • 相关阅读:
    Linux 管道命令(pipe)
    SQLITE入门逐步讲解SQLITE命令行(二)
    用flash上传多个图片、文件的插件TinyBrowser
    PHP的时区问题GMT8
    解决Apache+PHP服务器提示HTTP 500问题
    SQLITE入门逐步讲解SQLITE命令行(四)
    SQLITE入门逐步讲解SQLITE命令行(五)
    linux tar命令使用范例
    SQLITE入门逐步讲解SQLITE命令行(六)
    Tinymce配置智能的Url
  • 原文地址:https://www.cnblogs.com/williamweson/p/12811721.html
Copyright © 2020-2023  润新知