1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
| import os
import requests
import re
import json
import wx
class BilibiliDownloader(wx.Frame):
def __init__(self):
super().__init__(None, title="Bilibili 视频/音频下载器", size=(400, 400))
# 初始化界面元素
panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)
# BV ID 输入框
self.bv_id_label = wx.StaticText(panel, label="视频 BV ID:")
self.bv_id_input = wx.TextCtrl(panel)
vbox.Add(self.bv_id_label, flag=wx.TOP | wx.LEFT, border=10)
vbox.Add(self.bv_id_input, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=10)
# 音频/视频选择
self.media_choice_label = wx.StaticText(panel, label="选择下载类型:")
self.media_choice = wx.RadioBox(panel, label="下载类型", choices=["音频", "视频"], style=wx.RA_SPECIFY_ROWS)
vbox.Add(self.media_choice_label, flag=wx.TOP | wx.LEFT, border=10)
vbox.Add(self.media_choice, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=10)
# 目录选择
self.dir_label = wx.StaticText(panel, label="保存目录:")
self.dir_input = wx.TextCtrl(panel, style=wx.TE_READONLY)
self.browse_button = wx.Button(panel, label="选择目录", size=(100, 30))
vbox.Add(self.dir_label, flag=wx.TOP | wx.LEFT, border=10)
vbox.Add(self.dir_input, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=10)
vbox.Add(self.browse_button, flag=wx.ALIGN_LEFT | wx.BOTTOM, border=10)
# 下载按钮
self.download_button = wx.Button(panel, label="下载", size=(100, 30))
vbox.Add(self.download_button, flag=wx.ALL | wx.ALIGN_CENTER, border=10)
# 进度条
self.progress_bar = wx.Gauge(panel, range=100, style=wx.GA_HORIZONTAL)
vbox.Add(self.progress_bar, flag=wx.EXPAND | wx.ALL, border=10)
# 设置布局
panel.SetSizer(vbox)
# 绑定按钮事件
self.browse_button.Bind(wx.EVT_BUTTON, self.on_browse)
self.download_button.Bind(wx.EVT_BUTTON, self.on_download)
# 记住上次选择的目录
self.last_dir = wx.StandardPaths.Get().GetDocumentsDir()
self.Show()
def on_browse(self, event):
dialog = wx.DirDialog(self, "选择目录", self.last_dir)
if dialog.ShowModal() == wx.ID_OK:
self.dir_input.SetValue(dialog.GetPath())
self.last_dir = dialog.GetPath()
dialog.Destroy()
def on_download(self, event):
bv_id = self.bv_id_input.GetValue().strip()
media_type = 'audio' if self.media_choice.GetStringSelection() == "音频" else 'video'
save_dir = self.dir_input.GetValue().strip()
if not bv_id or not save_dir:
wx.MessageBox("请确保 BV ID 和保存目录都已输入", "错误", wx.OK | wx.ICON_ERROR)
return
# 下载文件并更新进度
self.download_bilibili_media(bv_id, save_dir, media_type)
def download_bilibili_media(self, bv_id, dir_path, media_type):
cookie = "buvid3=8F7865F6-456F-2DDC-0AD6-B7EA38BBC38890525infoc; b_nut=1733219390; _uuid=5533E2B1-293B-59B10-D4A6-76DC2619432420427infoc; buvid4=068192C5-543B-CE2A-E0C9-E3CDEBC3743E91165-024120309-Nficxoa62E6UeyU5C2SNm8mSEUsuV%2FLyrBvxTqOF18hHvJjkWcWuvr5wDBc4alZg; buvid_fp=20a5b8d5be257eeac5c1368d4adeea4b; header_theme_version=CLOSE; enable_web_push=DISABLE; home_feed_column=5; browser_resolution=1707-898; DedeUserID=213815864; DedeUserID__ckMd5=d5a3c935fd4c8e9c; rpdid=|(JJmYmYRmkm0J'u~JRkRR~mY; CURRENT_FNVAL=4048; CURRENT_QUALITY=64; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkyMzQzMjIsImlhdCI6MTczODk3NTA2MiwicGx0IjotMX0.VKnyld09i1ydkfGPON7wmgNsD-SCFI5EFHdhLFGdT5o; bili_ticket_expires=1739234262; b_lsid=10F783E56_194E60AEAF4; SESSDATA=00e0165f%2C1754578283%2C7d1f4%2A22CjDZmgKExa3pb9b_pXlvUX-K194lqmeyP6NiiqRUSNzW6xS4yhTzim-nym20HLbKeW0SVmp0djFWM0Y2ME1CaHdKb1lSSVVBckVPU2dJMjVhSHFLMmdMSmU0VzRaamozRXo4eE9OUzJzRXBsb1BhVXVfWGZzaWZmeFZuQzN2cjRIWXlQRU5IVDh3IIEC; bili_jct=fd16d9466e68eb0184ef44114b11d36b; sid=gt93v2im" # 请替换为你的cookie
url = f'https://www.bilibili.com/video/{bv_id}'
headers = {
"Referer": url,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Cookie": cookie
}
# 发送请求
response = requests.get(url=url, headers=headers)
html = response.text
# 解析数据: 提取视频标题
title = re.findall('title="(.*?)"', html)[0]
info = re.findall('window.__playinfo__=(.*?)</script>', html)[0]
json_data = json.loads(info)
# 获取媒体链接
if media_type == 'video':
media_url = json_data['data']['dash']['video'][0]['baseUrl']
file_extension = '.mp4'
elif media_type == 'audio':
media_url = json_data['data']['dash']['audio'][0]['baseUrl']
file_extension = '.mp3'
# 文件保存路径
file_path = os.path.join(dir_path, title + file_extension)
# 创建进度对话框
self.progress_bar.SetValue(0)
try:
media_content = requests.get(media_url, headers=headers, stream=True)
total_length = int(media_content.headers.get('content-length', 0))
with open(file_path, 'wb') as f:
for data in media_content.iter_content(chunk_size=4096):
if data:
f.write(data)
self.update_progress_bar(f.tell(), total_length)
wx.MessageBox(f"{media_type.capitalize()} '{title}' 下载成功!", "完成", wx.OK | wx.ICON_INFORMATION)
except Exception as e:
wx.MessageBox(f"下载失败: {str(e)}", "错误", wx.OK | wx.ICON_ERROR)
def update_progress_bar(self, current, total):
if total > 0:
progress = min(100, int((current / total) * 100))
self.progress_bar.SetValue(progress)
if __name__ == "__main__":
app = wx.App(False)
downloader = BilibiliDownloader()
app.MainLoop()
|