前(废)言(话)

好慕课(haomooc)是一个全学科,综合性的慕课导航平台。平台课程包含大学,中小学以及技能培训等。好慕课内所有同步视频课程免费。
好慕课算是一个比较良心的慕课平台了,里面的视频资源非常全面。然而,其线上观看的播放器较为简陋,不尽人意。

于是编写脚本,尝试将好慕课的视频批量下载下来。

过程实现

视频地址获取

通过抓包发现,其中加载了一个m3u8文件:
python-haomooc-zhuabao.jpg
而且每次刷新后,m3u8文件的地址随之改变,猜测其m3u8文件是有有效期的。
分析源代码可知,m3u8文件的动态地址已经写在<video></video>中。
python-haomooc-01.jpg
那就正则匹配出来呗:

import requests
import re
i = 'https://haomooc.com/index.php?s=xiaoxue&c=show&id=495&dezhi=1' #要抓取的网址
html = requests.get(i,headers = hea)
html.encoding = 'utf-8'  
#此为正则表达式部分。找到规律,利用正则,内容就可以出来
M3u8 = re.findall('<source src="(.*?)" type="application/x-mpegURL">',html.text,re.S)
#正则匹配`<source src="`到`" type="application/x-mpegURL">`的文本。

获取一季视频的列表

python-haomooc-02.jpg
发现前面都带有<a href="index.php?s=,但是搜索得知,在最上面还有一个与我们需要内容无关的项,如果使用正则匹配后不进行筛选,会混入很多无用内容。
python-haomooc-03.jpg
正则匹配后筛选列表中含有sectionid字样的元素,以保证筛选到的都是正常的URL:

print ('获取列表……')
html = requests.get(Url0,headers = hea)
html.encoding = 'utf-8' #这一行是将编码转为utf-8否则中文会显示乱码。
href = re.findall('<a href="index.php?(.*?)" ',html.text,re.S)  #正则匹配所有`<a href="index.php?s=`到`" `的内容
href = [s for s in href if 'sectionid' in s]  #筛选列表中含有`sectionid`字样的元素

此时以上列表href的内容是:

xiaoxue&c=show&packid=100330§ionid=2311
xiaoxue&c=show&packid=100330§ionid=2269
xiaoxue&c=show&packid=100330§ionid=2278
xiaoxue&c=show&packid=100330§ionid=2292

补充上前缀就完整了。
那么主体部分基本完成。

视频下载部分

干脆用一个别人做好的批量m3u8下载器,何乐而不为。(点我跳转到原网站)
m3u8 download.jpg
按调用格式,将获取到的m3u8地址逐行写入文件,最后运行os.system()进行调用就OK了。

问题

emmm,获取到的m3u8文件大概只有5-10分钟左右的有效期,当一次性获取过多m3u8地址时,前面的还没下载完后面的m3u8文件就过期了,目前的解决方法:分区间下载,或者你手动修改源码让它每获取20个文件隔五分钟再接下去获取也可以。
python-haomooc-exe.jpg

源码和成品下载

本地下载(慢)
Onedrive下载
源码(Python3.x环境 请提前安装requests库,并下载M3u8下载器):

import requests
import re
from os import system
num = 0
with open('URLURL.txt','w',encoding='utf-8') as f:
    print('文件已创建')
Url0 = input("Give me a Haomooc Url : ")
    #hea是我们自己构造的一个字典,里面保存了user-agent。
    #让目标网站误以为本程序是浏览器,并非爬虫。
    #从网站的Requests Header中获取。【审查元素】
hea = {'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36'}
print ('获取列表……')
html = requests.get(Url0,headers = hea)
html.encoding = 'utf-8' #这一行是将编码转为utf-8否则中文会显示乱码。
 
#此为正则表达式部分。找到规律,利用正则,内容就可以出来
href = re.findall('<a href="index.php?(.*?)" ',html.text,re.S)
href = [s for s in href if 'sectionid' in s]  #筛选好慕课URL部分
start = input ('共有'+str(len(href))+'个视频。从哪个开始?')
stop = input ('从第'+str(start)+'个视频开始。到哪个结束?')
num = 0 + int(start) - 1
print ('正在下载从第' + start +'个视频到第' + stop +'个视频的m3u8文件信息。')

'''
num_tit = 0
for tit in href:
    num_tit = num_tit + 1
    print ('[' + str(num_tit) + ']' + tit)    
'''
'''
if int(stop)==len(href):
    href = href[int(start)-1:int(stop)]
else:
'''
href = href[int(start)-1:int(stop)]
for i in href:
    i = 'https://haomooc.com//index.php' + i
    #print (i)
    html = requests.get(i,headers = hea)
    html.encoding = 'utf-8'  
    #此为正则表达式部分。找到规律,利用正则,内容就可以出来
    title = re.findall('<title>(.*?)-好慕课</title>',html.text,re.S)
    M3u8 = re.findall('<source src="(.*?)" type="application/x-mpegURL">',html.text,re.S)
    num = num + 1
    xuhao = str(num) + '-'
    all_info = xuhao + title[0]+','+M3u8[0]
    print (all_info)
    with open('URLURL.txt','a+',encoding='utf-8') as f:
        f.write(all_info + '\n')

system('m3u8.exe URLURL.txt')
print ()
print ('M3U8信息下载完成,已向下载器提交下载信息。')
print ()
system('pause')