Skip to content

Commit

Permalink
Merge pull request nICEnnnnnnnLee#193 from nICEnnnnnnnLee/dev
Browse files Browse the repository at this point in the history
V6.31 Update
  • Loading branch information
nICEnnnnnnnLee authored May 8, 2024
2 parents 6059e9e + 965e4f0 commit d0ae719
Show file tree
Hide file tree
Showing 12 changed files with 115 additions and 17 deletions.
13 changes: 6 additions & 7 deletions .github/release.info
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
* 新增: 添加功能,可以周期性地进行“一键下载”,并通报结果。
* 优化: 现在按平台和架构编译了四个版本ffmpeg,缺省时符合条件的会提示进行下载:`win_amd64`、`linux_amd64`、`win_arm64`、`linux_arm64`
* 优化: 现在补充完善了浏览器指纹等方面的cookie,期望是预防风控[#177](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/177), [#180](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/180)
+ 因为尚不清楚相关机制,目前`通过API上传指纹`这一动作只在`刷新cookie`时才会进行。在遇到风控时,不妨先试一试菜单栏里的`刷新cookie`选项。
+ 现在最好不要随意修改配置的UA,如果必要,需要在隐私模式下抓取cookie并抓包相应API的payload。详见配置页。
* 修复: [#182](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/182) 考虑在`UP主所有视频`类型的链接解析时,keyword中含有空格的情况。
* 删除: 移除解析分页链接时`promptAll`模式相关代码。
* 新增: 重命名文件失败时,尝试添加序号继续重命名。[#185](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/185)
+ 目的地址存在文件时,会在约定的名称末尾尝试添加`(01)、(02)...`这样的序号
+ 通过配置`bilibili.name.autoNumber`可以开启/关闭该功能
* 优化: 查询UP主所有链接时添加`dm_img`系列参数,防止返回352。(不登录也能用了)
* 修复: 查询UP主所有链接时相关请求添加`referer`,防止返回412。[#192](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/192)
* 其它常规优化,详见[V6.30...V6.31](https://github.com/nICEnnnnnnnLee/BilibiliDown/compare/V6.30...V6.31)
<hr/>

如果你是Win64用户,且没有java环境,请下载附件`*.win_x64_jre11.release.zip`
2 changes: 1 addition & 1 deletion .github/workflows/document.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
run: npm run docs:build

- name: Deploy
uses: peaceiris/actions-gh-pages@main
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/.vitepress/dist
Expand Down
8 changes: 8 additions & 0 deletions UPDATE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
## UPDATE
* V6.31 `2024-05-08`
* 新增: 重命名文件失败时,尝试添加序号继续重命名。[#185](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/185)
+ 目的地址存在文件时,会在约定的名称末尾尝试添加`(01)、(02)...`这样的序号
+ 通过配置`bilibili.name.autoNumber`可以开启/关闭该功能
* 优化: 查询UP主所有链接时添加`dm_img`系列参数,防止返回352。(不登录也能用了)
* 修复: 查询UP主所有链接时相关请求添加`referer`,防止返回412。[#192](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/192)
* 其它常规优化,详见[V6.30...V6.31](https://github.com/nICEnnnnnnnLee/BilibiliDown/compare/V6.30...V6.31)

* V6.30 `2024-02-23`
* 新增: 添加功能,可以周期性地进行“一键下载”,并通报结果。
* 优化: 现在按平台和架构编译了四个版本ffmpeg,缺省时符合条件的会提示进行下载:`win_amd64``linux_amd64``win_arm64``linux_arm64`
Expand Down
67 changes: 65 additions & 2 deletions src/nicelee/bilibili/API.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -235,7 +236,12 @@ public static void uploadFingerprint() {
String b_lsid = ResourcesUtil.randomHex(8) + "_" + Long.toHexString(currentTime).toUpperCase();
HttpCookies.set("b_lsid", b_lsid);
}

// 设置 browser_resolution
Matcher mResolution = pResolution.matcher(Global.userAgentPayload);
if(mResolution.find()) {
String resolution = String.format("%s-%s", mResolution.group(1), mResolution.group(2));
HttpCookies.set("browser_resolution", resolution);
}
// TODO payload
String payload = Global.userAgentPayload;
payload = payload.replaceFirst("\"5062\":\"[^\"]+\"", "\"5062\":\"" + currentTime + "\"");
Expand Down Expand Up @@ -293,10 +299,67 @@ public static String genNewFingerprint() {
String buvid_fp = Global.userAgentFingerprint;
kvMap.put("buvid_fp", buvid_fp);
kvMap.put("fingerprint", buvid_fp);
// 获取 browser_resolution
Matcher mResolution = pResolution.matcher(Global.userAgentPayload);
mResolution.find();
String resolution = String.format("%s-%s", mResolution.group(1), mResolution.group(2));
kvMap.put("browser_resolution", resolution);
return HttpCookies.map2CookieStr(kvMap);
} catch (IOException e) {
e.printStackTrace();
}
return "";
}

static String b64Sub2(String data) {
try {
String result = new String(Base64.getEncoder().encode(data.getBytes("UTF-8")), "UTF-8");
result = result.substring(0, result.length() - 2);
return result;
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}

static Random random = new Random();

static String f114(int a, int b) {
int t = random.nextInt(114);
return String.format("[%d,%d,%d]", 2 * a + 2 * b + 3 * t, 4 * a - b + t, t);
}

static String f514(int a, int b) {
int t = random.nextInt(514);
return String.format("[%d,%d,%d]", 3 * a + 2 * b + t, 4 * a - 4 * b + 2 * t, t);
}

static Pattern pWebglVersion = Pattern.compile("\"webgl version:([^\"]+)\"");
static Pattern pResolution = Pattern.compile("\"6e7c\":\"(\\d+)x(\\d+)\"");
static Pattern pWebglUnRenderer = Pattern.compile("\"webgl unmasked renderer:([^\"]+)\"");
static Pattern pWebglUnVendor = Pattern.compile("\"webgl unmasked vendor:([^\"]+)\"");

public static String genDmImgParams() {
// TODO dm_img_list 浏览器加载完毕后,如果没什么动作,请求始终为[]
String dm_img_list = "[]";
// dm_img_str
Matcher mWebglVersion = pWebglVersion.matcher(Global.userAgentPayload);
mWebglVersion.find();
String dm_img_str = b64Sub2(mWebglVersion.group(1).trim());
// TODO dm_img_inter 浏览器加载完毕后第一个请求始终为
// {"ds":[],"wh":f114(width, height),"of":f514(0,0)}
Matcher mResolution = pResolution.matcher(Global.userAgentPayload);
mResolution.find();
String _wh = f114(Integer.parseInt(mResolution.group(1)), Integer.parseInt(mResolution.group(2)));
String _of = f514(0, 0);
String dm_img_inter = String.format("{\"ds\":[],\"wh\":%s,\"of\":%s}", _wh, _of);
// dm_cover_img_str
Matcher mWebglUnRenderer = pWebglUnRenderer.matcher(Global.userAgentPayload);
mWebglUnRenderer.find();
Matcher mWebglUnVendor = pWebglUnVendor.matcher(Global.userAgentPayload);
mWebglUnVendor.find();
String dm_cover_img_str = mWebglUnRenderer.group(1).trim() + mWebglUnVendor.group(1).trim();
dm_cover_img_str = b64Sub2(dm_cover_img_str);
return String.format("&dm_img_list=%s&dm_img_str=%s&dm_img_inter=%s&dm_cover_img_str=%s", dm_img_list,
dm_img_str, dm_img_inter, dm_cover_img_str);
}
}
1 change: 1 addition & 0 deletions src/nicelee/bilibili/downloaders/Downloader.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public boolean download(String url, String avId, int qn, int page) {
try {
this.downloader = downloader.getClass().newInstance();
this.downloader.matches(url);
break;
} catch (InstantiationException | IllegalAccessException e) {
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ public VideoInfo result(int pageSize, int page, Object... obj) {
try {
// 先获取合集信息
HashMap<String, String> headers = new HttpHeaders().getCommonHeaders("api.bilibili.com");
HashMap<String, String> headersRefer = new HashMap<>(headers);
headersRefer.put("Referer", "https://space.bilibili.com/");
headersRefer.put("Origin", "https://space.bilibili.com/");
if (pageQueryResult.getVideoName() == null) {
String url = "https://api.bilibili.com/x/v1/medialist/info?type=1&tid=0&biz_id=" + spaceID;
Logger.println(url);
Expand All @@ -162,10 +165,10 @@ public VideoInfo result(int pageSize, int page, Object... obj) {
break;
}
}
String firstOid = position2Oid((page - 1) * pageSize + 1, headers, sortFieldParam);
String firstOid = position2Oid((page - 1) * pageSize + 1, headersRefer, sortFieldParam);
if(firstOid.equals("end"))
return pageQueryResult;
String lastOidPlus1 = position2Oid(page * pageSize + 1, headers, sortFieldParam);
String lastOidPlus1 = position2Oid(page * pageSize + 1, headersRefer, sortFieldParam);

// 根据oid查询分页的详细信息
String urlFormat = "https://api.bilibili.com/x/v2/medialist/resource/list?type=1&oid=%s&otype=2&biz_id=%s&bvid=&with_current=%s&mobi_app=web&ps=%d&direction=false&sort_field=%d&tid=%s&desc=true";
Expand Down Expand Up @@ -267,6 +270,7 @@ private String position2Oid(int pageNumber, HashMap<String, String> headers, Str
// String urlFormat = "https://api.bilibili.com/x/space/arc/search?mid=%s&ps=%d&tid=%s&pn=%d&keyword=&order=%s&jsonp=jsonp";
String urlFormat = "https://api.bilibili.com/x/space/wbi/arc/search?mid=%s&ps=%d&tid=%s&special_type=&pn=%d&keyword=&order=%s&platform=web"; // &web_location=1550101&order_avoided=true
String url = String.format(urlFormat, spaceID, 1, params.get("tid"), pageNumber, sortFieldParam);
url += API.genDmImgParams();
url = API.encWbi(url);
String json = util.getContent(url, headers, HttpCookies.globalCookiesWithFingerprint());
Logger.println(url);
Expand Down
6 changes: 5 additions & 1 deletion src/nicelee/bilibili/parsers/impl/URL4UPAllParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,12 @@ protected boolean query(int page, int min, int max, Object... obj) {
String urlFormat = "https://api.bilibili.com/x/space/wbi/arc/search?mid=%s&ps=%d&tid=%s&pn=%d&keyword=%s&order=%s&platform=web"; // &web_location=1550101&order_avoided=true
String keyword = API.encodeURL(params.get("keyword"));
String url = String.format(urlFormat, spaceID, API_PMAX, params.get("tid"), page, keyword, params.get("order"));
url += API.genDmImgParams();
url = API.encWbi(url);
String json = util.getContent(url, new HttpHeaders().getCommonHeaders("api.bilibili.com"), HttpCookies.globalCookiesWithFingerprint());
HashMap<String, String> headersRefer = new HttpHeaders().getCommonHeaders("api.bilibili.com");
headersRefer.put("Referer", "https://space.bilibili.com/");
headersRefer.put("Origin", "https://space.bilibili.com/");
String json = util.getContent(url, headersRefer, HttpCookies.globalCookiesWithFingerprint());
Logger.println(url);
Logger.println(json);
JSONObject jobj = new JSONObject(json);
Expand Down
12 changes: 11 additions & 1 deletion src/nicelee/bilibili/util/CmdUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,17 @@ public synchronized static void convertOrAppendCmdToRenameBat(final String avid_
File folder = file.getParentFile();
if (!folder.exists())
folder.mkdirs();
originFile.renameTo(file);
if((!originFile.renameTo(file)) && Global.autoNumberWhenFileExists) {// 如果不成功,大概率是文件名重复,在后面加上序号,类似于(01)
for(int i = 1; i < 100; i++) {
File f = new File(Global.savePath,
String.format("%s(%02d)%s", formattedTitle, i, tail));
Logger.println(f.getAbsolutePath());
if(!f.exists()) {
originFile.renameTo(f);
break;
}
}
}
} else {
File f = new File(Global.savePath, "rename.bat");
boolean isExist = f.exists();
Expand Down
2 changes: 2 additions & 0 deletions src/nicelee/bilibili/util/HttpCookies.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ public static boolean set(String key, String value) {
return true;
}
}
HttpCookie cCookie = new HttpCookie(key, value);
globalCookiesWithFingerprint().add(cCookie);
return false;
}
}
4 changes: 3 additions & 1 deletion src/nicelee/ui/Global.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

public class Global {
// 界面显示相关
@Config(key = "bilibili.version", defaultValue = "v6.30", warning = false)
@Config(key = "bilibili.version", defaultValue = "v6.31", warning = false)
public static String version; // 一般情况下,我们不会设置这个标签,这个用于测试
@Config(key = "bilibili.theme", note = "界面主题", defaultValue = "true", eq_true = "default", valids = { "default", "system" })
public static boolean themeDefault;
Expand Down Expand Up @@ -109,6 +109,8 @@ public class Global {
public static String cTimeFormat;
@Config(key = "bilibili.name.doAfterComplete", note = "下载完成后自动重命名", defaultValue = "true", valids = { "true", "false" })
public static boolean doRenameAfterComplete = true;
@Config(key = "bilibili.name.autoNumber", note = "遇到同名文件自动添加序号", defaultValue = "true", valids = { "true", "false" })
public static boolean autoNumberWhenFileExists = true;
@Config(key = "bilibili.repo.definitionStrictMode", note = "是否将同一视频不同清晰度看作不同任务", defaultValue = "false", eq_true = "on", valids = { "on",
"off" }) /* 存在某一清晰度后, 在下载另一种清晰度时是否判断已完成 */
public static boolean repoInDefinitionStrictMode; //
Expand Down
7 changes: 5 additions & 2 deletions src/nicelee/ui/thread/DownloadRunnable.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public class DownloadRunnable implements Runnable {
String record;
int qn; //想要申请的链接视频质量

final static String MSG_VIDEO_DOWNLOADED = "您已经下载过视频 %s\n如果想继续下载:\n"
+ "临时方案: 右上角[配置] -> [下载前先查询记录?] -> [不查询]\n"
+ "持久化方案: 在配置页搜索并修改配置 bilibili.repo";
// public DownloadRunnable(ClipInfo clip, int qn) {
// this.displayName = clip.getAvTitle() + "p" + clip.getRemark() + "-" +clip.getTitle();
// this.clip = clip;
Expand Down Expand Up @@ -75,7 +78,7 @@ public void download() {
}
//判断是否已经下载过
if(Global.useRepo && RepoUtil.isInRepo(record)) {
JOptionPaneManager.showMsgWithNewThread("提示", "您已经下载过视频" + record);
JOptionPaneManager.showMsgWithNewThread("提示", String.format(MSG_VIDEO_DOWNLOADED, record));
System.out.println("已经下载过 " + record);
BatchDownloadRbyRThread.taskFail(clip, "already downloaded");
return;
Expand Down Expand Up @@ -107,7 +110,7 @@ public void download() {
//如果清晰度不符合预期,再判断一次记录
//判断是否已经下载过
if (qn != realQN && Global.useRepo && RepoUtil.isInRepo(record)) {
JOptionPaneManager.showMsgWithNewThread("提示", "您已经下载过视频" + record);
JOptionPaneManager.showMsgWithNewThread("提示", String.format(MSG_VIDEO_DOWNLOADED, record));
System.out.println("已经下载过 " + record);
BatchDownloadRbyRThread.taskFail(clip, "already downloaded2");
return;
Expand Down
2 changes: 2 additions & 0 deletions src/resources/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ bilibili.name.format = (:listName listName-)avTitle-pAv2-qn
# 下载完成后是否马上重命名
# 若为false, 那么会追加到重命名文件, 可以人工运行rename.bat 重命名
bilibili.name.doAfterComplete = true
# 遇到同名文件自动添加序号 (01)、(02)...
bilibili.name.autoNumber = true
# 下载完成后是否尝试给相关作品点赞👍(已经点赞的不会取消)
bilibili.download.thumbUp = false
# 全部任务完成后是否播放提示音
Expand Down

0 comments on commit d0ae719

Please sign in to comment.