From b118ecd440bce83fb2ccf6972921f69e1d9857d7 Mon Sep 17 00:00:00 2001 From: lijia Date: Sun, 26 Mar 2023 09:54:36 +0800 Subject: [PATCH 01/10] fix: ss/ep/md update --- .../bilibili/parsers/impl/EPParser.java | 25 +++++++++++++------ .../bilibili/parsers/impl/SSParser.java | 23 +++++++++-------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/nicelee/bilibili/parsers/impl/EPParser.java b/src/nicelee/bilibili/parsers/impl/EPParser.java index d7a3e62f..17342e90 100644 --- a/src/nicelee/bilibili/parsers/impl/EPParser.java +++ b/src/nicelee/bilibili/parsers/impl/EPParser.java @@ -2,6 +2,7 @@ import java.util.regex.Pattern; +import org.json.JSONArray; import org.json.JSONObject; import nicelee.bilibili.annotations.Bilibili; @@ -49,14 +50,24 @@ private String EpIdToBvId(String epId) { String url = "https://www.bilibili.com/bangumi/play/" + epId; String html = util.getContent(url, headers.getCommonHeaders("www.bilibili.com")); - int begin = html.indexOf("window.__INITIAL_STATE__="); - int end = html.indexOf(";(function()", begin); - String json = html.substring(begin + 25, end); + int begin = html.indexOf("__NEXT_DATA__"); + begin = html.indexOf(">", begin); + int end = html.indexOf("", begin); + String json = html.substring(begin + 1, end); Logger.println(json); - JSONObject jObj = new JSONObject(json); - String bvid = jObj.getJSONObject("epInfo").getString("bvid"); - Logger.println("bvId为: " + bvid); - return bvid; + JSONObject jObj = new JSONObject(json).getJSONObject("props").getJSONObject("pageProps") + .getJSONObject("dehydratedState").getJSONArray("queries").getJSONObject(0) + .getJSONObject("state").getJSONObject("data").getJSONObject("mediaInfo"); + JSONArray array = jObj.getJSONArray("episodes"); + for (int i = 0; i < array.length(); i++) { + JSONObject ep = array.getJSONObject(i); + if(ep.getString("link").endsWith(epId)) { + String bvid = ep.getString("bvid"); + Logger.println("bvId为: " + bvid); + return bvid; + } + } + throw new RuntimeException("No epId found in the page"); } } diff --git a/src/nicelee/bilibili/parsers/impl/SSParser.java b/src/nicelee/bilibili/parsers/impl/SSParser.java index aef7a6f3..26ca1c0a 100644 --- a/src/nicelee/bilibili/parsers/impl/SSParser.java +++ b/src/nicelee/bilibili/parsers/impl/SSParser.java @@ -58,19 +58,22 @@ protected VideoInfo getSSDetail(String ssId, int videoFormat, boolean isGetLink) String url = "https://www.bilibili.com/bangumi/play/" + ssId; String html = util.getContent(url, headers.getCommonHeaders("www.bilibili.com")); - int begin = html.indexOf("window.__INITIAL_STATE__="); - int end = html.indexOf(";(function()", begin); - String json = html.substring(begin + 25, end); + int begin = html.indexOf("__NEXT_DATA__"); + begin = html.indexOf(">", begin); + int end = html.indexOf("", begin); + String json = html.substring(begin + 1, end); Logger.println(url); Logger.println(json); - JSONObject jObj = new JSONObject(json); - viInfo.setVideoName(jObj.getJSONObject("mediaInfo").getString("title")); - viInfo.setBrief(jObj.getJSONObject("mediaInfo").getString("evaluate")); + JSONObject jObj = new JSONObject(json).getJSONObject("props").getJSONObject("pageProps") + .getJSONObject("dehydratedState").getJSONArray("queries").getJSONObject(0) + .getJSONObject("state").getJSONObject("data").getJSONObject("mediaInfo"); + viInfo.setVideoName(jObj.getString("title")); + viInfo.setBrief(jObj.getString("evaluate")); viInfo.setAuthor("番剧"); viInfo.setAuthorId("番剧"); - viInfo.setVideoPreview("https:" + jObj.getJSONObject("mediaInfo").getString("cover")); + viInfo.setVideoPreview("https:" + jObj.getString("cover")); - JSONArray array = jObj.getJSONArray("epList"); + JSONArray array = jObj.getJSONArray("episodes"); LinkedHashMap clipMap = new LinkedHashMap(); ClipInfo lastClip = null; int[] qnListDefault = null; @@ -84,7 +87,7 @@ protected VideoInfo getSSDetail(String ssId, int videoFormat, boolean isGetLink) clip.setAvId(clipObj.getString("bvid")); clip.setcId(clipObj.getLong("cid")); //clip.setPage(Integer.parseInt(clipObj.getString("index"))); - clip.setRemark(clipObj.getInt("i") + 1); + clip.setRemark(i + 1); clip.setPicPreview("https:" +clipObj.getString("cover")); //如果和前面avid一致,那么是前者page + 1, 否则为 1 if(i > 0 && array.getJSONObject(i-1).getString("bvid").equals(clipObj.getString("bvid"))) { @@ -93,7 +96,7 @@ protected VideoInfo getSSDetail(String ssId, int videoFormat, boolean isGetLink) clip.setPage(1); } //clip.setTitle(clipObj.getString("index_title")); - clip.setTitle(clipObj.getString("longTitle")); + clip.setTitle(clipObj.getString("long_title")); clip.setUpName(viInfo.getVideoName()); clip.setUpId(ssId); From 68b4044cc28052473d10e682b4ebffedd8352f6d Mon Sep 17 00:00:00 2001 From: lijia Date: Sun, 26 Mar 2023 10:44:11 +0800 Subject: [PATCH 02/10] fix: ss/ep/md - api yes, html no --- .../bilibili/parsers/impl/EPParser.java | 19 ++++++--------- .../bilibili/parsers/impl/MdParser.java | 21 ++++++++--------- .../bilibili/parsers/impl/SSParser.java | 23 ++++++++----------- 3 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/nicelee/bilibili/parsers/impl/EPParser.java b/src/nicelee/bilibili/parsers/impl/EPParser.java index 17342e90..eadd053f 100644 --- a/src/nicelee/bilibili/parsers/impl/EPParser.java +++ b/src/nicelee/bilibili/parsers/impl/EPParser.java @@ -41,27 +41,22 @@ public VideoInfo result(String input, int videoFormat, boolean getVideoLink) { } /** - * 已知epId, 求bvId 目前没有抓到api哦... 暂时从网页里面爬 - * + * @see https://www.bilibili.com/bangumi/media/md134912 + * https://api.bilibili.com/pgc/view/web/season?ep_id=250435 * @input HttpRequestUtil util */ private String EpIdToBvId(String epId) { HttpHeaders headers = new HttpHeaders(); - String url = "https://www.bilibili.com/bangumi/play/" + epId; - String html = util.getContent(url, headers.getCommonHeaders("www.bilibili.com")); + String epIdNumber = epId.replace("ep", ""); + String url = "https://api.bilibili.com/pgc/view/web/season?ep_id=" + epIdNumber; + String json = util.getContent(url, headers.getCommonHeaders("www.bilibili.com")); - int begin = html.indexOf("__NEXT_DATA__"); - begin = html.indexOf(">", begin); - int end = html.indexOf("", begin); - String json = html.substring(begin + 1, end); Logger.println(json); - JSONObject jObj = new JSONObject(json).getJSONObject("props").getJSONObject("pageProps") - .getJSONObject("dehydratedState").getJSONArray("queries").getJSONObject(0) - .getJSONObject("state").getJSONObject("data").getJSONObject("mediaInfo"); + JSONObject jObj = new JSONObject(json).getJSONObject("result"); JSONArray array = jObj.getJSONArray("episodes"); for (int i = 0; i < array.length(); i++) { JSONObject ep = array.getJSONObject(i); - if(ep.getString("link").endsWith(epId)) { + if(epIdNumber.equals(ep.optString("id"))) { String bvid = ep.getString("bvid"); Logger.println("bvId为: " + bvid); return bvid; diff --git a/src/nicelee/bilibili/parsers/impl/MdParser.java b/src/nicelee/bilibili/parsers/impl/MdParser.java index a5e9246d..af7148a6 100644 --- a/src/nicelee/bilibili/parsers/impl/MdParser.java +++ b/src/nicelee/bilibili/parsers/impl/MdParser.java @@ -40,23 +40,22 @@ public VideoInfo result(String input, int videoFormat, boolean getVideoLink) { } /** - * 已知MdId, 求SsId 目前没有抓到api哦... 暂时从网页里面爬 - * + * @see https://www.bilibili.com/bangumi/media/md134912 + * https://api.bilibili.com/pgc/review/user?media_id=134912 + * https://api.bilibili.com/pgc/web/season/section?season_id=25617 * @input HttpRequestUtil util * @param mdId * @return */ private String MdIdToSsId(String mdId) { HttpHeaders headers = new HttpHeaders(); - String url = "https://www.bilibili.com/bangumi/media/" + mdId; - String html = util.getContent(url, headers.getCommonHeaders("www.bilibili.com")); - - int begin = html.indexOf("window.__INITIAL_STATE__="); - int end = html.indexOf(";(function()", begin); - String json = html.substring(begin + 25, end); - System.out.println(json); - JSONObject jObj = new JSONObject(json); - int ssId = jObj.getJSONObject("mediaInfo").getJSONObject("param").getInt("season_id"); + String mdIdNumber = mdId.replace("md", ""); + String url = "https://api.bilibili.com/pgc/review/user?media_id=" + mdIdNumber; + String result = util.getContent(url, headers.getCommonHeaders("www.bilibili.com")); + + System.out.println(result); + JSONObject jObj = new JSONObject(result); + int ssId = jObj.getJSONObject("result").getJSONObject("media").getInt("season_id"); System.out.println("ssId为: " + ssId); return "ss" + ssId; } diff --git a/src/nicelee/bilibili/parsers/impl/SSParser.java b/src/nicelee/bilibili/parsers/impl/SSParser.java index 26ca1c0a..ae788481 100644 --- a/src/nicelee/bilibili/parsers/impl/SSParser.java +++ b/src/nicelee/bilibili/parsers/impl/SSParser.java @@ -12,7 +12,7 @@ import nicelee.bilibili.util.HttpHeaders; import nicelee.bilibili.util.Logger; -//@Bilibili(name = "ss") +//@Bilibili(name = "SSParser") public class SSParser extends AbstractBaseParser { private final static Pattern pattern = Pattern.compile("(?!/cheese/play/ss[0-9]+)ss[0-9]+"); @@ -44,7 +44,9 @@ public VideoInfo result(String input, int videoFormat, boolean getVideoLink) { } /** - * + * @see https://www.bilibili.com/bangumi/media/md134912 + * https://api.bilibili.com/pgc/review/user?media_id=139252&ts=... + * https://api.bilibili.com/pgc/view/web/season?ep_id=250479 * @input HttpRequestUtil util * @param ssId * @param isGetLink @@ -54,24 +56,19 @@ protected VideoInfo getSSDetail(String ssId, int videoFormat, boolean isGetLink) VideoInfo viInfo = new VideoInfo(); viInfo.setVideoId(ssId); + String ssIdNumber = ssId.replace("ss", ""); HttpHeaders headers = new HttpHeaders(); - String url = "https://www.bilibili.com/bangumi/play/" + ssId; - String html = util.getContent(url, headers.getCommonHeaders("www.bilibili.com")); + String url = "https://api.bilibili.com/pgc/view/web/season?season_id=" + ssIdNumber; + String json = util.getContent(url, headers.getCommonHeaders("www.bilibili.com")); - int begin = html.indexOf("__NEXT_DATA__"); - begin = html.indexOf(">", begin); - int end = html.indexOf("", begin); - String json = html.substring(begin + 1, end); Logger.println(url); Logger.println(json); - JSONObject jObj = new JSONObject(json).getJSONObject("props").getJSONObject("pageProps") - .getJSONObject("dehydratedState").getJSONArray("queries").getJSONObject(0) - .getJSONObject("state").getJSONObject("data").getJSONObject("mediaInfo"); + JSONObject jObj = new JSONObject(json).getJSONObject("result"); viInfo.setVideoName(jObj.getString("title")); viInfo.setBrief(jObj.getString("evaluate")); viInfo.setAuthor("番剧"); viInfo.setAuthorId("番剧"); - viInfo.setVideoPreview("https:" + jObj.getString("cover")); + viInfo.setVideoPreview(jObj.getString("cover")); JSONArray array = jObj.getJSONArray("episodes"); LinkedHashMap clipMap = new LinkedHashMap(); @@ -88,7 +85,7 @@ protected VideoInfo getSSDetail(String ssId, int videoFormat, boolean isGetLink) clip.setcId(clipObj.getLong("cid")); //clip.setPage(Integer.parseInt(clipObj.getString("index"))); clip.setRemark(i + 1); - clip.setPicPreview("https:" +clipObj.getString("cover")); + clip.setPicPreview(clipObj.getString("cover")); //如果和前面avid一致,那么是前者page + 1, 否则为 1 if(i > 0 && array.getJSONObject(i-1).getString("bvid").equals(clipObj.getString("bvid"))) { clip.setPage(lastClip.getPage() + 1); From c92c69465f6cd31ba6775c102dbdb65aa19b1518 Mon Sep 17 00:00:00 2001 From: lijia Date: Mon, 3 Apr 2023 15:23:22 +0800 Subject: [PATCH 03/10] =?UTF-8?q?ci:=20=E4=BD=BF=E7=94=A8=E6=BA=90?= =?UTF-8?q?=E8=80=8C=E4=B8=8D=E6=98=AF=E9=95=9C=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/upload-manually.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/upload-manually.yml b/.github/workflows/upload-manually.yml index 86c2da61..7e99dfdb 100644 --- a/.github/workflows/upload-manually.yml +++ b/.github/workflows/upload-manually.yml @@ -108,7 +108,7 @@ jobs: RAILWAY_AUTH: ${{ secrets.RAILWAY_AUTH }} if: ${{ always() && env.RAILWAY_AUTH != '' && github.event.inputs.railwayFFmpeg == 'true'}} run: | - wget https://git.nicelee.top/nICEnnnnnnnLee/BilibiliDown/releases/download/V4.5/ffmpeg_N-108857-g00b03331a0-20221027.exe + wget https://github.com/nICEnnnnnnnLee/BilibiliDown/releases/download/V4.5/ffmpeg_N-108857-g00b03331a0-20221027.exe curl -X POST "https://bili.up.railway.app/upload" \ --cookie "auth=$RAILWAY_AUTH" \ -F "file=@ffmpeg_N-108857-g00b03331a0-20221027.exe;type=application/octet-stream" From 8fe268c67e620432d7cb626c409a589d20086ea6 Mon Sep 17 00:00:00 2001 From: lijia Date: Sat, 22 Apr 2023 16:57:10 +0800 Subject: [PATCH 04/10] =?UTF-8?q?fix=20#140,=20=E5=8D=B8=E8=BD=BD=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E5=A2=9E=E5=8A=A0=E6=9B=B4=E5=A4=9A=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- release/uninstall.bat | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release/uninstall.bat b/release/uninstall.bat index f6394742..0911a89b 100644 --- a/release/uninstall.bat +++ b/release/uninstall.bat @@ -1,4 +1,6 @@ @echo off +echo ĿļΪ %~dp0 +echo ýűɾļµļ set/p option=ж밴yȷ: if "%option%"=="y" echo y &goto :unistall if "%option%"=="Y" echo Y &goto :unistall From 61a0eea0542a85f8db5b5028ba0d1f47fe5b7a9c Mon Sep 17 00:00:00 2001 From: lijia Date: Sat, 22 Apr 2023 17:11:12 +0800 Subject: [PATCH 05/10] =?UTF-8?q?fix=20#141,=20=E5=A2=9E=E5=8A=A0=E9=85=8D?= =?UTF-8?q?=E7=BD=AE`bilibili.alert.qualityUnexpected`=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E5=BC=80=E5=90=AF/=E5=85=B3=E9=97=AD=E5=AF=B9?= =?UTF-8?q?=E9=9D=9E=E6=9C=9F=E6=9C=9B=E7=9A=84=E4=BD=8E=E7=94=BB=E8=B4=A8?= =?UTF-8?q?=E6=B8=85=E6=99=B0=E5=BA=A6=E8=A7=86=E9=A2=91=E7=9A=84=E5=88=A4?= =?UTF-8?q?=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/nicelee/bilibili/parsers/impl/AbstractBaseParser.java | 2 +- src/nicelee/ui/Global.java | 2 ++ src/resources/app.config | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/nicelee/bilibili/parsers/impl/AbstractBaseParser.java b/src/nicelee/bilibili/parsers/impl/AbstractBaseParser.java index 5e754421..8dbf762f 100644 --- a/src/nicelee/bilibili/parsers/impl/AbstractBaseParser.java +++ b/src/nicelee/bilibili/parsers/impl/AbstractBaseParser.java @@ -323,7 +323,7 @@ String getVideoLinkByFormat(String bvId, String cid, int qn, int downloadFormat) int linkQN = jObj.getInt("quality"); paramSetter.setRealQN(linkQN); System.out.println("查询质量为:" + qn + "的链接, 得到质量为:" + linkQN + "的链接"); - if(linkQN < 64 && qn > linkQN && Global.isLogin) { + if(Global.alertIfQualityUnexpected && linkQN < 64 && qn > linkQN && Global.isLogin) { throw new QualityTooLowException(bvId + " : " + cid + " - 查询质量为:" + qn + "的链接, 得到质量为:" + linkQN + "的链接"); } try { diff --git a/src/nicelee/ui/Global.java b/src/nicelee/ui/Global.java index 76f34a2e..73fd902d 100644 --- a/src/nicelee/ui/Global.java +++ b/src/nicelee/ui/Global.java @@ -163,6 +163,8 @@ public class Global { public static String menu_qn; // 菜单批量下载时, 优先下载清晰度 详见VideoQualityEnum @Config(key = "bilibili.tab.download.qn", note = "标签页下载时的优先清晰度", defaultValue = "1080P") public static String tab_qn; // 标签页批量下载时, 优先下载清晰度 详见VideoQualityEnum + @Config(key = "bilibili.alert.qualityUnexpected", note = "当遇到不期望的480P视频时是否抛出异常", defaultValue = "true", valids = { "true", "false" }) + public static boolean alertIfQualityUnexpected; // 字幕弹幕相关 @Config(key = "bilibili.cc.lang", note = "CC字幕优先语种", defaultValue = "zh-CN") public static String cc_lang; // 字幕优先语种,如zh-CN等, 详见 release/wiki/langs.txt diff --git a/src/resources/app.config b/src/resources/app.config index dcfb51e4..2dc1fe6c 100644 --- a/src/resources/app.config +++ b/src/resources/app.config @@ -188,6 +188,10 @@ bilibili.alert.isAlertIfDownloded = true # 批量下载时,最大提示框弹出数 bilibili.alert.maxAlertPrompt = 5 + +# 当遇到不期望的480P视频时是否抛出异常 +## https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/141 +bilibili.alert.qualityUnexpected = true ####################################################################################################### # 同时支持HTTP + HTTPS 代理 #proxyHost = 127.0.0.1 From 9c0645e1aba25c8b432291ca86560e581f429625 Mon Sep 17 00:00:00 2001 From: lijia Date: Thu, 25 May 2023 09:16:04 +0800 Subject: [PATCH 06/10] =?UTF-8?q?fix=20#146,fix=20#147,=E8=A7=A3=E5=86=B3a?= =?UTF-8?q?pi=E6=9B=B4=E6=8D=A2=E5=AF=BC=E8=87=B4UP=E4=B8=BB=E6=89=80?= =?UTF-8?q?=E6=9C=89=E8=A7=86=E9=A2=91=E6=97=A0=E6=B3=95=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bilibili/parsers/impl/URL4UPAllMedialistParser.java | 5 ++++- src/nicelee/bilibili/parsers/impl/URL4UPAllParser.java | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/nicelee/bilibili/parsers/impl/URL4UPAllMedialistParser.java b/src/nicelee/bilibili/parsers/impl/URL4UPAllMedialistParser.java index c5d4663b..4d183d1d 100644 --- a/src/nicelee/bilibili/parsers/impl/URL4UPAllMedialistParser.java +++ b/src/nicelee/bilibili/parsers/impl/URL4UPAllMedialistParser.java @@ -8,6 +8,7 @@ import org.json.JSONArray; import org.json.JSONObject; +import nicelee.bilibili.API; import nicelee.bilibili.annotations.Bilibili; import nicelee.bilibili.enums.VideoQualityEnum; import nicelee.bilibili.model.ClipInfo; @@ -154,8 +155,10 @@ protected boolean query(int page, int min, int max, Object... obj) { } } int lastPageNumber = (page - 1) * API_PMAX + 1; - 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/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"), lastPageNumber, sortFieldParam); + url = API.encWbi(url); String json = util.getContent(url, headers, HttpCookies.globalCookiesWithFingerprint()); Logger.println(url); Logger.println(json); diff --git a/src/nicelee/bilibili/parsers/impl/URL4UPAllParser.java b/src/nicelee/bilibili/parsers/impl/URL4UPAllParser.java index ba298bfb..80009bf6 100644 --- a/src/nicelee/bilibili/parsers/impl/URL4UPAllParser.java +++ b/src/nicelee/bilibili/parsers/impl/URL4UPAllParser.java @@ -1,5 +1,6 @@ package nicelee.bilibili.parsers.impl; +import java.net.URLDecoder; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.regex.Matcher; @@ -8,6 +9,7 @@ import org.json.JSONArray; import org.json.JSONObject; +import nicelee.bilibili.API; import nicelee.bilibili.annotations.Bilibili; import nicelee.bilibili.model.ClipInfo; import nicelee.bilibili.model.VideoInfo; @@ -84,8 +86,11 @@ protected boolean query(int page, int min, int max, Object... obj) { boolean getVideoLink = (boolean) obj[1]; try { //String urlFormat = "https://space.bilibili.com/ajax/member/getSubmitVideos?mid=%s&pagesize=%d&tid=0&page=%d&keyword=&order=pubdate"; - String urlFormat = "https://api.bilibili.com/x/space/arc/search?mid=%s&ps=%d&tid=%s&pn=%d&keyword=%s&order=%s&jsonp=jsonp"; - String url = String.format(urlFormat, spaceID, API_PMAX, params.get("tid"), page, params.get("keyword"), params.get("order")); + //String urlFormat = "https://api.bilibili.com/x/space/arc/search?mid=%s&ps=%d&tid=%s&pn=%d&keyword=%s&order=%s&jsonp=jsonp"; + 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 = URLDecoder.decode(params.get("keyword"), "UTF-8"); + String url = String.format(urlFormat, spaceID, API_PMAX, params.get("tid"), page, keyword, params.get("order")); + url = API.encWbi(url); String json = util.getContent(url, new HttpHeaders().getCommonHeaders("api.bilibili.com"), HttpCookies.globalCookiesWithFingerprint()); Logger.println(url); Logger.println(json); From 7c0d0c2764171eccb94a228f28aa8e47151b7d1e Mon Sep 17 00:00:00 2001 From: lijia Date: Tue, 30 May 2023 21:09:46 +0800 Subject: [PATCH 07/10] =?UTF-8?q?fix=20#145,=20=E5=8F=AF=E4=BB=A5=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E9=85=8D=E7=BD=AE=EF=BC=8C=E9=92=88=E5=AF=B9=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E5=88=86=E8=BE=A8=E7=8E=87=E8=AE=BE=E7=BD=AE=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E7=9A=84=E8=A7=86=E9=A2=91=E7=BC=96=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=85=88=E7=BA=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../parsers/impl/AbstractBaseParser.java | 5 ++++- src/nicelee/ui/Global.java | 19 ++++++++++++++++++- src/resources/app.config | 10 ++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/nicelee/bilibili/parsers/impl/AbstractBaseParser.java b/src/nicelee/bilibili/parsers/impl/AbstractBaseParser.java index 8dbf762f..268a9f2c 100644 --- a/src/nicelee/bilibili/parsers/impl/AbstractBaseParser.java +++ b/src/nicelee/bilibili/parsers/impl/AbstractBaseParser.java @@ -468,8 +468,11 @@ protected String parseType1(JSONObject jObj, int linkQN, HashMap System.out.println("API返回质量为:" + linkQN + "的链接, 实际上只有质量为:" + paramSetter.getRealQN() + "的链接"); qnVideos.add(v); } + // 根据清晰度选择合适的编码优先级 + Integer rQN = Integer.valueOf(paramSetter.getRealQN()); + int[] videoCodecPriority = Global.videoCodecPriorityMap.getOrDefault(rQN, Global.videoCodecPriority); // 根据需求选择编码合适的视频 - JSONObject video = findMediaByPriList(qnVideos, Global.videoCodecPriority, 0); + JSONObject video = findMediaByPriList(qnVideos, videoCodecPriority, 0); // 选择可以连通的链接 String videoLink = getUrlOfMedia(video, Global.checkDashUrl, headerForValidCheck); link.append(videoLink).append("#"); diff --git a/src/nicelee/ui/Global.java b/src/nicelee/ui/Global.java index 73fd902d..afa96318 100644 --- a/src/nicelee/ui/Global.java +++ b/src/nicelee/ui/Global.java @@ -62,8 +62,10 @@ public class Global { public static int downloadFormat = MP4; // 优先下载格式,如不存在该类型的源,那么将默认转为下载另一种格式 @Config(key = "bilibili.dash.download.mode", defaultValue = "0", valids = { "0", "1", "2" }, note = "DASH下载模式: 0-下载音视频,1-仅视频,2-仅音频") public static DownloadModeEnum downloadMode = DownloadModeEnum.All; - @Config(key = "bilibili.dash.video.codec.priority", defaultValue = "7, 12, 13", note = "视频编码优先级,AV1:13,HEVC:12,AVC:7,随意-1") + @Config(key = "bilibili.dash.video.codec.priority", defaultValue = "7, 12, 13", note = "视频编码优先级(默认),AV1:13,HEVC:12,AVC:7,随意-1") public static int[] videoCodecPriority = {7, 12, 13}; + @Config(key = "bilibili.dash.video.codec.priority.map", defaultValue = "80:7, 12, 13| 64:7, 12, 13", note = "视频编码优先级(区分清晰度),AV1:13,HEVC:12,AVC:7,随意-1") + public static HashMap videoCodecPriorityMap; @Config(key = "bilibili.dash.audio.quality.priority", defaultValue = "30280, 30232, 30216, -1, 30251, 30250", note = "音频编码优先级,30216:64K, 30232:132K, 30280:192K, 随意-1") public static int[] audioQualityPriority = {30280, 30232, 30216, -1}; @@ -303,6 +305,21 @@ private static void setValue(Field field, String value, boolean isDefaultValue, valueStrs[i] = valueStrs[i].trim(); } field.set(null, valueStrs); + }else if (field.getType().equals(HashMap.class)) { // HashMap + // 80:7, 12, 13| 64:7, 12, 13 + String[] patterns = value.split("\\|"); + HashMap m = new HashMap(); + for(String pattern: patterns) { + String[] pair = pattern.split(":"); + Integer key = Integer.parseInt(pair[0].trim()); + String[] valueStrs = pair[1].split(","); + int[] values = new int[valueStrs.length]; + for(int i=0; i Date: Tue, 6 Jun 2023 13:34:39 +0800 Subject: [PATCH 08/10] =?UTF-8?q?feat:=20=E7=9B=B4=E6=8E=A5=E5=9C=A8?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E4=BB=A3=E7=A0=81=E4=B8=AD=E5=88=B7=E6=96=B0?= =?UTF-8?q?cookie=EF=BC=8C=E8=80=8C=E4=B8=8D=E6=98=AF=E5=80=9F=E7=94=A8?= =?UTF-8?q?=E6=B5=8F=E8=A7=88=E5=99=A8=E7=8E=AF=E5=A2=83=E8=BF=90=E8=A1=8C?= =?UTF-8?q?wasm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/nicelee/ui/Global.java | 2 + .../ui/thread/CookieRefreshThread.java | 109 ++++++++++++++---- src/resources/app.config | 3 + 3 files changed, 91 insertions(+), 23 deletions(-) diff --git a/src/nicelee/ui/Global.java b/src/nicelee/ui/Global.java index afa96318..cd1ef2de 100644 --- a/src/nicelee/ui/Global.java +++ b/src/nicelee/ui/Global.java @@ -113,6 +113,8 @@ public class Global { @Config(key = "bilibili.download.batch.config.name.pattern", note = "一键下载配置名称的匹配正则表达式", defaultValue = "^batchDownload.*\\.config$") public static Pattern batchDownloadConfigNamePattern; // 登录相关 + @Config(key = "bilibili.login.cookie.refresh.runWASMinBrowser", defaultValue = "false", valids = { "true", "false" }) + public static boolean runWASMinBrowser; @Config(key = "bilibili.server.port", note = "http server监听端口,用于极验校验", defaultValue = "8787") public static int serverPort = 8787; @Config(key = "bilibili.user.userName", defaultValue = "", warning = false) diff --git a/src/nicelee/ui/thread/CookieRefreshThread.java b/src/nicelee/ui/thread/CookieRefreshThread.java index 7f372457..19487fbf 100644 --- a/src/nicelee/ui/thread/CookieRefreshThread.java +++ b/src/nicelee/ui/thread/CookieRefreshThread.java @@ -8,6 +8,17 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; +import java.security.KeyFactory; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.MGF1ParameterSpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.crypto.Cipher; +import javax.crypto.spec.OAEPParameterSpec; +import javax.crypto.spec.PSource; import nicelee.ui.item.JOptionPane; @@ -18,6 +29,7 @@ import nicelee.bilibili.util.HttpHeaders; import nicelee.bilibili.util.HttpRequestUtil; import nicelee.bilibili.util.Logger; +import nicelee.server.core.PathDealer; import nicelee.server.core.SocketServer; import nicelee.ui.Global; @@ -41,6 +53,37 @@ private CookieRefreshThread() { this.setName("Thread-CookieRefresh"); } + private static String encrypt(String origin) { + try { + // base64编码的公钥 + String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDLgd2OAkcGVtoE3ThUREbio0EgUc/prcajMKXvkCKFCWhJYJcLkcM2DKKcSeFpD/j6Boy538YXnR6VhcuUJOhH2x71nzPjfdTcqMz7djHum0qSZA0AyCBDABUqCrfNgCiJ00Ra7GmRj+YCK1NJEuewlb40JNrRuoEUXpabUzGB8QIDAQAB"; + byte[] decoded = Base64.getDecoder().decode(publicKey); + X509EncodedKeySpec spec = new X509EncodedKeySpec(decoded); + KeyFactory kf = KeyFactory.getInstance("RSA"); + RSAPublicKey pubKey = (RSAPublicKey) kf.generatePublic(spec); + // RSA加密 + Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding"); + OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), + PSource.PSpecified.DEFAULT); + cipher.init(Cipher.ENCRYPT_MODE, pubKey, oaepParams); + byte[] resultBytes = cipher.doFinal(origin.getBytes("UTF-8")); + char[] resultChars = new char[resultBytes.length * 2]; + char[] chars = "0123456789abcdef".toCharArray(); + for (int i = 0; i < resultBytes.length; i++) { + byte b = resultBytes[i]; + int left = (b & 0xf0) >> 4; + int right = b & 0x0f; + resultChars[i * 2] = chars[left]; + resultChars[i * 2 + 1] = chars[right]; + } + String outStr = new String(resultChars); + return outStr; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + @Override public void run() { // 判断有没有refresh_token @@ -57,32 +100,52 @@ public void run() { JSONObject csrfInfoObj = new JSONObject(csrfInfo).getJSONObject("data"); boolean needRefresh = csrfInfoObj.getBoolean("refresh"); if (!needRefresh) { - JOptionPane.showMessageDialog(null, "当前cookie无需刷新"); - return; + JOptionPane.showMessageDialog(null, "当前cookie无需刷新"); + return; } - // 打开server,等待返回 refresh_csrf - new Thread(new Runnable() { - @Override - public void run() { - socketServer = new SocketServer(Global.serverPort); - socketServer.startServer(); + if (Global.runWASMinBrowser) { + // 打开server,等待返回 refresh_csrf + new Thread(new Runnable() { + @Override + public void run() { + socketServer = new SocketServer(Global.serverPort); + socketServer.startServer(); + } + }, "Cookie 刷新server").start(); + String browseUrl = String.format("http://localhost:%d/cookieRefresh/index.html?timestamp=%d", + Global.serverPort, csrfInfoObj.optLong("timestamp")); + goUrlOrShowTips(browseUrl); + try {// 等待3min + synchronized (this) { + this.wait(180000); + } + } catch (Exception e) { } - }, "Cookie 刷新server").start(); - String browseUrl = String.format("http://localhost:%d/cookieRefresh/index.html?timestamp=%d", Global.serverPort, - csrfInfoObj.optLong("timestamp")); - goUrlOrShowTips(browseUrl); - try {// 等待3min - synchronized(this) { - this.wait(180000); + // 关闭server,判断情况 + shutDownServerAsyncDelay(); + if (getRefreshCsrf() == null) { + Logger.println("没有收到浏览器传来的refreshCsrf参数"); + JOptionPane.showMessageDialog(null, "没有收到浏览器传来的refreshCsrf参数"); + return; + } + } else { + try { + // 生成 correspond路径 + String refresh_timestamp = "refresh_" + csrfInfoObj.optString("timestamp"); + Logger.println(refresh_timestamp); + String path = "https://www.bilibili.com/correspond/1/" + encrypt(refresh_timestamp); + // 获取 refresh_csrf + String html = util.getContent(path, headers.getCommonHeaders(), HttpCookies.getGlobalCookies()); + Pattern p = Pattern.compile("
(.+?)
"); + Matcher m = p.matcher(html); + m.find(); + refreshCsrf = m.group(1).trim(); + Logger.println(refreshCsrf); + } catch (Exception e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(null, "刷新cookie出现错误"); + return; } - } catch (Exception e) { - } - // 关闭server,判断情况 - shutDownServerAsyncDelay(); - if (getRefreshCsrf() == null) { - Logger.println("没有收到浏览器传来的refreshCsrf参数"); - JOptionPane.showMessageDialog(null, "没有收到浏览器传来的refreshCsrf参数"); - return; } // 调用刷新Cookie的API INeedLogin inl = new INeedLogin(); diff --git a/src/resources/app.config b/src/resources/app.config index 1f45e12e..0e99f113 100644 --- a/src/resources/app.config +++ b/src/resources/app.config @@ -239,6 +239,9 @@ bilibili.download.batch.config.name.pattern = ^batchDownload.*\.config$ ####################################################################################################### ## 登录设置 +# 刷新cookie时,借用浏览器环境运行wasm,而不是直接使用代码 +bilibili.login.cookie.refresh.runWASMinBrowser = false + # 登录方式 # qr 扫描QR二维码 # pwd 使用用户名密码登录 From ad3baba728a580c35b6706fff1383e6650742b75 Mon Sep 17 00:00:00 2001 From: lijia Date: Tue, 6 Jun 2023 13:49:17 +0800 Subject: [PATCH 09/10] =?UTF-8?q?fix=3F=20#149,=20=E5=B0=9D=E8=AF=95?= =?UTF-8?q?=E5=85=BC=E5=AE=B9mac=E4=B8=8B=E8=BF=A5=E5=BC=82=E7=9A=84UI?= =?UTF-8?q?=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/nicelee/ui/TabVideo.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nicelee/ui/TabVideo.java b/src/nicelee/ui/TabVideo.java index 24f8b922..ffd3b106 100644 --- a/src/nicelee/ui/TabVideo.java +++ b/src/nicelee/ui/TabVideo.java @@ -118,12 +118,14 @@ public void actionPerformed(ActionEvent e) { this.add(btnDownCC); // 空白模块- 占位 JLabel jlBLANK11 = new JLabel(); - jlBLANK11.setPreferredSize(new Dimension(140, 30)); + jlBLANK11.setPreferredSize(new Dimension(90, 30)); + // jlBLANK11.setBorder(BorderFactory.createLineBorder(Color.red)); this.add(jlBLANK11); // 空白模块- 占位 JLabel jlBLANK2 = new JLabel(); jlBLANK2.setPreferredSize(new Dimension(100, 60)); + // jlBLANK2.setBorder(BorderFactory.createLineBorder(Color.red)); this.add(jlBLANK2); lbBreif.setBorder(BorderFactory.createLineBorder(Color.red)); From 7025a8c09ec21fcbd0fab79fe5c7a8a8e3a15382 Mon Sep 17 00:00:00 2001 From: lijia Date: Tue, 6 Jun 2023 14:12:05 +0800 Subject: [PATCH 10/10] V6.26 Update --- .github/release.info | 8 ++++++-- README.md | 1 + UPDATE.md | 8 ++++++++ src/nicelee/ui/Global.java | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/release.info b/.github/release.info index f3512882..f7c7080c 100644 --- a/.github/release.info +++ b/.github/release.info @@ -1,5 +1,9 @@ -* 修复`V6.24`引入的一个bug,该bug导致jar包路径存在空格或者中文时,程序不能正确运行。 -* 优化: 出现报错弹窗时,输出更详细的异常信息 +* 修复: [issues 146](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/146),[issues 147](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/147) 解决api更换导致的UP主所有视频无法查询的问题 +* 修复: [issues 149](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/149), 作品信息页面尝试兼容mac下的UI布局 +* 优化: [issues 140](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/140) 卸载脚本增加更多提示 +* 优化: [issues 141](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/141) 增加配置`bilibili.alert.qualityUnexpected`,可以开启/关闭对非期望的低画质清晰度视频的判断 +* 优化: [issues 145](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/145) 增加相关配置,可以针对不同分辨率设置不同的视频编码优先级 +* 优化: 现在可以直接在程序代码中刷新cookie,而不必再打开浏览器
如果你是Win64用户,且没有java环境,请下载附件`*.win_x64_jre11.release.zip` \ No newline at end of file diff --git a/README.md b/README.md index 62899512..7f78fd4a 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Bilibili 视频下载器,用于下载B站视频。 * 使用[zxing](https://github.com/zxing/zxing)库生成链接二维码图片[![](https://img.shields.io/badge/license-Apache%202-green.svg)](https://raw.githubusercontent.com/zxing/zxing/master/LICENSE) * 以外部库的方式调用[ffmpeg](http://www.ffmpeg.org)进行转码(短片段flv未使用ffmpeg,仅多flv合并及m4s转换mp4格式需要用到)[![](https://img.shields.io/badge/license-depends-orange.svg)](http://www.ffmpeg.org/legal.html) * geetest验证码实现参考了[geetest-validator](https://github.com/kuresaru/geetest-validator)[![](https://img.shields.io/badge/license-unknown-gray.svg)](https://github.com/kuresaru/geetest-validator) +* cookie刷新代码的wasm逆向实现参考了[SocialSisterYi/bilibili-API-collect#524](https://github.com/SocialSisterYi/bilibili-API-collect/issues/524#issuecomment-1537519232)[![](https://img.shields.io/badge/license-CC%20BY%20NC%204.0-green.svg)](https://github.com/SocialSisterYi/bilibili-API-collect/issues/524#issuecomment-1537519232) ## :smile:其它 * **下载地址**: diff --git a/UPDATE.md b/UPDATE.md index 537b95fa..5d5dc891 100644 --- a/UPDATE.md +++ b/UPDATE.md @@ -1,4 +1,12 @@ ## UPDATE +* V6.26 `2023-06-06` + * 修复: [issues 146](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/146),[issues 147](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/147) 解决api更换导致的UP主所有视频无法查询的问题 + * 修复: [issues 149](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/149), 作品信息页面尝试兼容mac下的UI布局 + * 优化: [issues 140](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/140) 卸载脚本增加更多提示 + * 优化: [issues 141](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/141) 增加配置`bilibili.alert.qualityUnexpected`,可以开启/关闭对非期望的低画质清晰度视频的判断 + * 优化: [issues 145](https://github.com/nICEnnnnnnnLee/BilibiliDown/issues/145) 增加相关配置,可以针对不同分辨率设置不同的视频编码优先级 + * 优化: 现在可以直接在程序代码中刷新cookie,而不必再打开浏览器 + * V6.25 `2023-03-23` * 修复`V6.24`引入的一个bug,该bug导致jar包路径存在空格或者中文时,程序不能正确运行。 * 优化: 出现报错弹窗时,输出更详细的异常信息 diff --git a/src/nicelee/ui/Global.java b/src/nicelee/ui/Global.java index cd1ef2de..74accb69 100644 --- a/src/nicelee/ui/Global.java +++ b/src/nicelee/ui/Global.java @@ -24,7 +24,7 @@ public class Global { // 界面显示相关 - @Config(key = "bilibili.version", defaultValue = "v6.25", warning = false) + @Config(key = "bilibili.version", defaultValue = "v6.26", warning = false) public static String version; // 一般情况下,我们不会设置这个标签,这个用于测试 @Config(key = "bilibili.theme", note = "界面主题", defaultValue = "true", eq_true = "default", valids = { "default", "system" }) public static boolean themeDefault;