def get_album_list(self, cookie=None): # 检验必要的参数 if self.uid is None: raise Util.ParameterError('缺少获取视频列表的必要参数') # 发送网络请求 http_request = { 'info_obj': Util.USER_VIDEO, 'params': { 'mid': str(self.uid), 'pagesize': 30, 'tid': 0, 'page': 1, 'order': 'pubdate' }, 'cookie': cookie } album_list = [] while True: json_data = Util.http_get(**http_request) # 循环获取列表 album_list.extend( [Video.Album(av['aid']) for av in json_data['data']['vlist']]) if len(album_list) < int(json_data['data']['count']): http_request['params']['page'] += 1 else: break # 返回视频列表 return album_list
def get_album_list(self, cookie=None): # 检验必要的参数 if self.uid is None or self.cid is None: raise Util.ParameterError('缺少获取频道列表的必要参数') # 发送网络请求 http_request = { 'info_obj': Util.CHANNEL, 'params': { 'mid': str(self.uid), 'cid': str(self.cid), 'pn': 1, # 当前页码下标 'ps': 30, # 每页视频数量 'order': 0 # 默认排序 }, 'cookie': cookie } album_list = [] while True: json_data = Util.http_get(**http_request) # 修改对象信息 self.name = json_data['data']['list']['name'] self.cover = json_data['data']['list']['cover'] self.count = str(json_data['data']['list']['count']) # 循环获取列表 album_list.extend([Video.Album(av['aid']) for av in json_data['data']['list']['archives']]) if len(album_list) < int(json_data['data']['page']['count']): http_request['params']['pn'] += 1 else: break return album_list
def sync(self, cookie=None): # 检验必要的参数 if self.uid is None: raise Util.ParameterError('缺少获取用户信息的必要参数') # 发送网络请求 http_request = { 'info_obj': Util.USER, 'params': { 'mid': str(self.uid), 'jsonp': 'jsonp' }, 'cookie': cookie } json_data = Util.http_get(**http_request) # 修改对象信息 self.name = json_data['data']['name'] self.sex = json_data['data']['sex'] self.face = json_data['data']['face'] self.sign = json_data['data']['sign'] self.level = json_data['data']['level'] self.birthday = json_data['data']['birthday'] self.title = json_data['data']['official']['title'] self.vip = bool(json_data['data']['vip']['status']) # 返回用户信息 return copy.deepcopy(vars(self))
def sync(self, cookie=None): # 检验必要的参数 if self.aid is None: raise Util.ParameterError('缺少获取视频信息的必要参数') # 发送网络请求 http_request = { 'info_obj': Util.ALBUM, 'params': { 'aid': str(self.aid) }, 'cookie': cookie } json_data = Util.http_get(**http_request) # 修改对象信息 self.num = json_data['data']['videos'] self.type = json_data['data']['tname'] self.cover = json_data['data']['pic'] self.name = json_data['data']['title'] self.time = json_data['data']['ctime'] self.desc = json_data['data']['desc'] self.view = json_data['data']['stat']['view'] self.danmu = json_data['data']['stat']['danmaku'] self.reply = json_data['data']['stat']['reply'] self.favorite = json_data['data']['stat']['favorite'] self.coin = json_data['data']['stat']['coin'] self.share = json_data['data']['stat']['share'] self.like = json_data['data']['stat']['like'] self.video_info = list() for page in json_data['data']['pages']: self.video_info.append((page['cid'], page['part'])) # 返回稿件信息 return copy.deepcopy(vars(self))
def fetch_all(self, cookie=None, name_pattern=Util.Config.SET_AS_CODE, quality=None): """ 自动获取用户与频道名下的所有视频信息 :param cookie: 权限信息 :param quality: 下载视频质量 :param name_pattern: 路径命名方式 :return: 所有视频的av号列表 """ av_list = [] self.info_list = [] # 确定对象类型 if isinstance(self.obj, Space.User): obj_code = self.obj.uid elif isinstance(self.obj, Space.Channel): obj_code = self.obj.cid else: raise Util.ParameterError('该类型对象无法自动加载') # 逐级确定储存路径 if name_pattern == Util.Config.SET_AS_NAME: self.obj.sync() obj_name = Util.legalize_name(self.obj.name) else: obj_name = obj_code album_list = self.obj.get_album_list() for album in album_list: if name_pattern == Util.Config.SET_AS_NAME: album.sync() album_name = Util.legalize_name(album.name) else: album_name = album.aid video_list = album.get_video_list() for video in video_list: video.sync(cookie, quality) if name_pattern == Util.Config.SET_AS_NAME: video_name = Util.legalize_name(video.name) else: video_name = video.aid video_name = '{}_P{}_{}'.format(video_name, video.page, video.quality[1]) self.info_list.append({ 'obj': self.obj, 'obj_name': obj_name, 'album': album, 'album_name': album_name, 'video': video, 'video_name': video_name }) av_list.append(album.aid) av_list = list(set(av_list)) return av_list
def fetch_all(self, cookie=None, name_pattern=Util.Config.SET_AS_CODE, quality=None): """ 自动获取用户与频道名下的所有视频信息 :param cookie: 权限信息 :param quality: 下载视频质量 :param name_pattern: 路径命名方式 :return: 所有视频的av号列表 """ av_list = [] self.info_list = [] # 确定对象类型 if isinstance(self.obj, Space.User): obj_code = self.obj.uid elif isinstance(self.obj, Space.Channel): obj_code = self.obj.cid else: raise Util.ParameterError('该类型对象无法自动加载') # 逐级确定储存路径 if name_pattern == Util.Config.SET_AS_CODE: obj_name = obj_code elif name_pattern == Util.Config.SET_AS_NAME: self.obj.sync() obj_name = Util.legalize_name(self.obj.name) elif name_pattern == Util.Config.SET_AS_PAGE: self.obj.sync() obj_name = Util.legalize_name(self.obj.name) else: obj_name = "unknown" album_list = self.obj.get_album_list() for album in tqdm(album_list, desc="Fetching..."): try: album.sync(cookie) except Util.RunningError: print("404 or 403 on: %s, skipped" % album.aid) continue album_name = album.album_name(name_pattern) video_list = album.get_video_list() for video in video_list: video.sync(cookie, quality) video_name = video.video_name(name_pattern) self.info_list.append({ 'obj': (obj_name, self.obj), 'album': (album_name, album), 'video': (video_name, video) }) av_list.append(album.aid) av_list = list(set(av_list)) return av_list
def sync(self, cookie=None, quality=None): # 检验必要的参数 if self.album.aid is None or self.cid is None: raise Util.ParameterError('缺少获取视频信息的必要参数') if quality is None: quality = Util.Config.Quality.V1080P60 # 发送网络请求 http_request = { 'info_obj': Util.VIDEO, 'params': { 'avid': str(self.album.aid), 'cid': str(self.cid), 'qn': quality[0], 'otype': 'json', 'fnver': 0, 'fnval': 16 }, 'cookie': cookie } json_data = Util.http_get(**http_request) # 自动识别不同的数据 self.format = json_data['data']['format'] self.length = json_data['data']['timelength'] self.quality = Util.Config.Quality.INDEX[json_data['data']['quality']] if 'dash' in json_data['data']: self.level = 'new_version' video_obj = json_data['data']['dash']['video'][0] audio_obj = json_data['data']['dash']['audio'][0] self.height = video_obj['height'] self.width = video_obj['width'] self.video = list([video_obj['baseUrl']]) self.audio = list([audio_obj['baseUrl']]) if video_obj['backup_url']: for backup in video_obj['backup_url']: self.video.append(backup) if audio_obj['backup_url']: for backup in audio_obj['backup_url']: self.video.append(backup) elif 'durl' in json_data['data']: self.level = 'old_version' video_obj = json_data['data']['durl'][-1] for item in json_data['data']['durl']: self.video.append(item['url']) #self.video = list([video_obj['url']]) if item['backup_url']: for backup in video_obj['backup_url']: self.video.append(backup) # 返回视频信息 return copy.deepcopy(vars(self))
def start(self, show_process=True, no_repeat=True): """ 开始下载任务 :param show_process: 是否显示下载进度信息 :param no_repeat: 是否重复下载 :return: 本次下载的视频所属的av号 / None """ if not os.path.exists(self.path): os.makedirs(self.path) # 创建基础路径 # 保存视频封面 if self.cover is not None and not os.path.exists(self.path + '/cover.jpg'): proxies = { 'http': Util.Config.HTTP_PROXY, 'https': Util.Config.HTTPS_PROXY } http_result = requests.get(self.cover, proxies=proxies) with open(self.path + '/cover.jpg', 'wb') as file: file.write(http_result.content) # 保存视频并转码 if no_repeat and os.path.exists(os.path.join(self.path, self.name)): return None if self.level == 'old_version': Util.aria2c_pull(self.aid, self.path, self.name + '.flv', self.video, show_process) elif self.level == 'new_version': Util.aria2c_pull(self.aid, self.path, self.name + '.aac', self.audio, show_process) Util.aria2c_pull(self.aid, self.path, self.name + '.flv', self.video, show_process) Util.ffmpeg_merge(self.path, self.name, show_process) sys.stdout.flush() return self.aid
def get_video_list(self, cookie=None): # 检验必要的参数 if self.aid is None: raise Util.ParameterError('缺少获取视频信息的必要参数') if self.video_info is None: self.sync(cookie) video_list = [] for index, info in enumerate(self.video_info): video = Video.Video(self, info[0], info[1], index + 1) video_list.append(video) return video_list
def get_video_list(self, cookie=None): # 检验必要的参数 if self.aid is None: raise Util.ParameterError('缺少获取视频信息的必要参数') if self.cid_list is None: self.sync(cookie) video_list = [] for index, cid in enumerate(self.cid_list): cv = Video.Video(self.aid, cid, self.name, index + 1) video_list.append(cv) return video_list
def __init__(self, aid=None): self.aid = Util.to_av(aid) self.num = None self.type = None self.cover = None self.name = None self.time = None self.desc = None self.view = None self.danmu = None self.reply = None self.favorite = None self.coin = None self.share = None self.like = None self.video_info = None
def album_name(self, name_pattern=Util.Config.SET_AS_CODE): """ 辅助生成稿件文件的名称 :param name_pattern: 命名模式 :return: 经过拼接的稿件文件名称 """ if name_pattern == Util.Config.SET_AS_CODE: name = self.aid elif name_pattern == Util.Config.SET_AS_NAME: name = self.name elif name_pattern == Util.Config.SET_AS_PAGE: name = self.name else: name = "unknown" return Util.legalize_name(name)
def video_name(self, name_pattern=Util.Config.SET_AS_CODE): """ 辅助生成视频文件的名称 :param name_pattern: 命名模式 :return: 经过拼接的视频文件名称 """ if name_pattern == Util.Config.SET_AS_CODE: name = self.cid elif name_pattern == Util.Config.SET_AS_NAME: name = self.album.name elif name_pattern == Util.Config.SET_AS_PAGE: name = self.name else: name = "unknown" name = Util.legalize_name(name) return "{}_P{}_{}".format(name, self.page, self.quality[1])
def get_channel_list(self, cookie=None): if self.uid is None: raise BaseException('缺少获取频道列表的必要参数') # 发送网络请求 http_request = { 'info_obj': Util.CHANNEL_LIST, 'params': { 'mid': str(self.uid), 'guest': False, 'jsonp': 'jsonp' }, 'cookie': cookie } json_data = Util.http_get(**http_request) channel_list = list( Space.Channel(self.uid, ch['cid']) for ch in json_data['data']['list']) # 返回频道列表 return channel_list
def set_ratio(self, ratio): if ~isinstance(ratio, list): raise Util.ParameterError('参数类型异常') self.ratio = ratio
def set_page(self, page): if ~isinstance(page, list): raise Util.ParameterError('参数类型异常') self.page = page
def set_width(self, width): if ~isinstance(width, list): raise Util.ParameterError('参数类型异常') self.width = width
def set_height(self, height): if ~isinstance(height, list): raise Util.ParameterError('参数类型异常') self.height = height
def set_length(self, length): if ~isinstance(length, list): raise Util.ParameterError('参数类型异常') self.length = length
def set_quality(self, quality): if ~isinstance(quality, list): raise Util.ParameterError('参数类型异常') self.quality = quality
def set_album(self, aid): self.aid = Util.to_av(aid)
def set_by_url(self, url): input_url = parse.urlparse(url) bid = re.match('/video/(BV[0-9a-zA-Z]+|av[0-9]+)', input_url.path).group(1) self.aid = Util.to_av(bid)