本系列文章旨在分享python学习的心得,所涉及的视频和up主皆是值得与大家分享的,如有冒犯,望请谅解。
本期任务:使用Python下载B站大佬投稿页所有视频
【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