Python 爬虫抓取网站 mp4 视频并且使用 tqdm 显示进度条下载视频

读这篇文章之前可以先读好久之前发的一篇题为 《Python批量下载m3u8的切片影片》 的文章,里面说明了怎么分析 m3u8 文件并且批量下载 ts 视频片段。

最近因为要看网课的原因,嫌弃网课网站带宽不足导致视频播放太卡,所以重操旧业了一下,但是我发现 mp4 文件大小比 ts 文件大的多了,有时候真怕代码出错或者下载卡住了,所以添加了一下下载进度条方便自己查看。

爬取网站 mp4 视频

首先我们可以先用 BeautifulSoup 和 Requests 去爬取并且分析我们的网站内容,我的那个网课网站并没有什么播放器 js 而是直接用的 video 标签进行播放,所以很简单就可以抓取了。

import requests
from bs4 import BeautifulSoup as bs

def getVideo(url):
    res = requests.get(url)
    html = bs(res.text, features="html.parser")
    video = html.find_all("video")[0]
    return video

这里给一个基本抓取 video 标签的代码,建议就是针对自己要抓取的网站进行修改,有时候要加 User-Agent 有时候要加 Referer 可以自己在 get 的时候添加。如果网站上有多于一个 video 那可以自己分析,如果全部要下载的话那就直接返回一个 list 然后在下载的时候处理就可以了。

如果抓取的网站用了一些 js 播放器,那么还是老老实实分析 Network 让后抓取 m3u8 吧。

下载视频并且显示进度条

这里我们可以使用 tqdm 显示进度条,只需要在 requests 抓取的时候设置成流就可以进行迭代了:

from tqdm import tqdm
import requests

def download():
    page = "http://example.com/video.html"
    url = getVideo(page)
    res = requests.get(url, stream=True) # 设定为流
    total_size = int(res.headers.get("Content-Length", 0)) # 文件总大小
    block_size = 1024 # 每次迭代下载大小
    progress_bar = tqdm(total = total_size, unit='iB', unit_scale=True)
    filename = os.path.join(os.getcwd(), "test.mp4")
    with open(filename, "wb") as f:
        for data in res.iter_content(block_size):
            progress_bar.update(len(data))
            f.write(data)
        progress_bar.close()
    print("下载完成")

if __name__ == "__main__":
    download()

这里给了一个大致的代码,如果有多个视频要下载那么加个 for 循环就可以了。记得使用之前整理一下代码即可,效果大概是这样的:

100%|████████████████████████████████████████████████████████████████████████████████| 283M/283M [04:55<00:00, 960kiB/s]
下载完成