bilibili下载视频

获取bilibili视频flv下载地址

  1. // ==UserScript==
  2. // @name bilibili下载视频
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.2.2
  5. // @description 获取bilibili视频flv下载地址
  6. // @author bibi
  7. // @require http://ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.4.min.js
  8. // @match *://*.bilibili.com/video/*
  9. // @include https://www.bibibili.com/video/*
  10. // @grant GM_xmlhttpRequest
  11. // @grant GM_download
  12. // @grant GM_getValue
  13. // @grant GM_setValue
  14. // @grant GM_notification
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. 'use strict';
  19. /*
  20. * 公共变量区
  21. */
  22. const scriptVersion = GM_info.script.version.trim(); //本程序的版本
  23. const scriptIcon = GM_info.script.icon64 || GM_info.script.icon; //本程序的图标
  24. const scriptName = "bilibilidownload";
  25. var currentUrl=document.URL;
  26. var aria2Port=6800;
  27. //定义数据数组
  28. //存储cid序列,用于分p记录
  29. var allcid=[];
  30. //存储{名字;url;cid}
  31. var urlArray=new Array();
  32. //当前p
  33. var whichP=0;
  34. //从全局变量中得到sessdata,用于下载.
  35. var sessdata="";
  36.  
  37.  
  38. /******************************************获取下载地址 start********************************************************/
  39. //获取bv号
  40. function getBV(){
  41. //页面获取 bv号
  42. var bvCode=currentUrl.split("?")[0];
  43. var bvArray=bvCode.split("/");
  44. //获取当前分p
  45. if(currentUrl.split("?")[1]){
  46. var P=currentUrl.split("?")[1];
  47. if(P.length>2 && P.substr(0, 2) == "p="){
  48. whichP=parseInt(P.split("=")[1])-1;
  49. }else{
  50. whichP=0;
  51. }
  52. }else{
  53. //否则当前p为第一p
  54. whichP=0;
  55. }
  56. return bvArray[4];
  57. }
  58.  
  59. //根据bv号获取aid cid
  60. function getAidAndCid() {
  61. var bv =getBV();
  62. var url="https://api.bilibili.com/x/web-interface/view?bvid="+bv;
  63. return new Promise((resolve,reject)=>{
  64. $.get(url,
  65. {},
  66. function (body){
  67. var data={};
  68. data.aid=body.data.aid;
  69. data.cids=new Array();
  70. for (let i = 0; i < body.data.pages.length; i++) {
  71. var mycid={};
  72. mycid.cid=body.data.pages[i].cid;
  73. mycid.name=body.data.pages[i].part;
  74. data.cids[i]=mycid;
  75. //维护一个cid数组
  76. allcid[i]=body.data.pages[i].cid;
  77. }
  78. //返回数据
  79. resolve(data);
  80. }
  81. )
  82.  
  83. });
  84. }
  85.  
  86. //获取下载url
  87. function getDownUrl(data) {
  88. return new Promise((resolve,reject)=>{
  89. //console.log(data);
  90. //https://api.bilibili.com/x/player/playurl/
  91. let myurl="https://api.bilibili.com/x/player/playurl?"
  92. //根据获取aidcid 获得真实的下载地址。
  93. const promiseArray=[];
  94. let i=0;
  95. data.cids.forEach((key)=>{
  96. let url=myurl+"avid="+data.aid+"&cid="+key.cid+"&qn=80";
  97. let promise=promiseGetUrl(url,key);
  98. promiseArray[i]=promise;
  99. i++;
  100. })
  101. //获取结果数组
  102. resolve(Promise.all(promiseArray));
  103. });
  104. }
  105.  
  106. //promiseGetUrl 获取多p视频的url
  107. function promiseGetUrl(url,key) {
  108. //大于480画质需要验证是否登陆
  109. //设置cookie
  110. return new Promise((resolve,reject)=>{
  111.  
  112. GM_xmlhttpRequest({
  113. method: 'GET',
  114. url: url,
  115. headers: {
  116. 'Accept':' application / JSON',
  117. 'Cookie':'SESSDATA='+sessdata+';',
  118. },
  119. onload: function(body) {
  120. var myport={};
  121. //console.log(body.responseText);
  122. var mybody=JSON.parse(body.responseText);
  123. myport.name=key.name;
  124. myport.cid=key.cid;
  125. myport.url=mybody.data.durl[0].url;
  126. resolve(myport);
  127. }
  128. });
  129. });
  130. }
  131.  
  132.  
  133. function get(){
  134. //获取aidcid
  135. getAidAndCid().then((data)=>{
  136. return getDownUrl(data)
  137.  
  138. }).then((data)=>{
  139. //data为数组
  140. data.forEach((key)=>{
  141. //console.log(key.name);
  142. //console.log(key.url);
  143. //console.log(key.cid);
  144. //rpcAria2_2(key,bv);
  145. });
  146. //将数据存放至全局数组
  147. urlArray=data;
  148. });
  149. }
  150. /******************************************设置下载地址end********************************************************/
  151.  
  152. //设置b站sessdata 因为httponly 无法在cookie中获取
  153. //不设置只能下载480p视频
  154. function setSessdata(biliSessdata){
  155. //保存
  156. if(biliSessdata!=null&&biliSessdata!=""){
  157. GM_setValue("bilibilidown-sessdata",biliSessdata);
  158. GM_notification({text:"设置已保存", title:scriptName, image:scriptIcon});
  159. }else{
  160. GM_notification({text:"设置失败,不能为空", title:scriptName, image:scriptIcon});
  161. }
  162. //返回
  163. return
  164. }
  165.  
  166. //设置Aria2Part 因为用户可能更改端口号
  167. //不设置只能下载480p视频
  168. function setAria2Part(inputbiliSessdata){
  169. //保存
  170. if(inputbiliSessdata!=null&&inputbiliSessdata!=""){
  171. GM_setValue('Aria2Part',inputbiliSessdata);
  172. GM_notification({text:"aria2c端口已保存", title:scriptName, image:scriptIcon});
  173. }else{
  174. GM_notification({text:"设置失败,不能为空", title:scriptName, image:scriptIcon});
  175. }
  176. //返回
  177. return
  178. }
  179.  
  180. /******************************************设置界面ui start********************************************************/
  181. // 设置界面ui
  182. function setUI(){
  183.  
  184. var ui2="<div class='bilibili-dropdown' style='position: relative;display: inline-block'>"+
  185. "<button class='bilibili-dropbtn' style=''background-color: #4CAF50;color: white;padding: 16px;font-size: 16px;border: none;cursor: pointer''>点击下载</button>"+
  186. "<div class='bilibili-dropdown-content' style='display: none;background-color: #f9f9f9;min-width: 160px;box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);'>"+
  187. "<li><a id=copyOneUrl href='#'>复制本p</a></li>"+
  188. "<li><a id=copyAllUrl href='#'>复制全部p</a>"+
  189. "<li><a id=sendOneUrltoAria2 href='#'>发送本p到aria2</a></li>"+
  190. "<li><a id=sendAllUrltoAria2 href='#'>发送全部到aria2</a></li>"+
  191. "<li><input type='text' id='inputSessdata' ></li>"+
  192. "<li><a id=setSessdata href='#'>设置sessdata</a></li>"+
  193. "<li><input type='text' id='inputAria2Port'value='6800'></li>"+
  194. "<li><a id='setAria2Port' href='#'>设置aria2端口号</a></li>"
  195.  
  196. "</div>"+
  197. "</div>";
  198. var uiStr = "<div href='javascript:void(0)' target='_blank' id='bilibilisetUi' style='cursor:pointer;z-index:98;display:block;width:60px;height:30px;line-height:30px;position:fixed;left:0;top:400px;text-align:center;overflow:visible'>"+ui2+"</div>";
  199. //console.log(uiStr);
  200. $("body").append(uiStr);
  201.  
  202. }
  203. /********************************************设置界面ui end******************************************************/
  204.  
  205. function getwhencilck( ){
  206. $("#bilibilisetUi").click(function(){
  207. get();
  208. $("#bilibilisetUi").mouseover(function(){
  209. //显示下拉菜单
  210. $(".bilibili-dropdown-content").css('display','block');
  211. });
  212.  
  213. $("#bilibilisetUi").mouseout(function(){
  214. $(".bilibili-dropdown-content").css('display','none');
  215. });
  216. /************************************************************绑定事件 start***********************************************/
  217. //绑定事件 点击下载本p视频
  218. $(".bilibili-dropbtn").click(function(){
  219. getBV();
  220. var innerP=0;
  221. var whichPCid=allcid[whichP];
  222. for(var i=0;i<urlArray.length;i++){
  223. if(whichPCid==urlArray[i].cid){
  224. innerP=i;
  225. }
  226. }
  227.  
  228. function func(){
  229. GM_notification({text:"下载完成", title:scriptName, image:scriptIcon});
  230. };
  231. var details={
  232. url:urlArray[innerP].url,
  233. headers:{
  234. referer:document.URL
  235. },
  236. name:urlArray[innerP].name+".flv",
  237. onload:func
  238. };
  239. //调用gm下载
  240. GM_download(details);
  241. GM_notification({text:"文件正在下载中,不要关闭本网页", title:scriptName, image:scriptIcon});
  242. return false;
  243. })
  244.  
  245. //复制本p下载Url
  246. $("#copyOneUrl").click(function(){
  247. getBV();
  248. var innerP=0;
  249. var whichPCid=allcid[whichP];
  250. for(var i=0;i<urlArray.length;i++){
  251. if(whichPCid==urlArray[i].cid){
  252. innerP=i;
  253. }
  254. }
  255. //console.log(urlArray[innerP].cid);
  256. var tag = document.createElement('input');
  257. tag.setAttribute('id', 'cp_hgz_input');
  258. tag.value = urlArray[innerP].url;
  259. document.getElementsByTagName('body')[0].appendChild(tag);
  260. document.getElementById('cp_hgz_input').select();
  261. document.execCommand('copy');
  262. document.getElementById('cp_hgz_input').remove();
  263. return false;
  264. })
  265.  
  266. //复制全部下载Url
  267. $("#copyAllUrl").click(function(){
  268.  
  269. var tag = document.createElement('input');
  270. tag.setAttribute('id', 'cp_hgz_input');
  271. for(var i=0;i<=urlArray.length;i++){
  272. tag.value =tag.value+urlArray[i].url;
  273. }
  274. document.getElementsByTagName('body')[0].appendChild(tag);
  275. document.getElementById('cp_hgz_input').select();
  276. document.execCommand('copy');
  277. document.getElementById('cp_hgz_input').remove();
  278. return false;
  279. })
  280. //发送本p到aria2
  281. $("#sendOneUrltoAria2").click(function(){
  282. //得到的数组可能和cid不对应
  283. getBV();
  284. var innerP=0;
  285. var whichPCid=allcid[whichP];
  286. for(var i=0;i<urlArray.length;i++){
  287. if(whichPCid==urlArray[i].cid){
  288. innerP=i;
  289. }
  290. }
  291. let json_rpc = {
  292. id:'',
  293. jsonrpc:'2.0',
  294. method:'aria2.addUri',
  295. //"method":'system.listMethods',
  296. params:[
  297. [urlArray[innerP].url],
  298. {
  299. out:urlArray[innerP].name+".flv",
  300. referer:currentUrl,
  301.  
  302. }
  303. ]
  304. }
  305. let data=JSON.stringify(json_rpc);
  306. console.log(data);
  307. //发送到本地aria2
  308. $.post(
  309. 'http://localhost:'+aria2Port+'/jsonrpc',
  310. data,
  311. function(body){
  312. console.log(body);
  313. if(body=="error"){
  314. GM_notification({text:"发送失败 请检查aria2端口", title:scriptName, image:scriptIcon});
  315. }else{
  316. GM_notification({text:"发送成功", title:scriptName, image:scriptIcon});
  317. }
  318. }
  319. );
  320. return false;
  321. })
  322. //发送全部p到aria2
  323. $("#sendAllUrltoAria2").click(function(){
  324. for(var i=0;i<=urlArray;i++){
  325. let json_rpc = {
  326. id:'',
  327. jsonrpc:'2.0',
  328. method:'aria2.addUri',
  329. //"method":'system.listMethods',
  330. params:[
  331. [urlArray[i].url],
  332. {
  333. out:urlArray[i].name+".flv",
  334. referer:currentUrl,
  335.  
  336. }
  337. ]
  338. }
  339. let data=JSON.stringify(json_rpc);
  340. //发送到本地aria2
  341. $.post(
  342. 'http://localhost:'+aria2Port+'/jsonrpc',
  343. data,
  344. function(body){
  345. console.log(body);
  346. }
  347. );
  348. }
  349. return false;
  350. })
  351.  
  352. //设置sessdata 如果不设置sessiondata 下载的文件最高为480p
  353. $("#setSessdata").click(function(){
  354. var data=$("#inputSessdata").val();
  355. //console.log(data);
  356. setSessdata(data);
  357. return false;
  358. })
  359.  
  360. //设置aria2端口号
  361. $("#setAria2Port").click(function(){
  362. var data=$("#inputAria2Port").val();
  363. setAria2Part(data);
  364. return false;
  365. })
  366.  
  367. //
  368. var sess=GM_getValue("bilibilidown-sessdata");
  369. console.log(sess);
  370. if(sess!=""&&sess!=null){
  371. sessdata=sess;
  372. };
  373. $("#inputSessdata").val(sessdata);
  374. /************************************************************绑定事件 end***********************************************/
  375. $('#bilibilisetUi').unbind("click");
  376. });
  377. };
  378. //get();
  379. setUI();
  380. getwhencilck();
  381. setInterval(function() {
  382. if(currentUrl==document.URL) {
  383. //console.log(currentUrl);
  384. }else{
  385. currentUrl=document.URL;
  386. //console.log(currentUrl);
  387. //取消事件。
  388. //$("#bilibilisetUi").unbind("mouseover");
  389. //$(".bilibili-dropbtn").unbind("click");
  390. //$("#bilibilisetUi").children().unbind();
  391. //getwhencilck( );
  392. }
  393. }, 3000);
  394. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址