【Python】哔哩哔哩视频下载第2篇:进程池的应用

本系列文章旨在分享python学习的心得,所涉及的视频和up主皆是值得与大家分享的,如有冒犯,望请谅解。

本期任务:使用Python下载B站大佬投稿页所有视频

【Python】第1节:常规方法与you-get

【Python】第2节:进程池的应用

【Python】第3节:Beautifulsoup+requests+selenium获取视频url

【Python】第4节:常见问题的解决(2020年3月23日哔哩哔哩将稿件的「av 号」变更为「BV 号」)

完整GitHub代码:BilibiliDownloader

上一节,我们实现了用you-get下载哔哩哔哩技术视频,但运行过程中,我们只用到了一个python进程,CPU利用率很低,网络带宽也未得到充分利用。
在这里插入图片描述
本节,我们将利用python的多进程库multiprocessing,调用多进程来辅助you-get下载。

代码

完整代码

import multiprocessing as mp
import os
import sys

import you_get


class YouGet:

    def __init__(self, path):
        self.path = path  # 存放视频文件

    def rmfile(self, path):
        """
        删除文件
        :param path: 文件路径
        :return: None
        """
        try:
            os.remove(path)
        except Exception as e:
            print(e)

    def download(self, url):
        sys.argv = ['you-get', '-o', self.path, url]
        you_get.main()

        # 下载完成,删除xml文件
        for file in os.listdir(self.path):
            if file[-3:] == 'xml':
                self.rmfile(os.path.join(self.path, file))


class MultiCore:
    def __init__(self, path):
        self.yg = YouGet(path)

    def job(self, urls):
        for url in urls:
            self.yg.download(url)

    def process(self, param=[], **kwargs):
        """
        :param param:
            self.job()函数的参数配置
        :param kwargs:
            processes: int, 核数,默认全部
        :return: 计算结果,list
        """
        pool = mp.Pool(processes=kwargs.get("processes"))  # 构建进程池
        pool.map(self.job, param)

    def split_list(self, ls, n):
        """
        将列表分成若干个个小列表
        :param ls: init list/numpy list
        :param n: split num
        :return: n small lists
        """
        if n > len(ls):
            print('分片数大于列表长度!')
        else:
            return [ls[i:i + n] for i in range(0, len(ls), n)]


if __name__ == "__main__":
    path = r"你想要的下载位置"
    urls = ["https://www.bilibili.com/video/av18156598?p=" + str(_) for _ in range(1, 107)]  # 目标视频urls列表

    mc = MultiCore()
    data = mc.split_list(urls, 8)  # 将urls分成8份
    mc.process(param=data)

核心部分讲解

YouGet类,上节已介绍,详情见:【Python】使用you-get下载哔哩哔哩视频

MultiCore类:

将YouGet实例作为公共变量,多核并行调用download()函数,避免重复定义YouGet类

	 def __init__(self, path):
	        self.yg = YouGet(path)

遍历对应的url列表,依次进行下载

    def job(self, urls):
        for url in urls:
            self.yg.download(url)

将一个大的url列表拆分成长度尽可能相等的多个子列表,方便并行下载

    def split_list(self, ls, n):
        """
        将列表分成若干个个小列表
        :param ls: init list/numpy list
        :param n: split num
        :return: n small lists
        """
        if n > len(ls):
            print('分片数大于列表长度!')
        else:
            return [ls[i:i + n] for i in range(0, len(ls), n)]

配置需要参与并行计算的核数(如:processes=8,默认使用可调用的所有核),使用mp.Pool创建进程池,将拆分好的二维列表使用map交给job函数进行并行计算。

    def process(self, param=[], **kwargs):
        """
        :param param:
            self.job()函数的参数配置
        :param kwargs:
            processes: int, 核数,默认全部
        :return: 计算结果,list
        """
        pool = mp.Pool(processes=kwargs.get("processes"))  # 构建进程池
        pool.map(self.job, param)

效果

本实例下载兄弟连Linux教程(通俗易懂,强力推荐入门使用),总计106集,将任务分成8份,默认使用全部核进行计算。
在这里插入图片描述
任务管理器状态如下:确实调用了多个python进程,带宽利用程度显著提高!
在这里插入图片描述

未完待续。。。

本节我们介绍了如何使用多进程来下载给定url的视频,但是url不一定都是像本文中是连续的,下一篇我们将介绍如何自动获取视频的url。

【Python】哔哩哔哩视频下载第3篇:Beautifulsoup+requests+selenium获取大牛技术视频url

原创文章 36 获赞 32 访问量 2758

猜你喜欢

转载自blog.csdn.net/weixin_43868754/article/details/104949475
今日推荐