一、m3u8类型说明

视频下载,一般而言,无非两种情况。
一种,链接明确是以 mp4、mkv、rmvb 这类视频格式后缀为结尾的链接,这种下载很简单,跟图片下载方法一样,就是视频文件要比图片大而已。
另一种,链接是以 m3u8 这类分段视频后缀结尾的链接。啥是分段视频?
抓包看一下就知道了,打开视频播放链接:http://youku.com-youku.net/share/f0d48bde60d407c45af7ca00d1ef927b

使用FFmpeg下载m3u8类型视频 - 图1

现在很多视频都是分段存储的,你看视频的时候,其实是在加载一个个 ts 视频片段,一个片段是几秒钟的视频。
这种视频要怎么下载?怎么将 ts 视频片段组合成一个视频?
其实,如果知道方法,就很简单。
m3u8 这种格式的视频,就是由一个个 ts 视频片段组成的。
一个 m3u8 文件并不大,你可以把它理解为链表,每个 ts 视频片段文件,都有下一个时序的 ts 视频片段的地址。
使用FFmpeg下载m3u8类型视频 - 图2

记住一点,解决音频和视频的一些问题,可以看看 FFmpeg,它的中文名叫多媒体视频处理工具。
FFmpeg 有非常强大的功能包括视频采集、视频格式转换、视频抓图、给视频加水印等功能。
这种 ts 视频片段合成,格式转换问题,交给 FFmpeg 就好了。
要使用 FFmpeg,需要先安装配置一番。

FFmpeg 也有 Python API 接口,名字叫 ffmpy3,安装好 FFmpeg 后,可以直接通过 pip 安装。

  1. pip install ffmpy3

比如想要下载 m3u8 文件。
URL:http://youku.com-youku.net/20180614/11920_4c9e1cc1/index.m3u8
可以在命令行输入如下指令:

ffmpeg -i "http://youku.com-youku.net/20180614/11920_4c9e1cc1/index.m3u8" "第001集.mp4"

视频会保存为「第001集.mp4」。

如果用 Python 接口,也只需要两行代码:

import ffmpy3
ffmpy3.FFmpeg(inputs={'http://youku.com-youku.net/20180614/11920_4c9e1cc1/index.m3u8': None}, outputs={'第001集.mp4':None}).run()

FFmpeg 自动整合 ts 分段视频,并保存为 mp4 格式的视频。

二、代码

# -*- coding:utf-8 -*-
import os
import ffmpy3
import requests
from bs4 import BeautifulSoup
from multiprocessing.dummy import Pool as ThreadPool

# search_keyword = '越狱第一季'

serach_res = {}


# 获取url及name
def get_videos_url(search_keyword):
    search_url = "http://www.jisudhw.com/index.php?m=vod-search"
    serach_headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36',
        'Referer': 'http://www.jisudhw.com/',
        'Origin': 'http://www.jisudhw.com',
        'Host': 'www.jisudhw.com'
    }
    serach_datas = {
        'wd': search_keyword,
        'submit': 'search'
    }
    r = requests.post(url=search_url, headers=serach_headers, data=serach_datas).content.decode('utf-8')
    search_html = BeautifulSoup(r, 'lxml')
    search_spans = search_html.find_all('span', class_='xing_vb4')
    for span in search_spans:
        url = 'http://www.jisudhw.com' + span.a.get('href')
        # video_dir = span.a.string
        # 创建电影文件夹
        if search_keyword not in os.listdir('./'):
            os.mkdir(search_keyword)
        r = requests.get(url=url).content.decode('utf-8')
        detail_bf = BeautifulSoup(r, 'lxml')
        uls = detail_bf.find('div', id="1").ul.stripped_strings
        for m3u8 in uls:
            video_num, value_path = m3u8.split("$")
            serach_res[value_path] = video_num


# 使用FFmpeg下载视频
def downVideo(url_detail):
    global search_keyword
    num = serach_res[url_detail]
    name = os.path.join(search_keyword, num)
    ffmpy3.FFmpeg(inputs={url_detail: None}, outputs={name: None}).run()


if __name__ == '__main__':
    # 开8个线程池
    search_keyword = "越狱第一季"
    get_videos_url(search_keyword)
    pool = ThreadPool(8)
    results = pool.map(downVideo, serach_res.keys())
    pool.close()
    pool.join()

三、总结

FFmpeg 配置

下载地址:https://ffmpeg.zeranoe.com/builds/
1.下载最新版 FFmpeg,bin目录为:”D:\Program Files (x86)\ffmpeg-win64-static\bin”,写入环境变量path
2.pip install ffmpy3后,编辑ffmpy3.py文件(import ffmpy3 按住ctrl点击ffmpy3 ),修改”def init(self, executable=r’D:\Program Files (x86)\ffmpeg-win64-static\bin\ffmpeg.exe’)”
3.或直接将bin目录下的ffmpeg.exe文件复制到当前python项目中,不必修改ffmpy3.py文件

使用ffmpy3.FFmpeg下载文件

ffmpy3.FFmpeg(inputs={"http://youku.com-youku.net/20180614/11920_4c9e1cc1/index.m3u8": None}, outputs={"第01集.mp4": None}).run()

注意 outputs={“第01集.mp4”: None} 必须有”xxx.mp4” 后缀名,否则会报错

Unable to find a suitable output format for '第01集'
AttributeError: 'NoneType' object has no attribute 'decode'