Skip to content

Commit 4d79210

Browse files
committed
Update to 1.3.0
1 parent 6a6c9c1 commit 4d79210

File tree

11 files changed

+276
-77
lines changed

11 files changed

+276
-77
lines changed

ExampleInput.txt

-7
This file was deleted.

ExampleLog.txt

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
请输入一个 AV 号或 BV 号:
2+
BV1pK4y1N7gw
3+
成功使用保存的 TOKEN 登录
4+
ID:Naptie
5+
UID:474403243
6+
7+
登录方式:
8+
1. WEB 端二维码登录
9+
2. TV 端二维码登录
10+
3. 输入 SESSDATA 登录
11+
4. 跳过登录
12+
请选择登录方式(输入 1~4 之间的整数):
13+
1
14+
15+
请使用B站手机客户端扫描窗口中显示的二维码并确认登录
16+
登录成功
17+
本次 WEB 端二维码登录所用 UA 的浏览器为 Chrome,请于登陆操作通知中核实对照
18+
请决定是否保存该 SESSDATA(输入“Y”代表是,输入“N”代表否):
19+
y
20+
已保存 SESSDATA
21+
22+
正在获取稿件信息······
23+
24+
标题:一位高中生沉迷于写漏洞,这是他的心路变化历程
25+
UP主:Naptie
26+
时长:03:24
27+
播放数:1,462
28+
弹幕数:5
29+
获赞数:68
30+
投币数:26
31+
收藏数:21
32+
33+
正在获取清晰度信息······
34+
35+
清晰度:
36+
1. 超清 4K
37+
2. 高清 1080P60
38+
3. 高清 1080P
39+
4. 高清 720P60
40+
5. 清晰 480P
41+
6. 流畅 360P
42+
请选择清晰度(输入 1~6 之间的整数):
43+
1
44+
45+
下载选项:
46+
1. 视频+音频(合并需要 FFmpeg)
47+
2. 仅视频
48+
3. 仅音频
49+
请选择下载选项(输入 1~3 之间的整数):
50+
1
51+
52+
成功获取 超清 4K 的视频下载地址:https://upos-sz-mirrorkodo.bilivideo.com/upgcxcode/76/87/332188776/332188776-1-30120.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1621446080&gen=playurlv2&os=kodobv&oi=659485736&trid=165fba752b604ad885b7ff5bc2e4166au&platform=pc&upsig=c2ed28c1a38900571c9ca4ec06f0d808&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=474403243&bvc=vod&orderid=0,3&agrr=1&logo=80000000
53+
54+
成功获取音频下载地址:https://upos-sz-mirrorkodo.bilivideo.com/upgcxcode/76/87/332188776/332188776-1-30280.m4s?e=ig8euxZM2rNcNbdlhoNvNC8BqJIzNbfqXBvEqxTEto8BTrNvN0GvT90W5JZMkX_YN0MvXg8gNEV4NC8xNEV4N03eN0B5tZlqNxTEto8BTrNvNeZVuJ10Kj_g2UB02J0mN0B5tZlqNCNEto8BTrNvNC7MTX502C8f2jmMQJ6mqF2fka1mqx6gqj0eN0B599M=&uipk=5&nbs=1&deadline=1621446080&gen=playurlv2&os=kodobv&oi=659485736&trid=165fba752b604ad885b7ff5bc2e4166au&platform=pc&upsig=c010b66df29664f0dc31b407aa4f1969&uparams=e,uipk,nbs,deadline,gen,os,oi,trid,platform&mid=474403243&bvc=vod&orderid=0,3&agrr=1&logo=80000000
55+
56+
正在下载视频至 E:\Downloads\tmpVid.mp4
57+
进度:100.00%(203.324MB / 203.324MB);速度:0.919MB/s;用时:221.259s
58+
视频下载完毕
59+
60+
正在下载音频至 E:\Downloads\tmpAud.aac
61+
进度:100.00%(7.740MB / 7.740MB);速度:0.988MB/s;用时:7.835s
62+
音频下载完毕
63+
64+
正在合并至 E:\Downloads\一位高中生沉迷于写漏洞,这是他的心路变化历程.mp4
65+
合并完毕
66+
67+
程序运行结束;总运行时间:04:32.835

README.md

+28-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<!--suppress HtmlDeprecatedAttribute -->
22
<h1 align="center">BiliDownload</h1>
33

4-
![](https://github.com/Naptie/BiliDownload/blob/main/bin/logo-small.png)
4+
<p align="center">
5+
<img src="bin/logo-small.png" alt="">
6+
</p>
57

68
<h3 align="center">本项目通过调用B站 WEB 端与 TV 端的 API 实现了对B站视频的下载。</h3>
79
<p align="center">
@@ -45,8 +47,8 @@
4547

4648
1. **[可跳过]** 使用 `mvn clean package` 命令进行编译。
4749

48-
2. 输入 `java -jar bili-download-1.2.0-jar-with-dependencies.jar`,进入程序。若您希望启用 debug 模式,请在参数中添加 `debug`
49-
,即输入 `java -jar bili-download-1.2.0-jar-with-dependencies.jar debug`,这将显示一些调试信息。
50+
2. 输入 `java -jar bili-download-1.3.0-jar-with-dependencies.jar`,进入程序。若您希望启用 debug 模式,请在参数中添加 `debug`
51+
,即输入 `java -jar bili-download-1.3.0-jar-with-dependencies.jar debug`,这将显示一些调试信息。
5052

5153
3. 输入一个 AV 号或 BV 号。
5254

@@ -97,16 +99,34 @@
9799

98100
5. 对于上述使用流程中的所有输入,均可写入工作目录下的 `Input.txt` 中。
99101

100-
6. **[BUG]** 在某些控制台中,实时更新的下载详细信息会无法正常显示。例如:缺少 `进度:`;下载完毕后速度信息的一部分被用时信息遮盖
102+
6. **[BUG]** 在某些控制台中,实时更新的下载详细信息会无法正常显示。例如下载完毕后速度信息的一部分被用时信息遮盖
101103

102-
7. **[优化项]** 程序目前只支持单线程下载,可考虑添加多线程下载功能。如果程序的下载速度过慢,请自行访问下载地址进行下载
104+
7. **[BUG]** 程序在进行多线程下载时会出现 `java.io.IOException: Server returned HTTP response code: 416 for URL: ...` 等错误
103105

104-
8. 本程序仍然存在诸如下载速度慢等问题,欢迎大家多多投递 issue 与 pull request。
106+
8. 本程序仍然存在诸多问题,欢迎大家多多投递 issue 与 pull request。
105107

106108
---
107109

108110
# ChangeLog
109111

112+
## 1.3.0
113+
114+
### 1. 加速了下载
115+
116+
使用32个线程进行视频与音频的下载,最高速度可达 23MB/s。
117+
118+
### 2. 添加了 LOGO
119+
120+
现在,BiliDownload 也有了自己的 LOGO。原图存于 `bin/logo.png`
121+
122+
### 3. 添加了 WEB 端二维码登录时浏览器标识的提示信息
123+
124+
选择 `WEB 端二维码登录` 并触发程序进行验证后,程序会提示当前所用的浏览器标识,便于与B站的登录操作通知中的 `设备/平台` 信息进行核实对照。
125+
126+
### 4. 解决了文件路径不能含有空格的问题
127+
128+
现已支持输入的文件路径中含有空格。
129+
110130
## 1.2.0
111131

112132
### 添加了 TV 端二维码登录功能
@@ -161,7 +181,7 @@
161181

162182
这直接导致了程序在访问 URL 时选择了位于1081端口的代理。因此,如果这个端口没有代理,就会提示拒绝连接。
163183

164-
![](https://github.com/Naptie/BiliDownload/blob/main/bin/your_debugging.jpg)
184+
<img src="bin/your_debugging.jpg" alt="">
165185

166186
### 2. 添加了 Debug 模式
167187

@@ -320,4 +340,4 @@ Fiddler 还是带来了希望。
320340

321341
**将被无限重生。**
322342

323-
![](https://github.com/Naptie/BiliDownload/blob/main/bin/example.png)
343+
<img src="bin/example.png" alt="">

pom.xml

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>me.naptie</groupId>
88
<artifactId>bili-download</artifactId>
9-
<version>1.2.0</version>
9+
<version>1.3.0</version>
1010
<build>
1111
<plugins>
1212
<plugin>
@@ -94,6 +94,11 @@
9494
<artifactId>javase</artifactId>
9595
<version>3.4.1</version>
9696
</dependency>
97+
<dependency>
98+
<groupId>cz.mallat.uasparser</groupId>
99+
<artifactId>uasparser</artifactId>
100+
<version>0.6.2</version>
101+
</dependency>
97102
</dependencies>
98103

99104
</project>

src/main/java/me/naptie/bilidownload/Main.java

+48-49
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22

33
import com.alibaba.fastjson.JSONArray;
44
import com.alibaba.fastjson.JSONObject;
5+
import cz.mallat.uasparser.OnlineUpdater;
6+
import cz.mallat.uasparser.UASparser;
7+
import me.naptie.bilidownload.objects.Downloader;
58
import me.naptie.bilidownload.utils.ConfigManager;
69
import me.naptie.bilidownload.utils.HttpManager;
710
import me.naptie.bilidownload.utils.LoginManager;
811
import me.naptie.bilidownload.utils.SignUtil;
12+
import org.apache.commons.codec.digest.DigestUtils;
913

10-
import java.io.*;
11-
import java.net.MalformedURLException;
14+
import java.io.File;
15+
import java.io.FileNotFoundException;
16+
import java.io.IOException;
1217
import java.net.URL;
1318
import java.net.URLConnection;
1419
import java.text.SimpleDateFormat;
@@ -60,7 +65,7 @@ private static int inputInt() {
6065
}
6166

6267
private static String input() {
63-
String input = scanner.next();
68+
String input = scanner.nextLine();
6469
if (input.equalsIgnoreCase("*exit")) {
6570
System.out.println("\n程序运行结束;总运行时间:" + getFormattedTime(System.currentTimeMillis() - beginTime));
6671
System.exit(0);
@@ -119,6 +124,7 @@ private static String[] login() throws IOException {
119124
sessData = LoginManager.sessData;
120125
if (sessData.isEmpty()) {
121126
System.out.println("登录失败");
127+
System.out.println("本次 WEB 端二维码登录所用 UA 的浏览器为 " + (new UASparser(OnlineUpdater.getVendoredInputStream()).parse(LoginManager.userAgent)).getUaFamily() + ",请于登陆操作通知中核实对照");
122128
continue;
123129
}
124130
} else if (method == 2) {
@@ -145,6 +151,7 @@ private static String[] login() throws IOException {
145151
if (login.getJSONObject("data").getBoolean("isLogin")) {
146152
webSuccess = loginSuccess = true;
147153
System.out.println("登录成功" + (debug ? "\nID:" + login.getJSONObject("data").getString("uname") + "\nUID:" + login.getJSONObject("data").getIntValue("mid") : ""));
154+
System.out.println("本次 WEB 端二维码登录所用 UA 的浏览器为 " + (new UASparser(OnlineUpdater.getVendoredInputStream()).parse(LoginManager.userAgent)).getUaFamily() + ",请于登录操作通知中核实对照");
148155
if (hint) System.out.println("请决定是否保存该 SESSDATA(输入“Y”代表是,输入“N”代表否):");
149156
if (input().equalsIgnoreCase("Y")) {
150157
if (!config.exists()) config.createNewFile();
@@ -403,8 +410,9 @@ private static void download(Object[] details, String[] path) throws IOException
403410
}
404411
String audioDownloadUrl = getAudioDownload(videoWeb);
405412
System.out.println("\n成功获取音频下载地址:" + audioDownloadUrl);
406-
File video = ffmpegSuccess == -1 ? new File(path[0], path[1] + ".mp4") : new File(path[0], "tmpVid.mp4");
407-
File audio = ffmpegSuccess == -1 ? new File(path[0], path[1] + ".aac") : new File(path[0], "tmpAud.aac");
413+
String md5 = DigestUtils.md5Hex(path[1] + System.currentTimeMillis());
414+
File video = ffmpegSuccess == -1 ? new File(path[0], path[1] + ".mp4") : new File(path[0], "tmpVid_" + md5 + ".mp4");
415+
File audio = ffmpegSuccess == -1 ? new File(path[0], path[1] + ".aac") : new File(path[0], "tmpAud_" + md5 + ".aac");
408416
System.out.println("\n正在下载视频至 " + video.getAbsolutePath());
409417
long lenVid = downloadFromUrl(videoDownloadUrl, video.getAbsolutePath());
410418
videoSuccess = video.length() == lenVid;
@@ -423,6 +431,8 @@ private static void download(Object[] details, String[] path) throws IOException
423431
} else {
424432
System.out.println("合并失败");
425433
}
434+
} else {
435+
System.out.println("\n合并失败");
426436
}
427437
break;
428438
}
@@ -557,53 +567,42 @@ private static String watermark(boolean availability) {
557567
else return "无水印";
558568
}
559569

560-
private static long downloadFromUrl(String address, String path) {
561-
long beginTime = System.currentTimeMillis();
562-
int byteRead;
563-
URL url;
564-
try {
565-
url = new URL(address);
566-
} catch (MalformedURLException e1) {
567-
e1.printStackTrace();
570+
private static long downloadFromUrl(String address, String path) throws IOException {
571+
Downloader downloader = new Downloader(address, path);
572+
URLConnection request = (new URL(address)).openConnection();
573+
request.setRequestProperty("Referer", "https://www.bilibili.com");
574+
long totalLen = request.getContentLengthLong();
575+
long result = downloader.download(totalLen);
576+
double total = totalLen / 1024.0 / 1024.0;
577+
System.out.println("文件大小:" + String.format("%,.3f", total) + "MB");
578+
if (result == -1) {
579+
System.out.println("磁盘空间不足");
568580
return -1;
569581
}
570-
try {
571-
URLConnection request = url.openConnection();
572-
request.setRequestProperty("Referer", "https://www.bilibili.com");
573-
InputStream inStream = request.getInputStream();
574-
FileOutputStream fs = new FileOutputStream(path);
575-
576-
byte[] buffer = new byte[1024];
577-
StringBuilder progress = new StringBuilder();
578-
double total = request.getContentLengthLong() / 1024.0 / 1024.0;
579-
System.out.print("进度:");
580-
while ((byteRead = inStream.read(buffer)) != -1) {
581-
fs.write(buffer, 0, byteRead);
582-
int lastByteLength = progress.toString().getBytes().length;
583-
int lastLength = progress.length();
584-
if (progress.length() > 0) {
585-
for (int i = 0; i < lastByteLength; i++)
586-
System.out.print("\b");
587-
}
588-
double downloaded = fs.getChannel().size() / 1024.0 / 1024.0;
589-
double speed = ((System.currentTimeMillis() - beginTime) / 1000.0 == 0) ? 0 : downloaded / ((System.currentTimeMillis() - beginTime) / 1000.0);
590-
progress = new StringBuilder(String.format("%.2f", (fs.getChannel().size() * 100.0 / request.getContentLengthLong())) + "%(" + String.format("%,.3f", downloaded) + "MB / " + String.format("%,.3f", total) + "MB);速度:" + String.format("%,.3f", speed) + "MB/s;剩余时间:" + String.format("%,.3f", (total - downloaded) / speed) + "s");
591-
for (int i = 0; i <= lastLength - progress.length(); i++)
592-
progress.append(" ");
593-
System.out.print(progress);
582+
StringBuilder progress = new StringBuilder();
583+
long downloadedLen = downloader.getDownloaded();
584+
double downloaded, speed;
585+
while (downloadedLen != totalLen) {
586+
int lastLength = progress.length();
587+
int lastByteLength = progress.toString().getBytes().length;
588+
if (progress.length() > 0) {
589+
for (int i = 0; i < lastByteLength; i++)
590+
System.out.print("\b");
594591
}
595-
System.out.print("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
596-
String timeSpent = "用时:" + String.format("%,.3f", (System.currentTimeMillis() - beginTime) / 1000.0) + "s";
597-
System.out.print(timeSpent);
598-
for (int i = 0; i < 13 - timeSpent.length(); i++)
599-
System.out.print(" ");
600-
inStream.close();
601-
fs.close();
602-
return request.getContentLengthLong();
603-
} catch (IOException e) {
604-
e.printStackTrace();
605-
return -1;
592+
downloadedLen = downloader.getDownloaded();
593+
downloaded = downloadedLen / 1024.0 / 1024.0;
594+
speed = ((System.currentTimeMillis() - beginTime) / 1000.0 == 0) ? 0 : downloaded / ((System.currentTimeMillis() - beginTime) / 1000.0);
595+
progress = new StringBuilder("进度:" + String.format("%.2f", (downloadedLen * 100.0 / totalLen)) + "%(" + String.format("%,.3f", downloaded) + "MB / " + String.format("%,.3f", total) + "MB);速度:" + String.format("%,.3f", speed) + "MB/s;剩余时间:" + String.format("%,.3f", (total - downloaded) / speed).replace("Infinity", "∞") + "s");
596+
for (int i = 0; i <= lastLength - progress.length(); i++)
597+
progress.append(" ");
598+
System.out.print(progress);
606599
}
600+
System.out.print("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
601+
String timeSpent = "用时:" + String.format("%,.3f", (System.currentTimeMillis() - beginTime) / 1000.0) + "s";
602+
System.out.print(timeSpent);
603+
for (int i = 0; i < 13 - timeSpent.length(); i++)
604+
System.out.print(" ");
605+
return totalLen;
607606
}
608607

609-
}
608+
}

0 commit comments

Comments
 (0)