// ==UserScript== // @name 哔哩哔哩番剧解锁大会员 (゜-゜)つロ 干杯~,B站视频下载、解析,A站视频下载、解析,集合了优酷、爱奇艺、腾讯、芒果、乐视、等全网VIP视频免费破解去广告,高清普清电视观看,增加对手机支持,持续更新 // @namespace aaa // @version 1.0 // @description 自用解析脚本,哔哩哔哩番剧解锁大会员,集合了优酷、爱奇艺、腾讯等全网VIP视频免费破解去广告,没有太多花哨,但是很好用,也会持续更新接口,方便看电影,此脚本仅用于学习研究,请勿用于商业用途,请大家支持正版。 // @author die // @namespace // @require https://cdn.bootcss.com/jquery/3.5.1/jquery.min.js // @require https://greasyfork.org/scripts/425555-qwjx/code/qwjx.js?version=925388 // @match *://v.qq.com/x/cover/* // @match *://m.v.qq.com/x/cover/* // @match *://v.qq.com/x/page/* // @match *://m.v.qq.com/x/page/* // @match *://m.v.qq.com/* // @match *://www.iqiyi.com/v* // @match *://www.iqiyi.com/* // @match *://m.iqiyi.com/kszt/* // @match *://www.iqiyi.com/kszt/* // @match *://v.youku.com/v_show/* // @match *://m.youku.com/alipay_video/* // @match *://w.mgtv.com/b/* // @match *://m.mgtv.com/b/* // @match *://www.mgtv.com/b/* // @match *://tv.sohu.com/v/* // @match *://m.tv.sohu.com/v/* // @match *://film.sohu.com/album/* // @match *://m.film.sohu.com/album/* // @match *://www.le.com/ptv/vplay/* // @match *://m.le.com/ptv/vplay/* // @match *://v.pptv.com/show/* // @match *://m.pptv.com/show/* // @match *://vip.pptv.com/show/* // @match *://www.acfun.cn/v/* // @match *://m.acfun.cn/v/* // @match *://www.bilibili.com/video/* // @match *://*.bilibili.com/*" // @match *://m.bilibili.com/video/* // @match *://www.bilibili.com/anime/* // @match *://m.bilibili.com/anime/* // @match *://www.bilibili.com/bangumi/play/* // @match *://m.bilibili.com/bangumi/play/* // @match *://vip.1905.com/play/* // @match *://www.wxtv.net/* // @match *://www.eggvod.cn/* // @license GPL License // @grant unsafeWindow // @grant GM_openInTab // @grant GM.openInTab // @grant GM_getValue // @grant GM.getValue // @grant GM_setValue // @grant GM.setValue // @grant GM_xmlhttpRequest // @grant GM.xmlHttpRequest // @grant GM_registerMenuCommand // @run-at document-idle // @connect bilibili.com // @connect iqiyi.com // @connect mgtv.com // @connect pl.hd.sohu.com // ==/UserScript== (async () => { if (window.location.host == 'www.zhihu.com') return; const playlistBaseUrl = 'https://lens.zhihu.com/api/videos/'; //const videoBaseUrl = 'https://video.zhihu.com/video/'; const videoId = window.location.pathname.split('/').pop(); // 视频id const menuStyle = 'transform:none !important; left:auto !important; right:-0.5em !important;'; const playerId = 'player'; const coverSelector = '#' + playerId + ' > div:first-child > div:first-child > div:nth-of-type(2)'; const controlBarSelector = '#' + playerId + ' > div:first-child > div:first-child > div:last-child > div:last-child > div:first-child'; const svgDownload = ''; let player = document.getElementById(playerId); let resolutionMap = {'标清': 'sd', '高清': 'ld', '超清': 'hd'}; let videos = []; // 存储各分辨率的视频信息 let downloading = false; function getBrowerInfo() { let browser = (function (window) { let document = window.document; let navigator = window.navigator; let agent = navigator.userAgent.toLowerCase(); // IE8+支持.返回浏览器渲染当前文档所用的模式 // IE6,IE7:undefined.IE8:8(兼容模式返回7).IE9:9(兼容模式返回7||8) // IE10:10(兼容模式7||8||9) let IEMode = document.documentMode; let chrome = window.chrome || false; let system = { // user-agent agent: agent, // 是否为IE isIE: /trident/.test(agent), // Gecko内核 isGecko: agent.indexOf('gecko') > 0 && agent.indexOf('like gecko') < 0, // webkit内核 isWebkit: agent.indexOf('webkit') > 0, // 是否为标准模式 isStrict: document.compatMode === 'CSS1Compat', // 是否支持subtitle supportSubTitle: function () { return 'track' in document.createElement('track'); }, // 是否支持scoped supportScope: function () { return 'scoped' in document.createElement('style'); }, // 获取IE的版本号 ieVersion: function () { let rMsie = /(msie\s|trident.*rv:)([\w.]+)/; let match = rMsie.exec(agent); try { return match[2]; } catch (e) { return IEMode; } }, // Opera版本号 operaVersion: function () { try { if (window.opera) { return agent.match(/opera.([\d.]+)/)[1]; } else if (agent.indexOf('opr') > 0) { return agent.match(/opr\/([\d.]+)/)[1]; } } catch (e) { return 0; } } }; try { // 浏览器类型(IE、Opera、Chrome、Safari、Firefox) system.type = system.isIE ? 'IE' : window.opera || (agent.indexOf('opr') > 0) ? 'Opera' : (agent.indexOf('chrome') > 0) ? 'Chrome' : //safari也提供了专门的判定方式 window.openDatabase ? 'Safari' : (agent.indexOf('firefox') > 0) ? 'Firefox' : 'unknow'; // 版本号 system.version = (system.type === 'IE') ? system.ieVersion() : (system.type === 'Firefox') ? agent.match(/firefox\/([\d.]+)/)[1] : (system.type === 'Chrome') ? agent.match(/chrome\/([\d.]+)/)[1] : (system.type === 'Opera') ? system.operaVersion() : (system.type === 'Safari') ? agent.match(/version\/([\d.]+)/)[1] : '0'; // 浏览器外壳 system.shell = function () { if (agent.indexOf('edge') > 0) { system.version = agent.match(/edge\/([\d.]+)/)[1] || system.version; return 'Edge'; } // 遨游浏览器 if (agent.indexOf('maxthon') > 0) { system.version = agent.match(/maxthon\/([\d.]+)/)[1] || system.version; return 'Maxthon'; } // QQ浏览器 if (agent.indexOf('qqbrowser') > 0) { system.version = agent.match(/qqbrowser\/([\d.]+)/)[1] || system.version; return 'QQBrowser'; } // 搜狗浏览器 if (agent.indexOf('se 2.x') > 0) { return '搜狗浏览器'; } // Chrome:也可以使用window.chrome && window.chrome.webstore判断 if (chrome && system.type !== 'Opera') { let external = window.external; let clientInfo = window.clientInformation; // 客户端语言:zh-cn,zh.360下面会返回undefined let clientLanguage = clientInfo.languages; // 猎豹浏览器:或者agent.indexOf("lbbrowser")>0 if (external && 'LiebaoGetVersion' in external) { return 'LBBrowser'; } // 百度浏览器 if (agent.indexOf('bidubrowser') > 0) { system.version = agent.match(/bidubrowser\/([\d.]+)/)[1] || agent.match(/chrome\/([\d.]+)/)[1]; return 'BaiDuBrowser'; } // 360极速浏览器和360安全浏览器 if (system.supportSubTitle() && typeof clientLanguage === 'undefined') { let storeKeyLen = Object.keys(chrome.webstore).length; let v8Locale = 'v8Locale' in window; return storeKeyLen > 1 ? '360极速浏览器' : '360安全浏览器'; } return 'Chrome'; } return system.type; }; // 浏览器名称(如果是壳浏览器,则返回壳名称) system.name = system.shell(); // 对版本号进行过滤过处理 // System.version = System.versionFilter(System.version); } catch (e) { // console.log(e.message); } return system; })(window); if (browser.name == undefined || browser.name == '') { browser.name = 'Unknown'; browser.version = 'Unknown'; } else if (browser.version == undefined) { browser.version = 'Unknown'; } return browser; } function fetchRetry(url, options = {}, times = 1, delay = 1000, checkStatus = true) { return new Promise((resolve, reject) => { // fetch 成功处理函数 function success(res) { if (checkStatus && !res.ok) { failure(res); } else { resolve(res); } } // 单次失败处理函数 function failure(error) { times--; if (times) { setTimeout(fetchUrl, delay); } else { reject(error); } } // 总体失败处理函数 function finalHandler(error) { throw error; } function fetchUrl() { return fetch(url, options) .then(success) .catch(failure) .catch(finalHandler); } fetchUrl(); }); } // 下载指定url的资源 async function downloadUrl(url, name = (new Date()).valueOf() + '.mp4') { let browser = getBrowerInfo(); // Greasemonkey 需要把 url 转为 blobUrl if (GM_info.scriptHandler == 'Greasemonkey') { let res = await fetchRetry(url); let blob = await res.blob(); url = URL.createObjectURL(blob); } // Chrome 可以使用 Tampermonkey 的 GM_download 函数绕过 CSP(Content Security Policy) 的限制 if (window.GM_download) { GM_download({url, name}); } else { // firefox 需要禁用 CSP, about:config -> security.csp.enable => false let a = document.createElement('a'); a.href = url; a.download = name; // a.target = '_blank'; document.body.appendChild(a); a.click(); document.body.removeChild(a); setTimeout(function () { URL.revokeObjectURL(url); }, 100); } } function humanSize(size) { let n = Math.log(size) / Math.log(1024) | 0; return (size / Math.pow(1024, n)).toFixed(0) + ' ' + (n ? 'KMGTPEZY'[--n] + 'B' : 'Bytes'); } if (!player) return; // 获取视频信息 const res = await fetchRetry(playlistBaseUrl + videoId, { headers: { 'referer': 'refererBaseUrl + videoId', 'authorization': 'oauth c3cef7c66a1843f8b3a9e6a1e3160e20' // in zplayer.min.js of zhihu } }, 3); const videoInfo = await res.json(); // 获取不同分辨率视频的信息 for (let [key, video] of Object.entries(videoInfo.playlist)) { video.name = key; if (!videos.find(v => v.width == video.width)) { videos.push(video); } } // 按分辨率大小排序 videos = videos.sort(function (v1, v2) { return v1.width == v2.width ? 0 : (v1.width > v2.width ? 1 : -1); }).reverse(); document.addEventListener('DOMNodeInserted', (evt) => { let domControlBar = evt.relatedNode.querySelector(':scope > div:last-child > div:first-child'); if (!domControlBar || domControlBar.querySelector('.download')) return; let domFullScreenBtn = domControlBar.querySelector(':scope > div:nth-last-of-type(1)'); let domResolutionBtn = domControlBar.querySelector(':scope > div:nth-last-of-type(3)'); let domDownloadBtn, defaultResolution, buttons; if (!domFullScreenBtn || !domFullScreenBtn.querySelector('button')) return; // 克隆分辨率菜单或全屏按钮为下载按钮 domDownloadBtn = (domResolutionBtn && (domResolutionBtn.className == domFullScreenBtn.className)) ? domResolutionBtn.cloneNode(true) : domFullScreenBtn.cloneNode(true); defaultResolution = domDownloadBtn.querySelector('button').innerText; // 生成下载按钮图标 domDownloadBtn.querySelector('button:first-child').outerHTML = domFullScreenBtn.cloneNode(true).querySelector('button').outerHTML; domDownloadBtn.querySelector('svg').innerHTML = svgDownload; domDownloadBtn.className = domDownloadBtn.className + ' download'; buttons = domDownloadBtn.querySelectorAll('button'); // button 元素添加对应的下载地址 buttons.forEach(dom => { let video = videos.find(v => v.name == resolutionMap[dom.innerText || defaultResolution]); video = video || videos[0]; dom.dataset.video = video.play_url; if (dom.innerText) { (dom.innerText = `${dom.innerText} (${humanSize(video.size)})`); } else if (buttons.length == 1) { dom.nextSibling.querySelector('div').innerText = humanSize(video.size); } }); // 鼠标事件 - 显示菜单 domDownloadBtn.addEventListener('pointerenter', () => { let domMenu = domDownloadBtn.querySelector('div:nth-of-type(1)'); if (domMenu) { domMenu.style.cssText = menuStyle + 'opacity:1 !important; visibility:visible !important'; } }); // 鼠标事件 - 隐藏菜单 domDownloadBtn.addEventListener('pointerleave', () => { let domMenu = domDownloadBtn.querySelector('div:nth-of-type(1)'); if (domMenu) { domMenu.style.cssText = menuStyle; } }); // 鼠标事件 - 选择菜单项 domDownloadBtn.addEventListener('pointerup', event => { if (downloading) { alert('当前正在执行下载任务,请等待任务完成。'); return; } let e = event.srcElement || event.target; while (e.tagName != 'BUTTON') { e = e.parentNode; } downloadUrl(e.dataset.video); }); // 显示下载按钮 domControlBar.appendChild(domDownloadBtn); }); })();