From 6d6edc9a8a71db160c6c4ed4db9b1b9f52c2ab7c Mon Sep 17 00:00:00 2001 From: ClovertaTheTrilobita Date: Mon, 3 Feb 2025 18:00:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=A0=B9=E6=8D=AEBV=E5=8F=B7?= =?UTF-8?q?=E5=8F=91=E9=80=81=E8=A7=86=E9=A2=91=E5=8A=9F=E8=83=BD=EF=BC=88?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E9=97=AE=E9=A2=98=EF=BC=89=20=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E8=B5=84=E6=BA=90=E5=87=BA=E7=8E=B0=E5=8F=91=E9=80=81?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84BUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/qq_plugins/bili_vid_search.py | 60 ++++++++++++++++- src/videos/billibili/biliVideos.py | 101 +++++++++++++++++++++++++++-- 2 files changed, 153 insertions(+), 8 deletions(-) diff --git a/src/qq_plugins/bili_vid_search.py b/src/qq_plugins/bili_vid_search.py index a5f5ead..163b5f8 100644 --- a/src/qq_plugins/bili_vid_search.py +++ b/src/qq_plugins/bili_vid_search.py @@ -1,6 +1,8 @@ # https://api.bilibili.com/x/web-interface/search/type?keyword=av28465342&search_type=video&page=1 import time +from pathlib import Path +import requests from nonebot import on_command from nonebot.rule import to_me from nonebot.adapters.qq import MessageSegment,MessageEvent, Message @@ -10,7 +12,7 @@ bili_vid = on_command("B站搜索",rule=to_me(), priority=10, block=True) @bili_vid.handle() async def get_bili_vid_info(message: MessageEvent): content = message.get_plaintext().replace("/B站搜索", "").strip() - response = biliVideos.get(content) + response = biliVideos.get_video_info(content) if response['code'] != 0: bili_vid.finish(response['message']) search_result = response['data']['result'] @@ -37,3 +39,59 @@ async def get_bili_vid_info(message: MessageEvent): time.sleep(0.5) await bili_vid.finish(f"展示{len(search_result)}条结果中的前3条。") + + +bili_bv_search = on_command("BV搜索", rule=to_me(), priority=10, block=True) +@bili_bv_search.handle() +async def get_video_file(message: MessageEvent): + keyword = message.get_plaintext().replace("/BV搜索", "").strip().split() + P_num, pages, vid_title, vid_author, vid_pic = biliVideos.get_video_pages_info(keyword[0]) + if len(keyword) == 1: + + if P_num > 1: + content = "\n标题:" + vid_title + "\nup主: " + vid_author + "\n该视频为多P播放:\n" + for page in pages: + content = content + "P" + str(page['page']) + ": " + page['part'] + "\n时长: " + str(page['duration']) + "s\n\n" + + content = content + "请选择您想播放的集数。\n决定好后麻烦回复 /BV搜索+BV号+序号 哦。\n" + await bili_bv_search.finish(content) + + elif P_num == 1: + + content = ("\n标题: " + vid_title + "\nup主: " + vid_author + "\n视频加载中~请稍后~~~") + msg = Message([ + MessageSegment.image(vid_pic), + MessageSegment.text(content), + ]) + await bili_bv_search.send(msg) + + cid = pages[0]['cid'] + video_url = biliVideos.get_video_file_url(keyword[0], cid) + biliVideos.video_download(video_url, cid) + # biliVideos.transcode_video(f"{cid}.mp4",f"{cid}-o.mp4") + await bili_bv_search.send(Message(MessageSegment.file_video(Path(f"{cid}.mp4")))) + + elif len(keyword) >= 2: + + try: + page_num = int(keyword[1]) + except: + await bili_bv_search.finish("输入有误\n请确认是否为 /BV搜索+BV号+序号(数字) ") + + if page_num > len(pages): + page_num = len(pages) + elif page_num < 1: + page_num = 1 + + content = ("\n标题: " + vid_title + "\nup主: " + vid_author + "\n正在播放共" + str(P_num) + "P中的第" + str(page_num) + "P" + "\n视频加载中~请稍后~~~") + msg = Message([ + MessageSegment.image(vid_pic), + MessageSegment.text(content), + ]) + await bili_bv_search.send(msg) + + cid = pages[page_num - 1]['cid'] + video_url = biliVideos.get_video_file_url(keyword[0], cid) + biliVideos.video_download(video_url, cid) + + await bili_bv_search.send(Message(MessageSegment.file_video(Path(f"{cid}.mp4")))) diff --git a/src/videos/billibili/biliVideos.py b/src/videos/billibili/biliVideos.py index 52eaae4..3d3ea6d 100644 --- a/src/videos/billibili/biliVideos.py +++ b/src/videos/billibili/biliVideos.py @@ -1,6 +1,7 @@ import os import pickle +import ffmpeg import requests import hashlib import urllib.parse @@ -31,9 +32,7 @@ headers = { appkey = '1d8b6e7d45233436' appsec = '560c52ccd288fed045859ed18bffd973' -params = { - 'search_type':'video' -} + def appsign(params, appkey, appsec): """为请求参数进行 APP 签名""" @@ -45,17 +44,105 @@ def appsign(params, appkey, appsec): return params -def get(keyword): +def get_video_info(keyword): + params = { + 'search_type': 'video' + } + signed_params = appsign(params, appkey, appsec) query = urllib.parse.urlencode(signed_params) url = f"https://api.bilibili.com/x/web-interface/search/type?keyword={keyword}&" + session = requests.session() session.get("https://www.bilibili.com/", headers=headers) response = session.get(url + query, headers=headers).json() # print(response['code']) return response -# print(signed_params) -# print(query) + +def get_video_info_bv(keyword): + params = { + 'bvid': keyword + } + + signed_params = appsign(params, appkey, appsec) + query = urllib.parse.urlencode(signed_params) + url = "https://api.bilibili.com/x/web-interface/view?&" + session = requests.session() + session.get("https://www.bilibili.com/", headers=headers) + response = session.get(url + query, headers=headers).json() + return response + +def get_video_pages_info(keyword): + """ + 通过BV号获取视频信息 + + :param keyword: + + :return: + len(vid_pages_info_list): 视频集数->int + vid_pages_info_list: 视频分集信息->dict + vid_title: 视频标题->str + vid_author: 视频UP主->str + vid_pic: 视频封面URL->str + """ + response = get_video_info_bv(keyword) + vid_pages_info_list = response['data']['pages'] + vid_title = response['data']['title'] + vid_author = response['data']['owner']['name'] + vid_pic = response['data']['pic'] + return len(vid_pages_info_list), vid_pages_info_list, vid_title, vid_author, vid_pic + +def get_video_pages_cid(vid_pages_info_list, num): + cid = vid_pages_info_list[num - 1]['cid'] + return cid + +def get_video_file_url(bvid, cid): + params = { + 'bvid': bvid, + 'cid': cid, + 'qn': '16', + 'platform': 'html5' + } + + signed_params = appsign(params, appkey, appsec) + query = urllib.parse.urlencode(signed_params) + url = "https://api.bilibili.com/x/player/playurl?&" + + session = requests.session() + session.get("https://www.bilibili.com/", headers=headers) + response = session.get(url + query, headers=headers).json() + + file_url = response['data']['durl'][0]['url'] + + return file_url + +def video_download(file_url, cid): + response = requests.get(file_url, headers=headers) + # 检查请求是否成功 + if response.status_code == 200: + # 将视频保存到本地文件 + with open(f'{cid}.mp4', 'wb') as file: + for chunk in response.iter_content(chunk_size=1024): + if chunk: + file.write(chunk) + print("视频下载完成") + else: + print(f"下载失败,状态码:{response.status_code}") + +def transcode_video(input_file, output_file): + try: + # 转码视频为 H.264 编码 + ( + ffmpeg.input(input_file) + .output(output_file, c="libx264", crf=23, preset="veryfast") + .run(capture_stdout=True, capture_stderr=True) + ) + print(f"视频转码完成,输出文件:{output_file}") + except ffmpeg.Error as e: + print(f"转码失败:{e.stderr.decode()}") if __name__ == "__main__": - print(get('海南某211台风过后现状111')) + print(get_video_info('海南某211台风过后现状111')) + print(get_video_file_url('BV1y7411Q7Eq', '171776208')) + + print(get_video_pages_info('BV1y7411Q7Eq'))