一些网站会提供m3u8视频地址,以供下载观看。或者一些网站经过分析后发现是使用m3u8格式进行播放的,这时使用m3u8的地址链接就可以下载到相应的视频。
一、关于m3u8:(https://blog.csdn.net/baidu_34418350/article/details/64922512)
m3u8是苹果公司推出一种视频播放标准,是m3u的一种,不过 编码方式是utf-8,是一种文件检索格式,将视频切割成一小段一小段的ts格式的视频文件,然后存在服务器中(现在为了减少I/o访问次数,一般存在服务器的内存中),通过m3u8解析出来路径,然后去请求。
示例链接:http://cdn.can.cibntv.net/12/201702161000/rexuechangan01/rexuechangan01.m3u8
第一层
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2650800,RESOLUTION=1920x1080
1.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:14
#EXTINF:11.480,
20170215T224129-1-0.ts
#EXTINF:11.480,
20170215T224129-1-1.ts
#EXTINF:10.480,
20170215T224129-1-2.ts
#EXTINF:11.400,
20170215T224129-1-3.ts
#EXTINF:11.120,
20170215T224129-1-4.ts
。。。
#EXTINF:1.000000,
3RCP49g82011159.ts
#EXTINF:0.600000,
3RCP49g82011160.ts
#EXT-X-ENDLIST
看到ts结尾的文件,这才是视频真正的存放路径:
http://cdn.can.cibntv.net/12/201702161000/rexuechangan01/20170215T224129-1-0.ts
这时候用浏览器下载就可以播放。不过这个播放不用我们去解析 android 4.0以后的videoView 就支持自动解析,并拼接播放。
安卓代码:
Uri uri = Uri.parse("http://cdn.can.cibntv.net/12/201702161000/rexuechangan01/rexuechangan01.m3u8"); video_view.setMediaController(new MediaController(this)); video_view.setVideoURI(uri); video_view.requestFocus(); ideo_view.start();
这样就可以简单的播放M3u8格式的视频了。
下载到本地,可直接用视频软件打开:
二、视频下载
可以用python脚本自动下载这些ts文件,但实际上有些网站的ts文件是用AES-128加密过的,所以需要解密才能播放。
加密过的视频在第二层m3u8中会有一个key文件链接:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="key.key" #key密钥文件
需要去读取这个key文件,才能拿到解密密钥。
-
# -*- coding:utf-8 -*-
-
import os
-
import sys
-
import requests
-
import datetime
-
from Crypto.Cipher
import AES
-
from binascii
import b2a_hex, a2b_hex
-
-
reload(sys)
-
sys.setdefaultencoding(
'utf-8')
-
-
def download(url):
-
download_path = os.getcwd() +
"\download"
-
if
not os.path.exists(download_path):
-
os.mkdir(download_path)
-
-
#新建日期文件夹
-
download_path = os.path.join(download_path, datetime.datetime.now().strftime(
'%Y%m%d_%H%M%S'))
-
#print download_path
-
os.mkdir(download_path)
-
-
all_content = requests.get(url).text
# 获取第一层M3U8文件内容
-
if
"#EXTM3U"
not
in all_content:
-
raise BaseException(
"非M3U8的链接")
-
-
if
"EXT-X-STREAM-INF"
in all_content:
# 第一层
-
file_line = all_content.split(
"\n")
-
for line
in file_line:
-
if
'.m3u8'
in line:
-
url = url.rsplit(
"/",
1)[
0] +
"/" + line
# 拼出第二层m3u8的URL
-
all_content = requests.get(url).text
-
-
file_line = all_content.split(
"\n")
-
-
unknow =
True
-
key =
""
-
for index, line
in enumerate(file_line):
# 第二层
-
if
"#EXT-X-KEY"
in line:
# 找解密Key
-
method_pos = line.find(
"METHOD")
-
comma_pos = line.find(
",")
-
method = line[method_pos:comma_pos].split(
'=')[
1]
-
print
"Decode Method:", method
-
-
uri_pos = line.find(
"URI")
-
quotation_mark_pos = line.rfind(
'"')
-
key_path = line[uri_pos:quotation_mark_pos].split(
'"')[
1]
-
-
key_url = url.rsplit(
"/",
1)[
0] +
"/" + key_path
# 拼出key解密密钥URL
-
res = requests.get(key_url)
-
key = res.content
-
print
"key:" , key
-
-
if
"EXTINF"
in line:
# 找ts地址并下载
-
unknow =
False
-
pd_url = url.rsplit(
"/",
1)[
0] +
"/" + file_line[index +
1]
# 拼出ts片段的URL
-
#print pd_url
-
-
res = requests.get(pd_url)
-
c_fule_name = file_line[index +
1].rsplit(
"/",
1)[
-1]
-
-
if len(key):
# AES 解密
-
cryptor = AES.new(key, AES.MODE_CBC, key)
-
with open(os.path.join(download_path, c_fule_name +
".mp4"),
'ab')
as f:
-
f.write(cryptor.decrypt(res.content))
-
else:
-
with open(os.path.join(download_path, c_fule_name),
'ab')
as f:
-
f.write(res.content)
-
f.flush()
-
if unknow:
-
raise BaseException(
"未找到对应的下载链接")
-
else:
-
print
"下载完成"
-
merge_file(download_path)
-
-
def merge_file(path):
-
os.chdir(path)
-
cmd =
"copy /b * new.tmp"
-
os.system(cmd)
-
os.system(
'del /Q *.ts')
-
os.system(
'del /Q *.mp4')
-
os.rename(
"new.tmp",
"new.mp4")
-
-
if __name__ ==
'__main__':
-
url =
"http://cdn.can.cibntv.net/12/201702161000/rexuechangan01/rexuechangan01.m3u8"
-
download(_url)
三、关于解密报错:No module named Crypto.Cipher
在python 中使用AES算法时,会报告上述错误,原因是Crypto并非标准模块,需要自己单独安装。
from Crypto.Cipher import AES
第一种办法:pip install pycropt 如果报错,就选择第二种办法。
第二种办法:使用编译好的安装包。http://www.voidspace.org.uk/python/modules.shtml#pycrypto
装上不好使就换一个试试,安装上面2个都不好使,就安装低版本的(我本机安装上面2个都报错,安装下面的版本就可用了)
如果还是报错就到下面目录修改大小写:(我没遇到这个问题)
C:\Python27\Lib\site-packages\crypto 改成
C:\Python27\Lib\site-packages\Crypto
四、合并文件
可以通过cmd命令的方式将所有的ts合并成一个文件:
copy /b d:\xxx\download_ts\* d:\xxx\download_ts\new.mp4
直接调用merge_file即可,会删除临时文件