// ==UserScript==
// @name 跟踪链接净化(B站, 百度)
// @name:zh-TW 跟蹤鏈接凈化(B站, 百度)
// @name:en Clean Tracking URLs (Bilibili, Baidu)
// @namespace https://greasyfork.org/en/scripts/456881
// @version 0.4.2
// @description 净化B站跟踪链接(推荐视频),百度<相关搜索、热搜>链接净化
// @description:zh-tw 凈化B站鏈接跟蹤(推薦視頻),百度<相關搜索、熱搜>鏈接凈化
// @description:en Clean Bilibili Tracking URLs (Recommended Videos), Baidu <Related Search><Hot Search> URLs.
// @author cilxe
// @match *://www.bilibili.com/*
// @match *://search.bilibili.com/*
// @match *://space.bilibili.com/*
// @match *://live.bilibili.com/*
// @match *://passport.bilibili.com/*
// @match *://account.bilibili.com/*
// @match *://message.bilibili.com/*
// @match *://member.bilibili.com/*
// @match *://t.bilibili.com/*
// @match *://app.bilibili.com/*
// @match *://www.baidu.com/s*
// @icon https://www.bilibili.com/favicon.ico
// @run-at document-body
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @license MIT
// ==/UserScript==
(() => {
const TIME_DELAY = 3000;
const INDEX_STRING_QM = '?';
// bilibili index strings
const INDEX_STRING_B1 = 'spm_id_from';
const INDEX_STRING_B2 = 'vd_source';
const INDEX_STRING_B3 = 'from_spmid';
// baidu index strings
const INDEX_STRING_BD1 = 'rsf';
const INDEX_STRING_BD2 = 'rsv_pq';
// If <true> block [Lucky Draw (The Selection)] popups at live.bilibili.com.
const BlockLivePopups = true;
const realLocation = window.location;
// Bilibili Restore history state session stack
function restoreState(indexStr) {
const URL = window.location.href;
const VideoIndex = URL.indexOf(indexStr);
const CleanURL = URL.substring(0, VideoIndex - 1);
window.history.replaceState({}, 'Restore', CleanURL);
}
function resetBiliMetadData() {
const metas = document.getElementsByTagName('meta');
for (let i = 0; i < metas.length; i += 1) {
if (metas[i].name === 'spm_prefix') {
metas[i].content = '000.0000';
}
}
}
// remove bilibili Ads
function removeBiliAds() {
function run() {
let index = 0;
do {
// Card-Ads
const cardAds = document.getElementsByTagName('a');
for (let i = 0; i < cardAds.length; i += 1) {
if (cardAds[i].hostname.includes('cm.bilibili.com')) {
cardAds[i].remove();
}
}
index += 1;
} while (index < 2);
}
run();
}
// // clean <a> links
function cleanBiliLinks() {
function run() {
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
const url = links[i].href;
const index = url.indexOf(INDEX_STRING_QM);
if (links[i].href.includes(INDEX_STRING_B1) || links[i].href.includes(INDEX_STRING_B3)) {
links[i].href = url.substring(0, index);
}
}
}
run();
setTimeout(() => { run(); }, 1000);
}
// block <a> link clicking events
function blockLinkEvents() {
function run() {
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
links[i].addEventListener('click', (e) => {
e.stopPropagation();
}, true);
}
}
run();
// bilibili home page button click (换一换)
const changeButtons = document.getElementsByClassName('primary-btn');
if (realLocation.href === 'https://www.bilibili.com/' && changeButtons != null) {
for (let i = 0; i < changeButtons.length; i += 1) {
changeButtons[i].addEventListener('click', () => {
run();
removeBiliAds();
setTimeout(() => { run(); removeBiliAds(); }, 1200);
});
}
}
}
// clean top menu events
function cleanBLTopMenu() {
setTimeout(() => {
const topEntries = document.getElementsByClassName('v-popover-wrap');
for (let i = 0; i < topEntries.length; i += 1) {
topEntries[i].addEventListener('mouseover', () => {
blockLinkEvents();
}, true);
const entryLinks = topEntries[i].getElementsByTagName('a');
for (let index = 0; index < entryLinks.length; index += 1) {
entryLinks[index].addEventListener('click', (e) => {
e.stopPropagation();
}, true);
}
}
const locItems = document.getElementsByClassName('loc-moveclip');
for (let i = 0; i < locItems.length; i += 1) {
locItems[i].addEventListener('click', (e) => {
e.stopPropagation();
}, true);
}
const rightItems = document.getElementsByClassName('right-entry__outside');
for (let i = 0; i < rightItems.length; i += 1) {
rightItems[i].addEventListener('click', (e) => {
e.stopPropagation();
}, true);
}
// 收藏 - 稍后再看
const favTabs = document.getElementsByClassName('tab-item');
for (let i = 0; i < favTabs.length; i += 1) {
favTabs[i].addEventListener('click', () => {
setTimeout(() => { blockLinkEvents(); }, 800);
}, true);
}
}, TIME_DELAY);
}
// www.bilibili.com/*, ww.bilibili.com/v/popular/*
function cleanBMainURL() {
restoreState(INDEX_STRING_B1);
restoreState(INDEX_STRING_B2);
function onFresh() {
// www.bilibili.com/v/popular/
function blockPopEvents() {
// block default events
const videoCards = document.getElementsByClassName('video-card__content');
for (let i = 0; i < videoCards.length; i += 1) {
videoCards[i].addEventListener('click', (e) => {
e.stopPropagation();
});
}
}
if (window.location.href.includes('www.bilibili.com/v/popular')) {
blockPopEvents();
// block navibar items clicking events
const naviItems = document.getElementsByClassName('nav-tabs__item');
for (let i = 0; i < naviItems.length; i += 1) {
naviItems[i].addEventListener('click', () => {
setTimeout(() => { blockPopEvents(); blockLinkEvents(); }, 700);
setTimeout(() => { blockPopEvents(); }, 1200);
});
}
// block traking link events after rank-tab clicked
const tagUL = document.getElementsByClassName('rank-tab')[0];
if (tagUL != null) {
const tagLIs = tagUL.getElementsByTagName('li');
for (let i = 0; i < tagLIs.length; i += 1) {
tagLIs[i].addEventListener('click', () => {
setTimeout(() => { blockLinkEvents(); }, 700);
});
}
}
}
}
onFresh();
removeBiliAds();
blockLinkEvents();
// Loop execution while scrolling
window.onscroll = () => {
let topScroll = 0;
// Scroll range
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
removeBiliAds();
blockLinkEvents();
onFresh();
topScroll = scrolls;
}
};
}
// bilibili search events
function blockBSearchItemEvents() {
function blockClickingEvents() {
// input suggested items
const suggestItems = document.getElementsByClassName('suggest-item');
for (let i = 0; i < suggestItems.length; i += 1) {
suggestItems[i].addEventListener('click', () => {
blockLinkEvents();
setTimeout(() => { blockLinkEvents(); }, 600);
});
}
// search trending items
const topSearchs = document.getElementsByClassName('trending-item');
for (let i = 0; i < topSearchs.length; i += 1) {
topSearchs[i].addEventListener('click', () => {
setTimeout(() => { blockLinkEvents(); }, 600);
});
}
// search history items
const historyItems = document.getElementsByClassName('history-item');
for (let i = 0; i < historyItems.length; i += 1) {
historyItems[i].addEventListener('click', () => {
setTimeout(() => { blockLinkEvents(); }, 600);
});
}
}
// search input area
const searchInputs = document.getElementsByClassName('search-input-el');
searchInputs[0].addEventListener('click', () => {
blockClickingEvents();
});
// clear icon
const clearIcon = document.getElementsByClassName('clear-icon')[0];
clearIcon.addEventListener('click', () => {
setTimeout(() => { blockClickingEvents(); }, 600);
});
}
// search.bilibili.com/*
function cleanBSearch() {
blockLinkEvents();
blockBSearchItemEvents();
// search button clicking event
const searchButtons = document.getElementsByClassName('search-button');
for (let i = 0; i < searchButtons.length; i += 1) {
searchButtons[i].addEventListener('click', () => {
restoreState(INDEX_STRING_B1);
setTimeout(() => { blockLinkEvents(); }, 700);
});
}
// paging button clicking event
const pageButtons = document.getElementsByClassName('vui_pagenation--btn');
for (let i = 0; i < pageButtons.length; i += 1) {
pageButtons[i].addEventListener('click', () => {
blockLinkEvents();
setTimeout(() => { blockLinkEvents(); }, 700);
restoreState(INDEX_STRING_B1);
});
}
setTimeout(() => { blockLinkEvents(); }, 700);
}
// www.bilibili.com/video/*
function cleanBVideoURL() {
// Restore State session
restoreState(INDEX_STRING_B1);
restoreState(INDEX_STRING_B2);
cleanBiliLinks();
const unfoldVideo = document.getElementsByClassName('rec-footer');
unfoldVideo[0].addEventListener('click', () => {
cleanBiliLinks();
restoreState(INDEX_STRING_B1);
setTimeout(() => { cleanBMainURL(); }, 500);
});
// loop execution while scrolling
window.onscroll = () => {
let topScroll = 0;
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
cleanBiliLinks();
removeBiliAds();
topScroll = scrolls;
}
};
// video episodes/collections tracking state after clicked
const episodes = document.getElementsByClassName('video-episode-card');
for (let i = 0; i < episodes.length; i += 1) {
episodes[i].addEventListener('click', () => {
cleanBiliLinks();
removeBiliAds();
setTimeout(() => {
restoreState(INDEX_STRING_B1); restoreState(INDEX_STRING_B2); blockLinkEvents();
}, 1500);
});
}
setTimeout(() => { restoreState(INDEX_STRING_B2); }, 1000);
}
// space.bilibili.com/*
function cleanBSpaceURL() {
cleanBLTopMenu(); // clean top menu events
cleanBiliLinks(); // clean <a> links
blockLinkEvents(); // block <a> links clicking events
// paging
const pageLinks = document.getElementsByClassName('be-pager');
for (let i = 0; i < pageLinks.length; i += 1) {
pageLinks[i].addEventListener('click', () => {
blockLinkEvents();
setTimeout(() => { blockLinkEvents(); }, TIME_DELAY - 1000);
});
}
// side navigation bar click events
const sideNavLinks = document.getElementsByClassName('text');
for (let i = 0; i < sideNavLinks.length; i += 1) {
sideNavLinks[i].addEventListener('click', () => {
blockLinkEvents();
setTimeout(() => { blockLinkEvents(); }, 1000);
});
}
// video sort navigation bar click events (Recent, Most Played, Most Stars)
const sortNavLinks = document.getElementsByClassName('be-tab-input');
for (let i = 0; i < sortNavLinks.length; i += 1) {
sortNavLinks[i].addEventListener('click', () => {
blockLinkEvents();
setTimeout(() => { blockLinkEvents(); }, 1000);
});
}
}
// live.bilibili.com/*
const livePopupBlock = (selection) => {
const iframes = document.getElementsByTagName('iframe');
for (let i = 0; i < iframes.length; i += 1) {
if (iframes[i].src.includes('live-lottery')) {
// document.getElementsByTagName('iframe')[2].style.visibility = 'hidden';
// document.getElementsByTagName('iframe')[2].style.opacity = 0;
// iframes[i].style.display = 'none';
if (selection === true) {
iframes[i].style.visibility = 'hidden';
} else {
iframes[i].style.visibility = '';
}
}
}
};
// Baidu related search, Hot search URL cleaning
function cleanBaiduURL() {
// all <a> links
function cleanLinks() {
// <a> class = "c-color-link"
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
if (links[i].href.includes(INDEX_STRING_BD1)) {
const index = links[i].href.indexOf(INDEX_STRING_BD1);
links[i].href = links[i].href.substring(0, index - 1);
}
if (links[i].href.includes(INDEX_STRING_BD2)) {
const index = links[i].href.indexOf(INDEX_STRING_BD2);
links[i].href = links[i].href.substring(0, index - 1);
}
}
}
// bottom of html paging block
function clearPages() {
const pageLinks = document.getElementById('page').getElementsByTagName('div')[0].getElementsByTagName('a');
for (let i = 0; i < pageLinks.length; i += 1) {
if (pageLinks[i].href.includes(INDEX_STRING_BD2)) {
const index = pageLinks[i].href.indexOf(INDEX_STRING_BD2);
pageLinks[i].href = pageLinks[i].href.substring(0, index - 1);
}
}
}
cleanLinks();
window.onscroll = () => {
let topScroll = 0;
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
cleanLinks();
clearPages();
topScroll = scrolls;
}
};
}
// Handle different sites
window.onload = () => {
const isBilibili = realLocation.hostname.includes('bilibili.com');
const isBMain = realLocation.hostname.includes('www.bilibili.com');
const isBVideo = realLocation.href.includes('www.bilibili.com/video');
const isBSearch = realLocation.hostname.includes('search.bilibili.com');
const isBSpace = realLocation.hostname.includes('space.bilibili.com');
const isBLive = realLocation.hostname.includes('live.bilibili.com');
const isBiliAccount = realLocation.hostname.includes('passport.bilibili.com') || realLocation.hostname.includes('account.bilibili.com');
const isBMessage = realLocation.hostname.includes('message.bilibili.com');
const isBMember = realLocation.hostname.includes('member.bilibili.com');
const isBTrends = realLocation.hostname.includes('t.bilibili.com');
const isBApp = realLocation.hostname.includes('app.bilibili.com');
const isBaidu = realLocation.hostname.includes('baidu.com');
// bilibili
if (isBilibili) {
resetBiliMetadData();
removeBiliAds();
// Restore history state session stack
if (realLocation.href.includes(INDEX_STRING_B1)) {
restoreState(INDEX_STRING_B1);
} else if (realLocation.href.includes(INDEX_STRING_B2)) {
restoreState(INDEX_STRING_B2);
}
if (isBMain) {
cleanBiliLinks();
cleanBLTopMenu();
blockLinkEvents();
setTimeout(() => { cleanBMainURL(); }, 600);
if (isBVideo) { cleanBVideoURL(); }
} else if (isBSearch) {
cleanBSearch(); // clean links
cleanBLTopMenu();
} else if (isBSpace) {
setTimeout(() => { cleanBSpaceURL(); }, 1000);
setTimeout(() => { cleanBSpaceURL(); }, TIME_DELAY);
} else if (isBLive) {
// block popups
const liveIntervalId = setInterval(livePopupBlock(BlockLivePopups), 1000);
setTimeout(() => { clearInterval(liveIntervalId); }, TIME_DELAY + 1000 * 200);
} else if (isBiliAccount || isBMessage || isBMember || isBTrends || isBApp) {
cleanBiliLinks();
resetBiliMetadData();
blockLinkEvents();
cleanBLTopMenu();
}
} else if (isBaidu) { // baidu <related search> <Hot search>
cleanBaiduURL();
setTimeout(() => { cleanBaiduURL(); }, 1000);
}
};
})();
/*
# Changelog
v0.4.2 2023.02.07
- Optimised events at the search-input-block. [Bilibili]
- Bug fixes. [search.bilibili.com/www.bilibili.com]
v0.4.1.2 2023.01.28
- Bug fixes and performance optimisation. [Bilibili]
v0.4.1.1 2023.01.25
- Expanded the effective pages of the script. [Bilibili]
v0.4.1.0 2023.01.23
- Performance optimisation and bug fixes.
- Code reduction.
v0.4.0.1 2023.01.21
- Clean other untracked links. [space.bilibili.com]
- Several bugs fixes. [bilibili.com]
v0.4.0 2023.01.20
- Clean Bilibili Video page collections clicking event URL state changes. [www.bilibili.com/video/]
- Clean Bilibili Search tracking events. [search.bilibili.com]
- Clean other tracking events (top-menu clicking). [Bilibili]
v0.3.8.3 2023.01.20
- Fixed tracking event after video sorting navigation bar items clicked. [space.bilibili.com]
v0.3.8.2 2023.01.19
- Fixed navibar items click events [www.bilibili.com/v/popular].
v0.3.8.1 2023.01.13
- Clean more links of Baidu.com
v0.3.8 2023.01.06
- Block Card-Ads for Bilibili. (And now blocked banner-ads & card-ads for Bilibili)
- Block [Lucky Draw (The Selection)] popup at [live.bilibili.com]. Disabled by default.
- (SET [{BlockLivePopups} = true] to enable it.)
- The script may add menus to unlock custom setting.
v0.3.7.1 2023.01.02
- Fixed [space.bilibili.com] effects after paged, navi-bar clicked or menu-item clicked.
- Added support to clean tracking url at [search.bilibili.com].
v0.3.7 2023-01-02
- Naming optimisation.
- Script handling optimisation. (Bilibili)
- Added support to block part of Bilibili Ads.
v0.3.6 2022.12.28
- Optimise Baidu related search URL, paging URL processing method.
v0.3.5 2022.12.27
- Script logic optimisation.
*/