基于httpx和pyside2的哔哩哔哩(bilibili)-视频下载程序

该项目是一个使用Python编写的Bilibili视频下载器,具备图形用户界面,采用httpx库实现协程下载。支持下载普通视频、多集视频以及番剧和电影。用户需要提供SESSDATA cookie来下载番剧。程序还具有检查更新和日志记录功能,允许自定义视频解析器。开发目的是学习交流,不建议用于商业用途。
摘要由CSDN通过智能技术生成

Bilibili_downloader

LICENCE:GPL-3.0

⭐如果能下😁记得STAR⭐

项目地址下载地址
GitHub平台GitHub发行版
Gitee平台Gitee发行版

1. 特点

  1. 使用了pyside2构建图形界面
  2. 使用了httpx以协程方式下载
  3. 借鉴了Java接口式、面向对象开发 (Java初学者的一次尝试😆)
  4. 准 - 全类型标注(尽力了…)

2.功能

  • 能够下载bilibili单集的普通视频
  • 能够下载bilibili多集的普通视频
  • 能够下载bilibili番剧&电影

3.使用方法

3.1 普通视频

  1. 在电脑浏览器上找到想要下载的b站视频,复制网页链接
  2. 在“视频链接”后的文本输入框内粘贴该链接,另外:
  3. 点击“下载”按钮

3.2 番剧/电影

  1. 在“设置”-“设置cookie”中添加自己的SESSDATA (内含操作示意图)
  2. 在电脑浏览器上找到想要下载的番剧/电影,复制网页链接
  3. 需要注意的是:
  4. 点击“下载”按钮

4.截图

demo1demo2demo3

5.更新日志

v1.1.1

  • 新增:检查更新功能
  • 优化:部分交互

v1.1.0

  • 新增:番剧/电影下载功能
  • 新增:可设置cookie
  • 修复:因为未转义导致的日志写入异常

v1.0.1

  • 修复:日志只在重启程序后才刷新的bug

v1.0.0

  • 新增:能够下载bilibili的普通视频
  • 修复:包含 ?p=的链接会解析错误
  • 修复:在下载期间退出窗口,子线程仍在后台下载 或 主线程卡死无法退出
  • 修复:变更保存路径后,需要重启才能恢复,否则会报错

6.一些想说的

  • 开发本程序仅用于学习交流,请勿用于任何商业用途!
  • 普通视频的解析器是不需要用户自行更新cookies的加密版本;番剧/电影的下载器需要在“设置”-“设置cookie”中添加自己的SESSDATA。
  • ui中的“主进度”其实是正在下载的文件的序号占下载任务总数的百分比,因此由于协程下载的特性,会在各个文件反复横跳,因此“主进度”仅用于提升观赏效果。
  • 正因如此,本程序同时下载多集视频的效率远高于下载单集视频

7.参考资料

8.对二次开发的构思

VideoHandler在初始化时,会调用get_proper_video_parser方法,如下方代码所示

# video_handler.py
class VideoHandler:
    def __init__(self, url, quality: Union[str, int], video_format: str, save_path: Path):
		# ...
        self.video_parser: VideoParserInterface = self.get_proper_video_parser()

    def get_proper_video_parser(self) -> VideoParserInterface:
        if "bangumi" in self.url:
            return FanVideoParser(self.url, self.quality)  # 为了下载番剧/电影的解析器
        else:
            return NormalVideoParser(self.url, self.quality)  # 默认的解析器

可以在此方法中自定义返回的视频分析器(继承自VideoParserInterface)

# video_parsers.py
class VideoParserInterface(abc.ABC):
    def __init__(self, url: str, quality: Union[str, int]):
        # ...
        self.downloader_list: List[VideoDownloader] = self.get_downloader_list()

    @abc.abstractmethod
    def get_downloader_list(self) -> List[VideoDownloader]:
        pass

downloader_list中的VideoDownloader,是下载器对象,下载方法用的异步函数

# my_classes.py
class VideoDownloader:
    def __init__(self, title, page: PageInAPI):
        self.title = title
        self.page = page
        self.local_path = Path(__file__)  # 这里是随便设个值,反正后面要改

    async def download(self, save_path: Path, video_format: str = ".flv",
                       all_progress_value: Union[int, float] = 0, headers: dict = None):
        # ...
        with open(self.local_path / video_name, 'wb') as f:
            async with async_downloader.stream('GET', url) as response:
                async for chunk in response.aiter_bytes():
                    f.write(chunk)

VideoDownloader.page 的类型(PageInAPI)是用于记录某一集视频的详细信息 (命名由来:b站的API对某一集的视频的名为Page),初始化参数info_dict是从api传来的json数据(转成字典后做实参传入)。特别说明,VideoDownloader.title类似于电视剧剧名,会作为文件夹的名字;此处的PageInAPI.part类似于电视剧每一集的集名,会作为视频的名称。

# my_classes.py
class PageInAPI:
    """用于记录api中的单个Page的信息"""
    def __init__(self, info_dict: Dict[str, Union[int, str]]):
        self.part: str = info_dict.get("part", '视频名')
        self.url: List[str] = []
        self.size: List[int] = []
        # ...其他属性非必需,可以根据实际情况置空
        
    def set_url(self, url: str):
        self.url.append(url)

    def set_size(self, size: int = 1):
        self.size.append(size)

综上所述,若需要扩展其他下载器,或许可按以下步骤改写:

  1. 自定义视频分析器(继承自VideoParserInterface),并重写get_downloader_list方法,使其能返回List[VideoDownloader]
  2. 更改VideoHandler.get_proper_video_parser中的逻辑,使其在指定条件下返回新的视频分析器

GitHub@laorange
bilibili@辣橙yzc

2021年11月26日

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值