前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python实战-让在职教育类网站的视频全自动播放

Python实战-让在职教育类网站的视频全自动播放

作者头像
somenzz
发布2020-11-25 10:29:06
1.4K0
发布2020-11-25 10:29:06
举报
文章被收录于专栏:Python七号Python七号

阅读本文需要 5.8 分钟。

时间是公平的,因为每个人的一分钟都是 60 秒;时间又是最不公平的,有人一年的收获顶得上别人十年,这取决于如何利用时间。

成年人的世界,一个字忙,忙得没有时间学习,没有时间健身,没有时间陪家人。其实解决忙这个问题很简单,那就是做减法,减去不必要的应酬、会议,减去不重要的事项,只保留那些重要的,有意义的,所谓永远只做那些重要不紧急的事情。另外节省时间的方法就是借助工具,提高效率。

这些年流行网络课程学习,在职人士尤其如此,有些课程,需要你花钱去用心学;有些课程,别人花了钱你也得学,什么学习积分,学习报表,积累学时等等,还与绩效、职称挂勾。后者大概率不许快进,这样就要花费时间点击播放,再点击再播放,直到看完完成任务。

如果你知道 Python,其实应对一些不得不看的在线课程,非常简单,可以写代码让它全部自动播放,最近就有个朋友让我帮助开发一个可以自动播放网课的工具,来缓解大量线上学习的压力,感觉这一过程应该有不少人需要,特些记录下来,可以帮助有同样需求的朋友。

如果对技术无感,想直接使用现成的工具,请移步:https://t.zsxq.com/7yzF23R 阅读原文可直接访问链接。

如果手撸代码,请继续阅读。

示例网址:http://jxjy.jxt.zj.gov.cn/iext/zgProject/index.jsp,请自行注册账号。网站风格如下:

第一步:登陆。

登陆前,先打开开发者工具(Chrome浏览器的快捷键是F12),然后登陆,查看接口返回数据:

点击这个login的接口,查看详细信息如下:

这点重点记录四个信息:

1、请求的接口地址,即图中的 Request URL 及请求的方法。 2、Cookie 中的信息,这里是 JSESSIONID。 3、传递的参数和返回的接口数据。

根据这些信息,使用 requests 库自带的 session 功能很容易写出登陆的代码,并且可以获取此处的 JSESSIONID,可以大致推测出后续的请求也是使用该 JSESSIONID。

代码语言:javascript
复制
import requests
session = requests.Session()
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
                  '(KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest',
}

def login():
    params = {
        'account': your_username,
        'password': your_password,
    }
    r = session.post("http://jxjy.jxt.zj.gov.cn/iext/zg/webfront/user/loginByAccount.do", params=params,headers = headers)
    jsessionid = session.cookies.get('JSESSIONID')
    return jsessionid

第二步:获取信息。

登陆后, 获取到了 JSESSIONID。接下来,我们看到登陆后,还有一个接口,返回的是视频课程的列表,此接口使用的 JSESSIONID 和登陆是一致的,可以推断出 JSESSIONID 是后续接口请求的凭证,不过这个凭证是记录在 cookie 中的,requests 的 session 功能可以自带 cookie 请求,因此不需要单独处理。这里就是着重要分析的地方:

我们可以从这里获取课程的名称,持续时间,学习进度,编号等信息,有了这些信息,就可以为后续接口的请求提供参数了。方法有很多,正则表达式,BeautifulSoup,Selenium 喜欢哪个就用哪个吧,我这里使用 BeautifulSoup。参考代码如下:

代码语言:javascript
复制
def get_play_list_info():
    video_list = []
    for i in range(4):
        params = {
            'pageNum': i + 1,
            'url': '/zgProject/front/learncenter/list'
        }
        r = session.get("http://jxjy.jxt.zj.gov.cn/iext/zg/webfront/DatumFrontController/infolist.do", params, headers )
        soup = BeautifulSoup(r, "html.parser")
        for el in soup.findAll("div", {'onclick': re.compile("skip(.*)")}):
            video_name = el.find("div", {'class': 'clearfix'}).get('title')
            function_name = el.get('onclick')
            video_id = function_name.split(",")[0].split('(')[1].strip()
            progress = el.find("span", {'class': 'baif'}).get_text()
            durationTime = el.find("span", {'class': 'durationTime'}).get_text()
            if progress != '已完成':
                video_list.append({'video_name': video_name, 'video_id': video_id, 'progress': progress,
                               'durationTime': int(durationTime)})

    logger.info(f"共 {len(video_list)} 个待播放的课程,将依次播放:")
    for video in video_list:
        logger.info(f"{video['video_name']},总时长:{video['durationTime']}秒")
    return video_list

第三步:分析视频播放进度保存逻辑。

以上步骤,可以获取所有未完成的课程列表,包括名称、ID,持续时长,当前进度等信息。接下来,我们点击一个视频播放,然后看看接口处有什么信息:

这里我们发现请求的参数中有两个,一个是 time,值是 110,一个是 zgcid,可以猜测,time 是秒数,zgcid 是对应的是视频课程的编号。过一会时间,发现又发送了请求:

此时 time 为 226,发现间隔了约 120 秒钟,继续观察:

image.png

接口名称叫 saveplayrecord,很容易猜测到,每隔 120 秒发送向服务器一次这样的请求,就代表向服务汇报,我当前已经观看到了这个位置,当 time 为视频的总持续时长时,视频播放的状态会显示为已完成。

代码语言:javascript
复制
def play_video(video):
    logger.info(f"{video['video_name']} 开始播放..." )
    params = {
        'url': '/zgProject/front/learncenter/videocast2',
        'zgcid': video['video_id']
    }
    session.get("http://jxjy.jxt.zj.gov.cn/iext/zg/webfront/DatumFrontController/detail.do", params, headers)
    percent = float(video['progress'].replace("已观看","").replace("%","").strip())
    cnt = int(video['durationTime']*percent/100)
    logger.info(f"当前进度:{percent:0.2f}%")
    while cnt < video['durationTime']:
        time.sleep(120)
        cnt += 120
        if cnt > video['durationTime']:
           cnt =  video['durationTime']
        params = {'time':cnt, 'zgcid':video['video_id'] }
        r = session.post("http://jxjy.jxt.zj.gov.cn/iext/zg/webfront/DatumFrontController/saveplayrecord.do", params,headers)
        if r.json()['success'] == 1:
            logger.info(f"播放进度为: {cnt*100/video['durationTime']:0.2f}%")
    logger.info(f"{video['video_name']} 播放完成。" )

到这里,我们发现播放视频的过程中,每隔两分钟,网站会向服务器发送一次请求,保存当前视频的播放进度。此时已经豁然开朗。接下来就是组装代码的事情了。

用代码小结

代码语言:javascript
复制
login()
videos = get_play_list_info()

for video in videos:
    play_video(video)

print("视频播放完毕")

爬虫的本质在于获取信息,获取信息的前提是知道信息发送和接收的方式,因此如果本文看不太懂的朋友,建议先花费 1 - 2 个小时看下 HTTP 协议,再学习下非常适合人类使用的 Python 第三方库 requests,之后再看此文,就十分简单。

(完)

专注于Python技术分享

订阅、在看、转发是真情

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python七号 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第一步:登陆。
  • 第二步:获取信息。
  • 第三步:分析视频播放进度保存逻辑。
  • 用代码小结
相关产品与服务
云点播
面向音视频、图片等媒体,提供制作上传、存储、转码、媒体处理、媒体 AI、加速分发播放、版权保护等一体化的高品质媒体服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档