我的哔哩.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /**
  2. * 已知问题:
  3. * [推荐]页面:'雷电模拟器'播放部份影片会出错,'播放器'改成'ijk' & '解码方式'改成'软解',即可正常播放
  4. * 影视TV 超連結跳轉支持
  5. * 影视TV 弹幕支持
  6. * https://t.me/fongmi_offical/
  7. * https://github.com/FongMi/Release/tree/main/apk
  8. * 皮皮虾DMBox 弹幕支持
  9. * 设置 > 窗口预览 > 开启
  10. * https://t.me/pipixiawerun
  11. * vod_area:'bilidanmu'
  12. * Cookie设置
  13. * Cookie获取方法 https://ghproxy.net/https://raw.githubusercontent.com/UndCover/PyramidStore/main/list.md
  14. * Cookie设置方法1: DR-PY 后台管理界面
  15. * CMS后台管理 > 设置中心 > 环境变量 > {"bili_cookie":"XXXXXXX","vmid":"XXXXXX"} > 保存
  16. * Cookie设置方法2: 手动替换Cookie
  17. * 底下代码 headers的
  18. * "Cookie":"$bili_cookie"
  19. * 手动替换为
  20. * "Cookie":"将获取的Cookie黏贴在这"
  21. * 客户端长期Cookie设置教程:
  22. * 抓包哔哩手机端搜索access_key,取任意链接里的access_key和appkey在drpy环境变量中增加同名的环境变量即可
  23. * 此时哔哩.js这个解析可用于此源的解析线路用
  24. * 传参 ?render=1&type=url&params=../json/哔哩教育.json@哔哩教育[官]
  25. * 传参 ?render=1&type=url&params=../json/哔哩大全.json@哔哩大全[官]
  26. */
  27. var rule = {
  28. title: '我的哔哩[官]',
  29. host: 'https://api.bilibili.com',
  30. homeUrl: '/x/web-interface/ranking/v2?rid=0&type=origin',
  31. // url:'/x/web-interface/search/type?search_type=video&keyword=fyclass&page=fypage',
  32. url: '/x/web-interface/search/type?search_type=video&fyfilter',
  33. filter_url: 'keyword=fyclass{{fl.tid}}&page=fypage&duration={{fl.duration}}&order={{fl.order}}',
  34. class_parse: $js.toString(() => {
  35. // let html = request('{{host}}/files/json/哔哩教育.json');
  36. log('rule.params:' + rule.params);
  37. let html = request(rule.params);
  38. let json = dealJson(html);
  39. input = json.classes;
  40. homeObj.filter = json.filter;
  41. // log(input);
  42. }),
  43. filterable: 1,
  44. detailUrl: '/x/web-interface/view/detail?aid=fyid',
  45. searchUrl: '/x/web-interface/search/type?search_type=video&keyword=**&page=fypage',
  46. searchable: 2,
  47. quickSearch: 0,
  48. params: 'http://127.0.0.1:9978/file/jars/哔哩大全.json',
  49. // params: '?render=1&type=url&params=../json/哔哩教育.json@哔哩教育[官]',
  50. // params: '?render=1&type=url&params=../json/哔哩大全.json@哔哩大全[官]',
  51. headers: {
  52. "User-Agent": "PC_UA",
  53. "Referer": "https://www.bilibili.com",
  54. "Cookie": "SESSDATA=01c79709%2C1711618905%2C244c3%2A91CjA9UUnRb_kJg03J5FqUbin76yMY90o1-ckJsM1ItQH21ns4hgcS6Le6oMR3SKtC18QSVmxSbGRhN3cyS3NReERsOHRfYVlhTWJKZjZyTF9wUWJXbjNfaF9qWklFMFpoeVg1ZUhFb0Q0MGFiN3FYd1N3UEFEY1oxX29IdmFSRVVLamcybGhhSkJnIIEC; bili_jct=e9d6e9df733afde2a03693d63a4e77dc; DedeUserID=186957646;"
  55. },
  56. timeout: 5000,
  57. limit: 8,
  58. play_parse: true,
  59. double: false,
  60. lazy: `js:
  61. let ids = input.split('_');
  62. let dan = 'https://api.bilibili.com/x/v1/dm/list.so?oid=' + ids[1];
  63. let result = {};
  64. let iurl = 'https://api.bilibili.com:443/x/player/playurl?avid=' + ids[0] + '&cid=' + ids[1] + '&qn=116';
  65. let html = request(iurl);
  66. let jRoot = JSON.parse(html);
  67. let jo = jRoot.data;
  68. let ja = jo.durl;
  69. let maxSize = -1;
  70. let position = -1;
  71. ja.forEach(function(tmpJo, i) {
  72. if (maxSize < Number(tmpJo.size)) {
  73. maxSize = Number(tmpJo.size);
  74. position = i
  75. }
  76. });
  77. let purl = '';
  78. if (ja.length > 0) {
  79. if (position === -1) {
  80. position = 0
  81. }
  82. purl = ja[position].url
  83. }
  84. result.parse = 0;
  85. result.playUrl = '';
  86. result.url = unescape(purl);
  87. result.header = {
  88. 'Referer': 'https://live.bilibili.com',
  89. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
  90. };
  91. if (/\\.flv/.test(purl)) {
  92. result.contentType = 'video/x-flv';
  93. } else {
  94. result.contentType = '';
  95. }
  96. result.danmaku = dan;
  97. input = result
  98. `,
  99. 推荐: `js:
  100. function stripHtmlTag(src) {
  101. return src.replace(/<\\/?[^>]+(>|$)/g, '').replace(/&.{1,5};/g, '').replace(/\\s{2,}/g, ' ');
  102. }
  103. function turnDHM(duration) {
  104. let min = '';
  105. let sec = '';
  106. try {
  107. min = duration.split(':')[0];
  108. sec = duration.split(':')[1];
  109. } catch (e) {
  110. min = Math.floor(duration / 60);
  111. sec = duration % 60;
  112. }
  113. if (isNaN(parseInt(duration))) {
  114. return '无效输入';
  115. }
  116. if (min == 0) {
  117. return sec + '秒'
  118. } else if (0 < min && min < 60) {
  119. return min + '分'
  120. } else if (60 <= min && min < 1440) {
  121. if (min % 60 == 0) {
  122. let h = min / 60;
  123. return h + '小时'
  124. } else {
  125. let h = min / 60;
  126. h = (h + '').split('.')[0];
  127. let m = min % 60;
  128. return h + '小时' + m + '分';
  129. }
  130. } else if (min >= 1440) {
  131. let d = min / 60 / 24;
  132. d = (d + '').split('.')[0];
  133. let h = min / 60 % 24;
  134. h = (h + '').split('.')[0];
  135. let m = min % 60;
  136. let dhm = '';
  137. if (d > 0) {
  138. dhm = d + '天'
  139. }
  140. if (h >= 1) {
  141. dhm = dhm + h + '小时'
  142. }
  143. if (m > 0) {
  144. dhm = dhm + m + '分'
  145. }
  146. return dhm
  147. }
  148. return null
  149. }
  150. function ConvertNum(num) {
  151. let _ws = Math.pow(10, 1);
  152. let _b = 1e4;
  153. if (num < _b) {
  154. return num.toString();
  155. }
  156. let _r = '';
  157. let _strArg = ['', '万', '亿', '万亿'];
  158. let _i = Math.floor(Math.log(num) / Math.log(_b));
  159. if (_i > 3) {
  160. _i = 3;
  161. }
  162. _r = Math.floor(num / Math.pow(_b, _i) * _ws) / _ws + _strArg[_i];
  163. return _r;
  164. }
  165. let html = request(input);
  166. let vodList = JSON.parse(html).data.list;
  167. let videos = [];
  168. vodList.forEach(function(vod) {
  169. let aid = vod.aid;
  170. let title = stripHtmlTag(vod.title);
  171. let img = vod.pic;
  172. if (img.startsWith('//')) {
  173. img = 'https:' + img;
  174. }
  175. let remark = turnDHM(vod.duration) + ' ▶' + ConvertNum(vod.stat.view) + ' 🆙' + vod.owner.name;
  176. videos.push({
  177. vod_id: aid,
  178. vod_name: title,
  179. vod_pic: img,
  180. vod_remarks: remark
  181. })
  182. });
  183. VODS = videos
  184. `,
  185. 一级: `js:
  186. if (cateObj.tid.endsWith('_clicklink')) {
  187. cateObj.tid = cateObj.tid.split('_')[0];
  188. input = HOST + '/x/web-interface/search/type?search_type=video&keyword=' + cateObj.tid + '&page=' + MY_PAGE;
  189. }
  190. function stripHtmlTag(src) {
  191. return src.replace(/<\\/?[^>]+(>|$)/g, '').replace(/&.{1,5};/g, '').replace(/\\s{2,}/g, ' ');
  192. }
  193. function turnDHM(duration) {
  194. let min = '';
  195. let sec = '';
  196. try {
  197. min = duration.split(':')[0];
  198. sec = duration.split(':')[1];
  199. } catch (e) {
  200. min = Math.floor(duration / 60);
  201. sec = duration % 60;
  202. }
  203. if (isNaN(parseInt(duration))) {
  204. return '无效输入';
  205. }
  206. if (min == 0) {
  207. return sec + '秒'
  208. } else if (0 < min && min < 60) {
  209. return min + '分'
  210. } else if (60 <= min && min < 1440) {
  211. if (min % 60 == 0) {
  212. let h = min / 60;
  213. return h + '小时'
  214. } else {
  215. let h = min / 60;
  216. h = (h + '').split('.')[0];
  217. let m = min % 60;
  218. return h + '小时' + m + '分';
  219. }
  220. } else if (min >= 1440) {
  221. let d = min / 60 / 24;
  222. d = (d + '').split('.')[0];
  223. let h = min / 60 % 24;
  224. h = (h + '').split('.')[0];
  225. let m = min % 60;
  226. let dhm = '';
  227. if (d > 0) {
  228. dhm = d + '天'
  229. }
  230. if (h >= 1) {
  231. dhm = dhm + h + '小时'
  232. }
  233. if (m > 0) {
  234. dhm = dhm + m + '分'
  235. }
  236. return dhm
  237. }
  238. return null
  239. }
  240. function ConvertNum(num) {
  241. let _ws = Math.pow(10, 1);
  242. let _b = 1e4;
  243. if (num < _b) {
  244. return num.toString();
  245. }
  246. let _r = '';
  247. let _strArg = ['', '万', '亿', '万亿'];
  248. let _i = Math.floor(Math.log(num) / Math.log(_b));
  249. if (_i > 3) {
  250. _i = 3;
  251. }
  252. _r = Math.floor(num / Math.pow(_b, _i) * _ws) / _ws + _strArg[_i];
  253. return _r;
  254. }
  255. let data = [];
  256. let vodList = [];
  257. if (MY_CATE === '推荐') {
  258. input = HOST + '/x/web-interface/index/top/rcmd?ps=14&fresh_idx=' + MY_PAGE + '&fresh_idx_1h=' + MY_PAGE;
  259. data = JSON.parse(request(input)).data;
  260. vodList = data.item;
  261. } else if (MY_CATE === '历史记录') {
  262. input = HOST + '/x/v2/history?pn=' + MY_PAGE;
  263. data = JSON.parse(request(input)).data;
  264. vodList = data;
  265. } else {
  266. data = JSON.parse(request(input)).data;
  267. vodList = data.result;
  268. }
  269. let videos = [];
  270. vodList.forEach(function(vod) {
  271. let aid = vod.aid?vod.aid:vod.id;
  272. let title = stripHtmlTag(vod.title);
  273. let img = vod.pic;
  274. if (img.startsWith('//')) {
  275. img = 'https:' + img;
  276. }
  277. let play = '';
  278. let danmaku = '';
  279. if (MY_CATE === '推荐') {
  280. play = ConvertNum(vod.stat.view);
  281. danmaku = vod.stat.danmaku;
  282. } else if (MY_CATE === '历史记录') {
  283. play = ConvertNum(vod.stat.view);
  284. danmaku = vod.stat.danmaku;
  285. } else {
  286. play = ConvertNum(vod.play);
  287. danmaku = vod.video_review;
  288. }
  289. let remark = turnDHM(vod.duration) + ' ▶' + play + ' 💬' + danmaku;
  290. videos.push({
  291. vod_id: aid,
  292. vod_name: title,
  293. vod_pic: img,
  294. vod_remarks: remark
  295. })
  296. });
  297. VODS = videos
  298. `,
  299. 二级: `js:
  300. function stripHtmlTag(src) {
  301. return src.replace(/<\\/?[^>]+(>|$)/g, '').replace(/&.{1,5};/g, '').replace(/\\s{2,}/g, ' ');
  302. }
  303. let html = request(input);
  304. let jo = JSON.parse(html).data.View;
  305. // 历史记录
  306. let cookies = rule_fetch_params.headers.Cookie.split(';');
  307. let bili_jct = '';
  308. cookies.forEach(cookie => {
  309. if (cookie.includes('bili_jct')) {
  310. bili_jct = cookie.split('=')[1];
  311. }
  312. });
  313. if (bili_jct !== '') {
  314. let historyReport = 'https://api.bilibili.com/x/v2/history/report';
  315. let dataPost = {
  316. aid: jo.aid,
  317. cid: jo.cid,
  318. csrf: bili_jct,
  319. };
  320. post(historyReport, dataPost, 'form');
  321. }
  322. let stat = jo.stat;
  323. let up_info = JSON.parse(html).data.Card;
  324. let relation = up_info.following ? '已关注' : '未关注';
  325. let aid = jo.aid;
  326. let title = stripHtmlTag(jo.title);
  327. let pic = jo.pic;
  328. let desc = jo.desc;
  329. let date = new Date(jo.pubdate * 1000);
  330. let yy = date.getFullYear().toString();
  331. let mm = date.getMonth()+1;
  332. mm = mm < 10 ? ('0' + mm) : mm;
  333. let dd = date.getDate();
  334. dd = dd < 10 ? ('0' + dd) : dd;
  335. let up_name = jo.owner.name;
  336. let typeName = jo.tname;
  337. // let remark = jo.duration;
  338. let vod = {
  339. vod_id: aid,
  340. vod_name: title,
  341. vod_pic: pic,
  342. type_name: typeName,
  343. vod_year: yy+mm+dd,
  344. vod_area: 'bilidanmu',
  345. // vod_remarks: remark,
  346. vod_tags: 'mv',
  347. // vod_director: '🆙 ' + up_name + ' 👥 ' + up_info.follower + ' ' + relation,
  348. vod_director: '🆙 ' + '[a=cr:' + JSON.stringify({'id':up_name + '_clicklink','name':up_name}) + '/]' + up_name + '[/a]' + ' 👥 ' + up_info.follower + ' ' + relation,
  349. vod_actor: '▶' + stat.view + ' ' + '💬' + stat.danmaku + ' ' + '👍' + stat.like + ' ' + '💰' + stat.coin + ' ' + '⭐' + stat.favorite,
  350. vod_content: desc
  351. };
  352. let ja = jo.pages;
  353. let treeMap = {};
  354. let playurls = [];
  355. ja.forEach(function(tmpJo) {
  356. let cid = tmpJo.cid;
  357. let part = tmpJo.part.replaceAll('#', '﹟').replaceAll('$', '﹩');
  358. playurls.push(
  359. part + '$' + aid + '_' + cid
  360. )
  361. });
  362. treeMap['B站'] = playurls.join('#');
  363. let relatedData = JSON.parse(html).data.Related;
  364. playurls = [];
  365. relatedData.forEach(function(rd) {
  366. let ccid = rd.cid;
  367. let title = rd.title.replaceAll('#', '﹟').replaceAll('$', '﹩');
  368. let aaid = rd.aid;
  369. playurls.push(
  370. title + '$' + aaid + '_' + ccid
  371. )
  372. });
  373. treeMap['欧歌推荐'] = playurls.join('#');
  374. vod.vod_play_from = Object.keys(treeMap).join("$$$");
  375. vod.vod_play_url = Object.values(treeMap).join("$$$");
  376. VOD = vod;
  377. `,
  378. 搜索: `js:
  379. let html = request(input);
  380. function stripHtmlTag(src) {
  381. return src.replace(/<\\/?[^>]+(>|$)/g, '').replace(/&.{1,5};/g, '').replace(/\\s{2,}/g, ' ');
  382. }
  383. function turnDHM(duration) {
  384. let min = '';
  385. let sec = '';
  386. try {
  387. min = duration.split(':')[0];
  388. sec = duration.split(':')[1];
  389. } catch (e) {
  390. min = Math.floor(duration / 60);
  391. sec = duration % 60;
  392. }
  393. if (isNaN(parseInt(duration))) {
  394. return '无效输入';
  395. }
  396. if (min == 0) {
  397. return sec + '秒'
  398. } else if (0 < min && min < 60) {
  399. return min + '分'
  400. } else if (60 <= min && min < 1440) {
  401. if (min % 60 == 0) {
  402. let h = min / 60;
  403. return h + '小时'
  404. } else {
  405. let h = min / 60;
  406. h = (h + '').split('.')[0];
  407. let m = min % 60;
  408. return h + '小时' + m + '分';
  409. }
  410. } else if (min >= 1440) {
  411. let d = min / 60 / 24;
  412. d = (d + '').split('.')[0];
  413. let h = min / 60 % 24;
  414. h = (h + '').split('.')[0];
  415. let m = min % 60;
  416. let dhm = '';
  417. if (d > 0) {
  418. dhm = d + '天'
  419. }
  420. if (h >= 1) {
  421. dhm = dhm + h + '小时'
  422. }
  423. if (m > 0) {
  424. dhm = dhm + m + '分'
  425. }
  426. return dhm
  427. }
  428. return null
  429. }
  430. let videos = [];
  431. let vodList = JSON.parse(html).data.result;
  432. vodList.forEach(function(vod) {
  433. let aid = vod.aid;
  434. let title = stripHtmlTag(vod.title);
  435. let img = vod.pic;
  436. if (img.startsWith('//')) {
  437. img = 'https:' + img;
  438. }
  439. let remark = turnDHM(vod.duration);
  440. videos.push({
  441. vod_id: aid,
  442. vod_name: title,
  443. vod_pic: img,
  444. vod_remarks: remark
  445. })
  446. });
  447. VODS = videos
  448. `,
  449. }