视频解析接口调用

替换v.qq.com搜索页播放链接

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         视频解析接口调用
// @namespace    vqq
// @version      0.2
// @description  替换v.qq.com搜索页播放链接
// @author       unknownuser001
// @match        https://v.qq.com/x/search/?q=*
// @icon         data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAdBJREFUWEftlrtLw1AYxc+X3rZpY3FxFGd3cRH8AxxFECcfLT4WK2qkgh2iiw/qi6qLoC4uDuLi7tBNwcFJBRcdRURabfr6pEVBBZNrG8nSzIfv/O6537mE4PJHLvujDlBPwDaB5V1u9gj0MINLRRzHhunBycW1BFjZ506FcQogVDFlZEFIpPNYNEbp1QkQS4DEHl8AaPtpxIx7APpMhI5qhbADyAMQFiZnCiE6NURX1YLYAbDE4BIYhyhgSh+lRwn9N4kTAB/rgSciLLRo2OrtpaIsiGMAn4YMXBIjqkcoJQPhOEClLAwmwgELjM/0U8YK5F8Avhju62EKuwfAyKXvoRkGFX6DsExgIG7KtODXAxIBoWefmkyS6QpAQ4Cut+d8rVVfQbUJlE8eVOk24Pd2rOrWb4PjV+D34k1Thb4e8+zUXMO/JKAQs6Z5Tpqyos8wKCdjXtY4koCm0p0a8HatTdONrPGnzhJgMG6yVQ1UPz03BpTIii6O/2osBTAyb2bMPII/hwsPiqGgktyIeSerNZYCmE4Ux55e8julUnmvgUqvVSXl84tuu+2WBbP9JZtI5NpRoNnKQMFLm7rvXHa4jM4WQGZILZo6QD0B1xN4B/iKmyF8Ne2sAAAAAElFTkSuQmCC
// @grant		 GM_addStyle
// @grant		 GM_getValue
// @grant		 GM_setValue
// @grant		 GM_registerMenuCommand
// @license      AGPL License
// ==/UserScript==


// 解析接口来自
// https://greasyfork.org/zh-CN/scripts/418804
const originalInterfaceList = [
	{"name":"乐多资源","category":"1","url":"https://api.leduotv.com/wp-api/ifr.php?isDp=1&vid=", "id":"leduotv"},
	{"name":"M3U8.TV","category":"1","url":"https://jx.m3u8.tv/jiexi/?url=", "id":"m3u8"},
	{"name":"人人迷","category":"1","url":"https://jx.blbo.cc:4433/?url=", "id":"blbo"},
	{"name":"七哥","category":"1","url":"https://jx.mmkv.cn/tv.php?url=", "id":"mmkv"},
	{"name":"冰豆","category":"1","url":"https://api.qianqi.net/vip/?url=", "id":"qianqi"},
	{"name":"迪奥","category":"1","url":"https://123.1dior.cn/?url=", "id":"1dior"},
	{"name":"CK","category":"1","url":"https://www.ckplayer.vip/jiexi/?url=", "id":"ckplayer"},
	{"name":"游艺","category":"1","url":"https://api.u1o.net/?url=", "id":"u1o"},
	{"name":"LE","category":"1","url":"https://lecurl.cn/?url=", "id":"lecurl"},
	{"name":"ckmov","category":"1","url":"https://www.ckmov.vip/api.php?url=", "id":"ckmovvip"},
	{"name":"ccyjjd","category":"1","url":"https://ckmov.ccyjjd.com/ckmov/?url=", "id":"ccyjjd"},
	{"name":"爱豆","category":"1","url":"https://jx.aidouer.net/?url=", "id":"aidouer"},
	{"name":"诺诺","category":"1","url":"https://www.ckmov.com/?url=", "id":"ckmovcom"},
	{"name":"H8","category":"1","url":"https://www.h8jx.com/jiexi.php?url=", "id":"h8jx"},
	{"name":"BL","category":"1","url":"https://vip.bljiex.com/?v=", "id":"bljiex"},
	{"name":"解析la","category":"1","url":"https://api.jiexi.la/?url=", "id":"jiexila"},
	{"name":"MUTV","category":"1","url":"https://jiexi.janan.net/jiexi/?url=", "id":"janan"},
	{"name":"MAO","category":"1","url":"https://www.mtosz.com/m3u8.php?url=", "id":"mtosz"},
	{"name":"老板","category":"1","url":"https://vip.laobandq.com/jiexi.php?url=", "id":"laobandq"},
	{"name":"盘古","category":"1","url":"https://www.pangujiexi.cc/jiexi.php?url=", "id":"pangujiexi"},
	{"name":"盖世","category":"1","url":"https://www.gai4.com/?url=", "id":"gai4"},
	{"name":"小蒋","category":"1","url":"https://www.kpezp.cn/jlexi.php?url=", "id":"kpezp"},
	{"name":"YiTV","category":"1","url":"https://jiexi.us/?url=", "id":"jiexius"},
	{"name":"星空","category":"1","url":"http://60jx.com/?url=", "id":"60jx"},
	{"name":"0523","category":"1","url":"https://go.yh0523.cn/y.cy?url=", "id":"yh0523"},
	{"name":"17云","category":"1","url":"https://www.1717yun.com/jx/ty.php?url=", "id":"1717yun"},
	{"name":"4K","category":"1","url":"https://jx.4kdv.com/?url=", "id":"4kdv"},
	{"name":"云析","category":"1","url":"https://jx.yparse.com/index.php?url=", "id":"yparse"},
	{"name":"8090","category":"1","url":"https://www.8090g.cn/?url=", "id":"8090g"},
	{"name":"江湖","category":"1","url":"https://api.jhdyw.vip/?url=", "id":"jhdyw"},
	{"name":"诺讯","category":"1","url":"https://www.nxflv.com/?url=", "id":"nxflv"},
	{"name":"PM","category":"1","url":"https://www.playm3u8.cn/jiexi.php?url=", "id":"playm3u8"},
	{"name":"奇米","category":"1","url":"https://qimihe.com/?url=", "id":"qimihe"},
	{"name":"思云","category":"1","url":"https://jx.ap2p.cn/?url=", "id":"ap2p"},
	{"name":"听乐","category":"1","url":"https://jx.dj6u.com/?url=", "id":"dj6u"},
	{"name":"aijx","category":"1","url":"https://jiexi.t7g.cn/?url=", "id":"t7g"},
	{"name":"52","category":"1","url":"https://vip.52jiexi.top/?url=", "id":"52jiexi"},
	{"name":"黑米","category":"1","url":"https://www.myxin.top/jx/api/?url=", "id":"myxin"},
	{"name":"豪华啦","category":"1","url":"https://api.lhh.la/vip/?url=", "id":"lhh"},
	{"name":"凉城","category":"1","url":"https://jx.mw0.cc/?url=", "id":"mw0"},
	{"name":"33t","category":"1","url":"https://www.33tn.cn/?url=", "id":"33tn"},
	{"name":"180","category":"1","url":"https://jx.000180.top/jx/?url=", "id":"000180"},
	{"name":"无名","category":"1","url":"https://www.administratorw.com/video.php?url=", "id":"administratorw"},
	{"name":"黑云","category":"1","url":"https://jiexi.380k.com/?url=", "id":"380k"},
	{"name":"九八","category":"1","url":"https://jx.youyitv.com/?url=", "id":"youyitv"},
	{"name":"综合线路解析","category":"2","url":"https://www.xixicai.top/mov/s/?sv=3&url=", "id":"xixicai"},
	{"name":"纯净/B站","category":"2","url":"https://z1.m1907.cn/?jx=", "id":"m1907"},
	{"name":"高速接口","category":"2","url":"https://jsap.attakids.com/?url=", "id":"attakids"},
	{"name":"综合/B站1","category":"2","url":"https://vip.parwix.com:4433/player/?url=", "id":"parwix"},
	{"name":"OK解析","category":"2","url":"https://okjx.cc/?url=", "id":"okjx"},
	{"name":"夜幕","category":"2","url":"https://www.yemu.xyz/?url=", "id":"yemu"},
	{"name":"虾米","category":"2","url":"https://jx.xmflv.com/?url=", "id":"xmflv"},
	{"name":"全民","category":"2","url":"https://jx.quanmingjiexi.com/?url=", "id":"quanmingjiexi"},
];

const noSiteId = '__no_parse_site__';

let SelectedSite;
initSelectedSite();

const __app_main__ = function() {

	injectCss();
	injectSiteSelectorButton();
	setTimeout(openFoldItemsAdnInjectLink, 1000);
	GM_registerMenuCommand('选择解析站点', showSiteSelectorWindow);
}

function openFoldItemsAdnInjectLink() {
	if (openFoldItems()) {
		setTimeout(injectLink, 1000);
	} else {
		injectLink();
	}
}

function openFoldItems() {
	//展开所有剧集
	let foldBtns = document.querySelectorAll('div.item_fold > a');
	let foldClicked = false;
	for (let i = 0; i < foldBtns.length; i++) {
		if (foldBtns[i].parentElement.className.indexOf('item_unfold') < 0) {
			foldBtns[i].click();
			foldClicked = true;
		}
	}
	return foldClicked;
}

function injectLink() {
	let link1 = Array.prototype.slice.call(document.querySelectorAll('div.item > a'), 0);
	let link2 = Array.prototype.slice.call(document.querySelectorAll('div._playlist > div.result_btn_line > a.btn_primary'), 0);
	let link3 = Array.prototype.slice.call(document.querySelectorAll('div._infos > div > a.figure'), 0);
	let link4 = Array.prototype.slice.call(document.querySelectorAll('div._infos > div > h2.result_title > a'), 0);
	let link5 = Array.prototype.slice.call(document.querySelectorAll('div.info_item.info_item_desc > span.desc_text > a.desc_more'), 0);
	let aniLinks = [];
	let itemLinks = link1.concat(link2).concat(link3).concat(link4).concat(link5);
	for (let i = 0; i < itemLinks.length; i++) {
		let itemLink = itemLinks[i];
		let noClassItemFold = (itemLink.parentElement.className.indexOf('item_unfold') < 0);
		let noClassItemUnFold = (itemLink.parentElement.className.indexOf('item_fold') < 0);
		let parsedUrl = parseUrl(itemLink.href);
		let isRedirectSearchReuslt = (parsedUrl.pathname.indexOf('search_redirect.html') > 0);
		let oUrl;
		if (itemLink.attributes.oUrl == undefined) {
			if (isRedirectSearchReuslt) {
				oUrl = parsedUrl.query.url;
				if (oUrl.indexOf('?') > 0) {
					oUrl = oUrl.split('?')[0];
				} else {
					oUrl = '';
				}
			} else {
				oUrl = itemLink.href;
			}
		} else {
			oUrl = itemLink.attributes.oUrl;
		}

		if (noClassItemUnFold && noClassItemFold) {
			itemLink.attributes.oUrl = oUrl;
			itemLink.href = SelectedSite.url + oUrl;
			if (itemLink.parentNode.classList.contains('item')) {
				let mark = itemLink.parentNode.querySelector('span');
				aniLinks.push(itemLink);
				if (mark != undefined && mark.attributes.labelFree != true) {
				    mark.className += " hide-mark";
				} else {
					mark = document.createElement('span');
					itemLink.parentNode.appendChild(mark);
				}
			}
		} else if (!noClassItemUnFold) {
			itemLink.parentNode.remove();
		}
	}

	setTimeout(function(){
		for (let i = 0; i < aniLinks.length;i++) {
			let itemLink = aniLinks[i];
			let mark = itemLink.parentNode.querySelector('span');
			if (mark == undefined) {
				mark = document.createElement('span');
				itemLink.parentNode.appendChild(mark);
			}
			if (mark.attributes.labelFree == true) {
				continue;
			}
			mark.className = "mark_v";
			mark.className += ' free-video';
			mark.innerHTML = '免';
			mark.className += ' free-video-ani';
			mark.attributes.labelFree = true;
		}


		let tabResult = document.querySelectorAll('div._playlist div.result_tabs > a');
		if (tabResult == undefined) {
			return;
		}

		for ( let i = 0; i < tabResult.length; i++) {
			let t = tabResult[i];
			if (t.__event_added) {
				continue;
			}
			t.__event_added = true;
			t.addEventListener('click', function () {
				setTimeout(openFoldItemsAdnInjectLink, 1000);
			});
		}


	}, 1000);
	let allCover = document.querySelectorAll('div._infos > div > a > span.mark_v');
	for ( let i = 0 ; i < allCover.length; i++){
		allCover[i].innerHTML = '免费';
		allCover[i].className = allCover[i].className +' free-video-2';
	}
}



function parseQuery(search) {
	var args = search.substring(1).split('&');
	var argsParsed = {};
	var i, arg, kvp, key, value;
	for (i = 0; i < args.length; i++) {
		arg = args[i];
		if (-1 === arg.indexOf('=')) {
			argsParsed[decodeURIComponent(arg).trim()] = true;
		} else {
			kvp = arg.split('=');
			key = decodeURIComponent(kvp[0]).trim();
			value = decodeURIComponent(kvp[1]).trim();
			argsParsed[key] = value;
		}
	}
	return argsParsed;
}

function parseUrl(url) {
	let urlParser = document.createElement('a');
	urlParser.href = url;
	return {
		protocol: urlParser.protocol,
		host: urlParser.host,
		hostname: urlParser.hostname,
		port: urlParser.port,
		pathname: urlParser.pathname,
		query: parseQuery(urlParser.search),
		hash: urlParser.hash
	};
}

//https://codepen.io/avstorm/pen/jxjKGj
function injectCss() {
	let modalDialogCss = `
		#siteSelectorPopDiv{
			display: none;
			background-color: #f5f5f5;
			z-index: 11;
			width: 300px;
			height: 400px;
			position:fixed;
			top:0;
			right:0;
			left:0;
			bottom:0;
			margin:auto;
			border-radius: 10px;
			border: 2px solid #7d7d7d;
			border-width: 2px;
			box-shadow: 0 0 15px #7d7d7d;
		}

		#siteSelectorPopDiv .content-wrapper {
			overflow-y: scroll;
			height: 350px;
			width:295px;
		}
		#siteSelectorPopDiv .content {
			width: 95%;
			margin-top: 6px;
			display: grid;
			padding:5px;
			grid-template-columns: repeat(2, 130px);
			grid-column-gap: 10px;
			grid-row-gap: 5px;
			font-size: 9px;
		}
		#siteSelectorPopDiv .buttons {
			width:80%;
			margin:auto;
			display: flex;
			justify-content: space-between;
			padding-top: 8px;
		}

		#siteSelectorPopDiv .buttons > button {
			box-shadow:inset 0px 1px 0px 0px #ffffff;
			background:linear-gradient(to bottom, #f9f9f9 5%, #e9e9e9 100%);
			background-color:#f9f9f9;
			border-radius:6px;
			border:1px solid #dcdcdc;
			display:inline-block;
			cursor:pointer;
			color:#666666;
			font-family:Arial;
			font-size:15px;
			font-weight:bold;
			padding:6px 24px;
			text-decoration:none;
			text-shadow:0px 1px 0px #ffffff;
		}
		#siteSelectorPopDiv .buttons > button:hover {
			background:linear-gradient(to bottom, #e9e9e9 5%, #f9f9f9 100%);
			background-color:#e9e9e9;
		}
		#siteSelectorPopDiv .buttons > button:active {
			position:relative;
			top:1px;
		}

		input[type="radio"] {
		  vertical-align:middle;
		}

		.radio {
		  position: relative;
		  cursor: pointer;
		  font-size: 16px;
		  margin: 5px;
		  height: 24px;
		  overflow-y: hidden;
		  color: black;
		}
		.radio .label {
		  position: relative;
		  display: block;
		  float: left;
		  margin-right: 10px;
		  width: 20px;
		  height: 20px;
		  border: 2px solid #c8ccd4;
		  border-radius: 100%;
		  -webkit-tap-highlight-color: transparent;
		}
		.radio .label:after {
		  content: '';
		  position: absolute;
		  top: 5px;
		  left: 5px;
		  width: 10px;
		  height: 10px;
		  border-radius: 100%;
		  background: #0080c0;
		  transform: scale(0);
		  transition: all 0.2s ease;
		  opacity: 0.08;
		  pointer-events: none;
		}
		.radio:hover .label:after {
		  transform: scale(3.6);
		}
		input[type="radio"]:checked + .label {
		  border-color: #0080c0;
		}
		input[type="radio"]:checked + .label:after {
		  transform: scale(1);
		  transition: all 0.2s cubic-bezier(0.35, 0.9, 0.4, 0.9);
		  opacity: 1;
		}
		.hidden {
		  display: none;
		}

		.free-video {
		    color: #f8f8f8!important;
		    width: 16px!important;
		    height: 16px!important;
		    font-size: 12px!important;
		    text-align: center!important;
		    vertical-align: middle!important;
		    border-radius: 10px!important;
		    margin: 0!important;
		    background-image: linear-gradient(to right, #ff9569 0%, #e92758 100%)!important;
		    top: -2px!important;
		    right: -2px!important;
		    transform: rotate(30deg)!important;
			padding-bottom: 2px;
			padding-left: 1px;
			opacity: 90%;

		}

		.free-video-ani {
			transition: opacity 1s linear;
		}

		.free-video-2 {
			color: white!important;
			width: 30px!important;
			height: 20px!important;
			font-size: 12px!important;
			text-align: center!important;
			vertical-align: middle!important;
			border-radius: 5px!important;
			margin: 0!important;
			background-image: linear-gradient(#ff6429, #f5f900c9)!important;
			top: 2px!important;
			right: 2px!important;
			opacity: 70%;
		}

		.hide-mark {
		  visibility: hidden;
		  opacity: 0;
		  transition: visibility 0s 2s, opacity 1s linear;
		}
	`;
	GM_addStyle(modalDialogCss);
}

function closeSiteSelectorWindow() {
	let ssw = document.getElementById('siteSelectorPopDiv');
	if (ssw != undefined) {
		ssw.remove()
	}
}

function saveSiteSelectorWindow() {
	var siteRadios = document.getElementsByName("siteRadio");
	for (let i = 0; i < siteRadios.length; i++) {
		if (siteRadios[i].checked) {
			SelectedSite.id = siteRadios[i].value;
			GM_setValue('selectedSite', SelectedSite.id);
			initSelectedSite();
			injectSiteSelectorButton();
			openFoldItemsAdnInjectLink();
		}
	}
	closeSiteSelectorWindow();
}

function showSiteSelectorWindow() {
	let siteSelectorPopDiv = document.createElement('div');
	siteSelectorPopDiv.id = 'siteSelectorPopDiv';
	siteSelectorPopDiv.innerHTML = `
	<div class='content-wrapper'>
		<div class="content">
		</div>
	</div>
	<div class="buttons">
	    <button class="save">保存</button><button class="close">关闭</button>
	</div>
	`;
	document.body.appendChild(siteSelectorPopDiv);
	document.querySelector('#siteSelectorPopDiv > div.buttons > button.save')
		.addEventListener('click', saveSiteSelectorWindow);
	document.querySelector('#siteSelectorPopDiv > div.buttons > button.close')
		.addEventListener('click', closeSiteSelectorWindow);

	let selectorHtml = `
	<label for="${noSiteId}" class="radio">
		<input ${isNoSiteId(SelectedSite.id) ? 'checked' : ''} type="radio" class="hidden" name="siteRadio" id="${noSiteId}" value="${noSiteId}"/>
		<span class="label"></span>无解析
	</label>
	<span></span>
	`;

	originalInterfaceList.forEach(function(item, index) {
		selectorHtml += `
		<label for="${item.id}" class="radio">
			<input ${SelectedSite.id == item.id ? 'checked' : ''} + type="radio" class="hidden" name="siteRadio" id="${item.id}" value="${item.id}"/>
			<span class="label"></span>${item.name}
		</label>
		`;
	});

	document.querySelector('#siteSelectorPopDiv div.content').innerHTML = selectorHtml;

	siteSelectorPopDiv.style.display = 'block';
	return siteSelectorPopDiv;
}

function injectSiteSelectorButton(){

	let lastElement = document.querySelector('#search_container > div.search_tools > div > div.filter_tip.none');

	if (document.querySelector('#search_container div.filter_item > a.doParseLink') == undefined) {
		let doParseLinkButton = document.createElement('div');
		doParseLinkButton.innerHTML = '<a class="doParseLink" href="javascript:void(0)">〖点此解析〗</a>';
		doParseLinkButton.className = 'filter_item';
		document.querySelector('#search_container > div.search_tools > div').insertBefore(doParseLinkButton, lastElement);
		document.querySelector('#search_container div.filter_item > a.doParseLink').addEventListener('click', openFoldItemsAdnInjectLink);
	}

	if (document.querySelector('#search_container div.filter_item > a.openSiteSelector') == undefined) {
		let parseSite = document.createElement('div');
		parseSite.innerHTML = `<a class="openSiteSelector" href="javascript:void(0)">选择解析(当前:${SelectedSite.name})</a>`;
		parseSite.className = 'filter_item';
		document.querySelector('#search_container > div.search_tools > div').insertBefore(parseSite, lastElement);
		document.querySelector('#search_container div.filter_item > a.openSiteSelector').addEventListener('click', function(){
			showSiteSelectorWindow();
		});
	} else {
		document.querySelector('#search_container div.filter_item > a.openSiteSelector').innerHTML = `选择解析(当前:${SelectedSite.name})`;
	}

}

function initSelectedSite() {
	let name;
	let url;
	let id = GM_getValue('selectedSite');
	if (id == undefined) {
		id = 'xixicai';
	}
	originalInterfaceList.forEach(function(item, index) {
		if (id == item.id) {
			id = item.id;
			url = item.url;
			name = item.name;
		}
	});
	if ( isNoSiteId(id) || name == undefined) {
		SelectedSite = {
			"name": '无解析',
			"id": noSiteId,
			"url": ''
		};
		return;
	}
	SelectedSite = {
		"name": name,
		"id": id,
		"url": url
	}
};

function isNoSiteId(id){
	return id == noSiteId;
}


__app_main__();