python 爬取B站原视频的实例代码


Posted in Python onSeptember 09, 2020

B站原视频爬取,我就不多说直接上代码。直接运行就好。
B站是把视频和音频分开。要把2个合并起来使用。这个需要分析才能看出来。然后就是登陆这块是比较难的。

import os
import re
import argparse
import subprocess
import prettytable
from DecryptLogin import login


'''B站类'''
class Bilibili():
	def __init__(self, username, password, **kwargs):
		self.username = username
		self.password = password
		self.session = Bilibili.login(username, password)
		self.headers = {
						'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36'
					}
		self.user_info_url = 'http://api.bilibili.com/x/space/acc/info'
		self.submit_videos_url = 'http://space.bilibili.com/ajax/member/getSubmitVideos'
		self.view_url = 'http://api.bilibili.com/x/web-interface/view'
		self.video_player_url = 'http://api.bilibili.com/x/player/playurl'
	'''运行主程序'''
	def run(self):
		while True:
			userid = input('请输入目标用户ID(例:345993405)(我的一个LOL好友凯撒可以关注他一下 谢谢) ——> ')
			user_info = self.__getUserInfo(userid)
			tb = prettytable.PrettyTable()
			tb.field_names = list(user_info.keys())
			tb.add_row(list(user_info.values()))
			print('获取的用户信息如下:')
			print(tb)
			is_download = input('是否下载该用户的所有视频(y/n, 默认: y) ——> ')
			if is_download == 'y' or is_download == 'yes' or not is_download:
				self.__downloadVideos(userid)
	'''根据userid获得该用户基本信息'''
	def __getUserInfo(self, userid):
		params = {'mid': userid, 'jsonp': 'jsonp'}
		res = self.session.get(self.user_info_url, params=params, headers=self.headers)
		res_json = res.json()
		user_info = {
						'用户名': res_json['data']['name'],
						'性别': res_json['data']['sex'],
						'个性签名': res_json['data']['sign'],
						'用户等级': res_json['data']['level'],
						'生日': res_json['data']['birthday']
					}
		return user_info
	'''下载目标用户的所有视频'''
	def __downloadVideos(self, userid):
		if not os.path.exists(userid):
			os.mkdir(userid)
		# 非会员用户只能下载到高清1080P
		quality = [('16', '流畅 360P'),
				  ('32', '清晰 480P'),
				  ('64', '高清 720P'),
				  ('74', '高清 720P60'),
				  ('80', '高清 1080P'),
				  ('112', '高清 1080P+'),
				  ('116', '高清 1080P60')][-3]
		# 获得用户的视频基本信息
		video_info = {'aids': [], 'cid_parts': [], 'titles': [], 'links': [], 'down_flags': []}
		params = {'mid': userid, 'pagesize': 30, 'tid': 0, 'page': 1, 'order': 'pubdate'}
		while True:
			res = self.session.get(self.submit_videos_url, headers=self.headers, params=params)
			res_json = res.json()
			for item in res_json['data']['vlist']:
				video_info['aids'].append(item['aid'])
			if len(video_info['aids']) < int(res_json['data']['count']):
				params['page'] += 1
			else:
				break
		for aid in video_info['aids']:
			params = {'aid': aid}
			res = self.session.get(self.view_url, headers=self.headers, params=params)
			cid_part = []
			for page in res.json()['data']['pages']:
				cid_part.append([page['cid'], page['part']])
			video_info['cid_parts'].append(cid_part)
			title = res.json()['data']['title']
			title = re.sub(r"[‘'\/\\\:\*\?\"\<\>\|\s']", ' ', title)
			video_info['titles'].append(title)
		print('共获取到用户ID<%s>的<%d>个视频...' % (userid, len(video_info['titles'])))
		for idx in range(len(video_info['titles'])):
			aid = video_info['aids'][idx]
			cid_part = video_info['cid_parts'][idx]
			link = []
			down_flag = False
			for cid, part in cid_part:
				params = {'avid': aid, 'cid': cid, 'qn': quality, 'otype': 'json', 'fnver': 0, 'fnval': 16}
				res = self.session.get(self.video_player_url, params=params, headers=self.headers)
				res_json = res.json()
				if 'dash' in res_json['data']:
					down_flag = True
					v, a = res_json['data']['dash']['video'][0], res_json['data']['dash']['audio'][0]
					link_v = [v['baseUrl']]
					link_a = [a['baseUrl']]
					if v['backup_url']:
						for item in v['backup_url']:
							link_v.append(item)
					if a['backup_url']:
						for item in a['backup_url']:
							link_a.append(item)
					link = [link_v, link_a]
				else:
					link = [res_json['data']['durl'][-1]['url']]
					if res_json['data']['durl'][-1]['backup_url']:
						for item in res_json['data']['durl'][-1]['backup_url']:
							link.append(item)
				video_info['links'].append(link)
				video_info['down_flags'].append(down_flag)
		# 开始下载
		out_pipe_quiet = subprocess.PIPE
		out_pipe = None
		aria2c_path = os.path.join(os.getcwd(), 'tools/aria2c')
		ffmpeg_path = os.path.join(os.getcwd(), 'tools/ffmpeg')
		for idx in range(len(video_info['titles'])):
			title = video_info['titles'][idx]
			aid = video_info['aids'][idx]
			down_flag = video_info['down_flags'][idx]
			print('正在下载视频<%s>...' % title)
			if down_flag:
				link_v, link_a = video_info['links'][idx]
				# --视频
				url = '"{}"'.format('" "'.join(link_v))
				command = '{} -c -k 1M -x {} -d "{}" -o "{}" --referer="https://www.bilibili.com/video/av{}" {} {}'
				command = command.format(aria2c_path, len(link_v), userid, title+'.flv', aid, "", url)
				print(command)
				process = subprocess.Popen(command, stdout=out_pipe, stderr=out_pipe, shell=True)
				process.wait()
				# --音频
				url = '"{}"'.format('" "'.join(link_a))
				command = '{} -c -k 1M -x {} -d "{}" -o "{}" --referer="https://www.bilibili.com/video/av{}" {} {}'
				command = command.format(aria2c_path, len(link_v), userid, title+'.aac', aid, "", url)
				print(command)

				process = subprocess.Popen(command, stdout=out_pipe, stderr=out_pipe, shell=True)
				process.wait()
				# --合并
				command = '{} -i "{}" -i "{}" -c copy -f mp4 -y "{}"'
				command = command.format(ffmpeg_path, os.path.join(userid, title+'.flv'), os.path.join(userid, title+'.aac'), os.path.join(userid, title+'.mp4'))
				print(command)

				process = subprocess.Popen(command, stdout=out_pipe, stderr=out_pipe_quiet, shell=True)
				process.wait()
				os.remove(os.path.join(userid, title+'.flv'))
				os.remove(os.path.join(userid, title+'.aac'))
			else:
				link = video_info['links'][idx]
				url = '"{}"'.format('" "'.join(link))
				command = '{} -c -k 1M -x {} -d "{}" -o "{}" --referer="https://www.bilibili.com/video/av{}" {} {}'
				command = command.format(aria2c_path, len(link), userid, title+'.flv', aid, "", url)
				process = subprocess.Popen(command, stdout=out_pipe, stderr=out_pipe, shell=True)
				process.wait()
				os.rename(os.path.join(userid, title+'.flv'), os.path.join(userid, title+'.mp4'))
		print('所有视频下载完成, 该用户所有视频保存在<%s>文件夹中...' % (userid))
	'''借助大佬开源的库来登录B站'''
	@staticmethod
	def login(username, password):
		_, session = login.Login().bilibili(username, password)
		return session


'''run'''
if __name__ == '__main__':
	parser = argparse.ArgumentParser(description='下载B站指定用户的所有视频(仅支持Windows下使用)')
	parser.add_argument('--username', dest='username', help='xxx', type=str, required=True)
	parser.add_argument('--password', dest='password', help='xxxx', type=str, required=True)
	print(parser)
	args = parser.parse_args(['--password', 'xxxx','--username', 'xxx'])
	# args = parser.parse_args(['--password', 'FOO'])
	print('5')
	bili = Bilibili(args.username, args.password)
	bili.run()

把账号密码填上就行。这是我根据一个微信公众号Charles大佬的想法写的。大家可以去关注他一下。

以上就是python 爬取B站原视频的实例代码的详细内容,更多关于python 爬取B站原视频的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python通过pil为png图片填充上背景颜色的方法
Mar 17 Python
Python判断一个文件夹内哪些文件是图片的实例
Dec 07 Python
python使用mitmproxy抓取浏览器请求的方法
Jul 02 Python
pytorch 在网络中添加可训练参数,修改预训练权重文件的方法
Aug 17 Python
nginx+uwsgi+django环境搭建的方法步骤
Nov 25 Python
解决Tensorboard可视化错误:不显示数据 No scalar data was found
Feb 15 Python
python的dict判断key是否存在的方法
Dec 09 Python
浅谈pytorch中stack和cat的及to_tensor的坑
May 20 Python
Pytorch中的学习率衰减及其用法详解
Jun 05 Python
Python虚拟环境virtualenv是如何使用的
Jun 20 Python
Django Paginator分页器的使用示例
Jun 23 Python
python代码实现扫码关注公众号登录的实战
Nov 01 Python
利用Python实现Json序列化库的方法步骤
Sep 09 #Python
python之语音识别speech模块
Sep 09 #Python
python speech模块的使用方法
Sep 09 #Python
python计算auc的方法
Sep 09 #Python
详解anaconda离线安装pytorchGPU版
Sep 08 #Python
python如何将图片转换素描画
Sep 08 #Python
Python自动化之UnitTest框架实战记录
Sep 08 #Python
You might like
php array的学习笔记
2012/05/16 PHP
PHP文件操作详解
2016/12/30 PHP
[原创]PHP正则匹配中英文、数字及下划线的方法【用户名验证】
2017/08/01 PHP
JavaScript 学习笔记(九)call和apply方法
2010/01/11 Javascript
js 纯数字不重复排列的另类方法
2010/07/17 Javascript
基于jquery的bankInput银行卡账号格式化
2012/08/22 Javascript
Extjs4 GridPanel 的几种样式使用介绍
2013/04/18 Javascript
js中把JSON字符串转换成JSON对象最好的方法
2014/03/21 Javascript
ExtJS4 表格的嵌套 rowExpander应用
2014/05/02 Javascript
理解JS绑定事件
2016/01/19 Javascript
纯js模仿windows系统日历
2017/02/04 Javascript
Bootstrap 3浏览器兼容性问题及解决方案
2017/04/11 Javascript
原生JS实现移动端web轮播图详解(结合Tween算法造轮子)
2017/09/10 Javascript
Nodejs中使用phantom将html转为pdf或图片格式的方法
2017/09/18 NodeJs
AngularJS与BootStrap模仿百度分页的示例代码
2018/05/23 Javascript
基于Vue自定义指令实现按钮级权限控制思路详解
2018/05/23 Javascript
laydate如何根据开始时间或者结束时间限制范围
2018/11/15 Javascript
JavaScript的级联函数用法简单示例【链式调用】
2019/03/26 Javascript
详解vuejs中执行npm run dev出现页面cannot GET/问题
2020/04/26 Javascript
vue:el-input输入时限制输入的类型操作
2020/08/05 Javascript
再也不怕 JavaScript 报错了,怎么看怎么处理都在这儿
2020/12/09 Javascript
python求pi的方法
2014/10/08 Python
python多进程提取处理大量文本的关键词方法
2018/06/05 Python
python实现求两个字符串的最长公共子串方法
2018/07/20 Python
python爬虫之快速对js内容进行破解
2019/07/09 Python
美国东北部户外服装和设备零售商:Eastern Mountain Sports
2016/10/05 全球购物
上海微创软件面试题
2012/06/14 面试题
医科大学毕业生自荐信
2014/02/03 职场文书
公司年会策划方案
2014/05/17 职场文书
农村优秀教师事迹材料
2014/08/27 职场文书
2015年妇委会工作总结
2015/05/22 职场文书
公司年会开场白
2015/06/01 职场文书
Python机器学习算法之决策树算法的实现与优缺点
2021/05/13 Python
Python实战之大鱼吃小鱼游戏的实现
2022/04/01 Python
Win11快速关闭所有广告推荐
2022/04/19 数码科技
Echarts如何重新渲染实例详解
2022/05/30 Javascript