相关文件

想学Python的小伙伴可以关注小编的公众号【Python日志】
有很多的资源可以白嫖的哈,不定时会更新一下Python的小知识的哈!!
需要源码的小伙伴可以在公众号回复视频下载器

简介

一款简单易用的视频下载器,目前支持的平台如下:

开发环境

Python版本:3.7.8
相关模块:
requests模块;
tqdm模块;
pyfreeproxy模块;
pyecharts模块;
以及一些python自带的模块。

环境搭建

安装Python并添加到环境变量,pip安装需要的相关模块即可。

效果展示

直接输入我们的一个视频链接就可以直接下载到文件夹downloaded中

复制哔哩哔哩视频链接

b站视频链接

https://www.bilibili.com/video/BV1si4y1y76f?spm_id_from=333.999.0.0



然后就可以直接播放我们的视频啦!!

代码实现过程

主代码


import sys
import copy
import json
import click
if __name__ == '__main__':from modules import *from __init__ import __version__
else:from .modules import *from .__init__ import __version__'''basic info'''
BASICINFO = '''************************************************************
Function: 视频下载器 V%s
微信公众号: Python日志
操作帮助:输入r: 重新初始化程序(即返回主菜单)输入q: 退出程序
视频保存路径:当前路径下的%s文件夹内
************************************************************''''''视频下载器'''
class videodl():def __init__(self, configpath=None, config=None, **kwargs):assert configpath or config, 'configpath of config should be given...'self.config = loadConfig(configpath) if config is None else configself.logger_handle = Logger(self.config['logfilepath'])self.supported_sources = self.initializeAllSources()'''非开发人员外部调用'''def run(self):print(BASICINFO % (__version__, self.config.get('savedir')))while True:# 视频链接输入user_input = self.dealInput('请输入视频链接: ')# 判断视频链接类型是否支持解析下载source = self.findsource(user_input)if source is None:self.logger_handle.warning('暂不支持解析视频链接: %s...' % user_input)continue# 实例化client = source(self.config, self.logger_handle)# 视频链接解析videoinfos = client.parse(user_input)# 视频下载client.download(videoinfos)'''判断视频源'''def findsource(self, url):for key, source in self.supported_sources.items():if source.isurlvalid(url): return sourcereturn None'''初始化所有支持的搜索/下载源'''def initializeAllSources(self):supported_sources = {'ted': Ted,'cntv': CNTV,'mgtv': MGTV,'migu': Migu,'pipix': Pipix,'acfun': AcFun,'zhihu': Zhihu,'xigua': Xigua,'iqiyi': Iqiyi,'douyin': Douyin,'haokan': Haokan,'bilibili': Bilibili,'pipigaoxiao': Pipigaoxiao,}return supported_sources'''处理用户输入'''def dealInput(self, tip=''):user_input = input(tip)if user_input.lower() == 'q':self.logger_handle.info('ByeBye...')sys.exit()elif user_input.lower() == 'r':self.initializeAllSources()self.run()else:return user_input'''cmd直接运行'''
@click.command()
@click.option('-i', '--url', default=None, help='想要下载的视频链接, 若不指定, 则进入videodl终端版')
@click.option('-l', '--logfilepath', default='videodl.log', help='日志文件保存的路径')
@click.option('-p', '--proxies', default='{}', help='设置的代理')
@click.option('-s', '--savedir', default='videos', help='视频保存的文件夹')
def videodlcmd(url, logfilepath, proxies, savedir):config = {'logfilepath': logfilepath,'proxies': json.loads(proxies),'savedir': savedir,}dl_client = videodl(config=config)if url is None:dl_client.run()else:source = dl_client.findsource(url)client = source(dl_client.config, dl_client.logger_handle)videoinfos = client.parse(url)client.download(videoinfos)'''run'''
if __name__ == '__main__':import osrootdir = os.path.split(os.path.abspath(__file__))[0]dl_client = videodl(os.path.join(rootdir, 'config.json'))dl_client.run()

bilibili代码

'''
Function:B站视频下载器类
'''
import re
import time
from .base import Base
from ..utils.misc import *'''B站视频下载器类'''
class Bilibili(Base):def __init__(self, config, logger_handle, **kwargs):super(Bilibili, self).__init__(config, logger_handle, **kwargs)self.source = 'bilibili'self.__initialize()'''视频解析'''def parse(self, url):response = self.session.get(url, headers=self.headers)bv = re.compile('BV..........').search(url).group()response = self.session.get(self.pagelist_url.format(bv), headers=self.headers)response_json = response.json()cid_list = [item['cid'] for item in response_json['data']]titles = [item.get('part', f'视频走丢啦_{time.time()}') for item in response_json['data']]download_urls = []for cid in cid_list:response = self.session.get(self.play_url.format(cid, bv), headers=self.headers)response_json = response.json()for item in response_json['data']['durl']:download_urls.append(item['url'])assert len(titles) == len(download_urls)videoinfos = []for idx, download_url in enumerate(download_urls):videoinfo = {'source': self.source,'download_url': download_url,'savedir': self.config['savedir'],'savename': '_'.join([self.source, filterBadCharacter(titles[idx])]),'ext': 'mp4',}videoinfos.append(videoinfo)return videoinfos'''初始化'''def __initialize(self):self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',}self.pagelist_url = 'https://api.bilibili.com/x/player/pagelist?bvid={}&jsonp=jsonp'self.play_url = 'http://api.bilibili.com/x/player/playurl?&cid={}&bvid={}&qn=80&fnval=0&fnver=0&fourk=1''''判断视频链接是否属于该类'''@staticmethoddef isurlvalid(url):valid_hosts = ['bilibili.com/video']for host in valid_hosts:if host in url: return Truereturn False

抖音代码

'''
Function:抖音视频下载器类
'''
import re
import json
import time
import random
import requests
from .base import Base
from ..utils.misc import *'''抖音视频下载器类'''
class Douyin(Base):def __init__(self, config, logger_handle, **kwargs):super(Douyin, self).__init__(config, logger_handle, **kwargs)self.source = 'douyin'self.__initialize()'''视频解析'''def parse(self, url):url = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', url)[0]response = self.session.get(url)if response.url[:28] == 'https://www.douyin.com/user/':videoinfos = self.multiparse(response)else:videoinfos = self.singleparse(response)return videoinfos'''批量下载用户的视频'''def multiparse(self, response):videoinfos = []key = re.findall(r'/user/(.*?)\?', str(response.url))[0]if not key: key = response.url[28: 83]page_count, max_cursor = 35, 0while True:url = self.uid_url.format('post', key, page_count, max_cursor)response = self.session.get(url, headers=self.headers)response_json = json.loads(response.content.decode())max_cursor, aweme_list = response_json['max_cursor'], response_json['aweme_list']if max_cursor == 0: breakfor idx in range(min(page_count, len(aweme_list))):download_url = str(aweme_list[idx].get('video', {}).get('play_addr', {}).get('url_list', [''])[0])videoinfo = {'source': self.source,'aweme_id': aweme_list[idx].get('aweme_id', None),'download_url': download_url,'savedir': self.config['savedir'],'savename': '_'.join([self.source, filterBadCharacter(str(aweme_list[idx].get('desc', f'视频走丢啦_{time.time()}')))]),'ext': 'mp4',}if videoinfo['download_url']: videoinfos.append(videoinfo)time.sleep(random.random() + 0.2)return videoinfos'''下载单个视频'''def singleparse(self, response):url = self.iteminfo_url.format(re.findall(r'video/(\d+)?', str(response.url))[0])response_json = json.loads(self.session.get(url, headers=self.headers).text)try: download_url = str(response_json['item_list'][0]['video']['play_addr']['url_list'][0]).replace('playwm','play')except: return []videoinfo = {'source': self.source,'download_url': download_url,'savedir': self.config['savedir'],'savename': '_'.join([self.source, filterBadCharacter(str(response_json.get('item_list', [{}])[0].get('desc', f'视频走丢啦_{time.time()}')))]),'ext': 'mp4',}return [videoinfo]'''初始化'''def __initialize(self):self.headers = {'User-Agent': 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Mobile Safari/537.36 Edg/87.0.664.66',}self.iteminfo_url = 'https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids={}'self.uid_url = 'https://www.iesdouyin.com/web/api/v2/aweme/{}/?sec_uid={}&count={}&max_cursor={}&aid=1128&_signature=PDHVOQAAXMfFyj02QEpGaDwx1S&dytk=''''判断视频链接是否属于该类'''@staticmethoddef isurlvalid(url):valid_hosts = ['v.douyin.com']for host in valid_hosts:if host in url: return Truereturn False

皮皮搞笑视频


import re
import json
from .base import Base
from ..utils.misc import *'''皮皮搞笑视频下载器类'''
class Pipigaoxiao(Base):def __init__(self, config, logger_handle, **kwargs):super(Pipigaoxiao, self).__init__(config, logger_handle, **kwargs)self.source = 'pipigaoxiao'self.__initialize()'''视频解析'''def parse(self, url):pattern = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.S)url = re.findall(pattern, url)[0]self.headers['Referer'] = urltry:mid = re.findall('mid=(\d+)', url, re.S)[0]pid = re.findall('pid=(\d+)', url, re.S)[0]except:mid = ''pid = url.split('/')[-1]data = {'mid': int(mid) if mid else 'null','pid': int(pid),'type': 'post',}response = self.session.post(self.content_url, data=json.dumps(data), headers=self.headers)response_json = response.json()download_url = response_json['data']['post']['videos'][str(response_json['data']['post']['imgs'][0]['id'])]['url']title = response_json['data']['post']['content'].replace('\n', '')videoinfo = {'source': self.source,'download_url': download_url,'savedir': self.config['savedir'],'savename': '_'.join([self.source, filterBadCharacter(title)]),'ext': 'mp4',}return [videoinfo]'''初始化'''def __initialize(self):self.headers = {'Host': 'share.ippzone.com','Origin': 'http://share.ippzone.com','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36',}self.content_url = 'https://h5.ippzone.com/ppapi/share/fetch_content''''判断视频链接是否属于该类'''@staticmethoddef isurlvalid(url):valid_hosts = ['h5.ippzone.com', 'share.ippzone.com']for host in valid_hosts:if host in url: return Truereturn False

代码量太多,小编就不全部展示啦
代码获取可以关注小编公众号:Python日志
在公众号中回复:视频下载器就可以领取啦

【Python工具】Python实现一款支持各大平台的视频下载器 | 附源码相关推荐

  1. python 开发视频播放网站_python开发微电影视频网站教程附源码

    做为一个合格的Pythoner,只掌握一个框架是不够,如果你有过其它Python框架(例如django)的使用经验,对比不同框架的特性来学习,你将收获更多 当前信息若含有黄赌毒等违法违规不良内容,请点 ...

  2. 【Python】基金/股票 最大回撤率计算与绘图详解(附源码和数据)

    如果你想找的是求最大回撤的算法,请跳转:[Python] 使用动态规划求解最大回撤详解 [Python]基金/股票 最大回撤率计算与绘图详解(附源码和数据) 0. 起因 1. 大成沪深300指数A 5 ...

  3. 2款不同样式的CSS3 Loading加载动画 附源码

    原文:2款不同样式的CSS3 Loading加载动画 附源码 我们经常看到的Loading加载很多都是转圈圈的那种,今天我们来换一种有创意的CSS3 Loading加载动画,一种是声波形状的动画,另一 ...

  4. 一款仿网易云音乐Java开源系统(附源码)

    嗨喽!Java后端编程的各位小伙伴们,由于公众号做了乱序推送改版,为了保证公众号的推文能够第一时间及时送达到大家手上,大家记得将公众号 加星标置顶 ,公众号每天会送上Java技术干货推文 ! 上篇推文 ...

  5. 【Python实战】WIFI密码小工具,甩万能钥匙十条街,WIFI任意连哦~(附源码)

    前言 不会吧不会吧,流量都这么便宜了不会还有人在蹭别人家WIFI吧? 但是也可以理解哈,试问谁还没有经历过这种时光那?就算是我,也曾经有过蹲在别人家大门 口蹭WIFi的事儿.这都是成长道路中不可避免的 ...

  6. Python 自动化收取蚂蚁森林能量,不错过暗恋的她(附源码)

    作者 | 锅g头 来源 | Crossin的编程教室 最近在家远程工作,结果作息更混乱了,早上起不来,导致我蚂蚁森林能量天天被偷,严重影响我沙漠造树"大业".于是我决定用pytho ...

  7. 【Python游戏】Python基于第三方库pygame实现一个魂斗罗小游戏,毕业设计必备 | 附源码

    前言 halo,包子们下午好 今天给打击整一个魂斗罗小游戏 很多小伙伴接触魂斗罗应该是在小时候的一个手柄游戏上面吧 我记得作为90后的我,玩这一款游戏是在小学的时候 废话不多说,直接上才艺 今天给大家 ...

  8. 用Python几行代码实现简单的人脸识别,10分钟完成(附源码)

    前言 今天,我们用Python实现简单的人脸识别技术! Python里,简单的人脸识别有很多种方法可以实现,依赖于python胶水语言的特性,我们通过调用包可以快速准确的达成这一目的.这里介绍的是准确 ...

  9. 用Python标准库turtle画一头金牛,祝您新年牛气冲天!(附源码)

    今年是牛年,祝大家新年牛气冲天!嗨皮牛Year! 前几天在百度图片里下载了一张金牛的图片,就是封面的这张.想着用Python标准库turtle肯定可以画出这张图,所以说干就干,花两天时间实现了. 画图 ...

最新文章

  1. 【FPGA】双端口RAM的设计(异步读写)
  2. CodeForces - 715A Plus and Square Root(思维+构造)
  3. linux网络编程——webserver服务器编写
  4. Mr.J-- 图片墙动画效果
  5. 深入理解分布式事务,高并发下分布式事务的解决方案
  6. foobar的来源与历史
  7. 《火球——UML大战需求分析》(第3章 分析业务模型-类图)——3.7 关于对象图
  8. 工业互联网为湖南制造装上“智脑”
  9. 【TSP】基于matlab遗传算法求解31城市旅行商问题【含Matlab源码 1150期】
  10. 【JAVA】学习java 运行环境配置
  11. NJUPT【电工电子基础实验】
  12. Java 全国省市接口
  13. C语言实现简单电子通讯录
  14. 无线路由器桥接 - 终极完美教程
  15. 苹果微信昵称表情php,苹果手机微信名如何使用特殊符号
  16. 【论文精读】SalBiNet360: Saliency Prediction on 360° Images with Local-Global Bifurcated Deep Network
  17. 星际文件系统新动作——建立存储供应商赏金委员会
  18. 团体程序设计天梯赛-练习集 L1-015 跟奥巴马一起画方块
  19. POJ(8463)-----Stupid cat Doge(openjudge)
  20. 电脑装机完没有efi_win7系统eFI引导从硬盘安装的操作方法

热门文章

  1. Move Semantics and Perfect Forwarding in C++11
  2. Ubuntu18.04 搜狗输入法不能输入中文问题、
  3. 饿了么技术往事(上)
  4. 基于stm32c8t6的两轮平衡小车 第一篇——物料选购
  5. 小谈Intel SGX
  6. iOS6和iOS7代码的适配(2)——status bar
  7. HTML期末大作业~节日礼品购物商城网站html模板(HTML+CSS+JavaScript)
  8. 光纤交换机 序列号_交换机 获取S系列交换机序列号
  9. stm32(声音传感器控制LED)
  10. 电化学甲醛气体传感器