// ==UserScript==
// @name 跟踪链接净化(B站, 百度)
// @name:zh-TW 跟蹤鏈接凈化(B站, 百度)
// @name:en Clean Tracking URLs (Bilibili, Baidu)
// @namespace https://greasyfork.org/en/scripts/456881
// @version 0.4.5
// @description 净化B站跟踪链接(推荐视频),百度<相关搜索、热搜>链接净化
// @description:zh-tw 凈化B站鏈接跟蹤(推薦視頻),百度<相關搜索、熱搜>鏈接凈化
// @description:en Clean Bilibili Tracking URLs (Recommended Videos), Baidu <Related Search><Hot Search> URLs.
// @author cilxe
// @match *://*.bilibili.com/*
// @exclude *://*.bilibili.com/api/*
// @exclude *://api.bilibili.com/*
// @exclude *://api.*.bilibili.com/*
// @exclude *://bbq.bilibili.com/*
// @match *://www.baidu.com/*
// @match *://zhidao.baidu.com/*
// @match *://*.douyin.com/search/*
// @icon https://www.bilibili.com/favicon.ico
// @run-at document-start
// @license MIT
// ==/UserScript==
(() => {
const DELAY_TIME = { fast: 600, normal: 1000, slow: 3000 };
// Sites with its tracking or other params
const Indexes = {
bilibili: ['spm_id_from', 'spm_id', 'vd_source', 'from_spmid', 'csource',
'sourceFrom', 'hotRank', 'live_from', 'from', 'launch_id', 'msource', 'popular_rank',
'session_id', 'business', 'sort_field', 'broadcast_type', 'is_room_feed',
'is_live_full_webview', 'is_live_webview', 'refer_from', 'vt'],
baidu: ['rsf', 'rsv_pq', 'rsv_t', 'qid', 'rsv_dl', 'sa', 'rqid', 'oq', 'gpc', 'usm',
'tfflag', 'ie', 'bs', 'rqlang', 'tn', 'sc_us', 'wfr', 'for', 'from', 'topic_pn',
'rsp', 'rs_src', 'f', 'rsv_page', 'dyTabStr', 'tn', 'ct', 'lm', 'site', 'sites',
'fr', 'cl', 'bsst', 'lid', 'rsv_spt', 'rsv_bp', 'src', 'sfrom', 'utm_source',
'utm_medium', 'refer', 'zp_fr', 'channel'],
douyin: ['rsv_idx', 'hisfilter', 'source', 'aid', 'enter_from', 'focus_method', 'gid'],
};
const sites = [Indexes.bilibili, Indexes.baidu, Indexes.douyin];
// If <true> block [Lucky Draw (The Selection)] popups at live.bilibili.com.
const BlockLivePopups = true;
// Restore history state, remove redundant params
function restoreState(site) {
const OLD_URL = window.location.href;
const url = new URL(OLD_URL);
const params = url.searchParams;
site.forEach((k) => { params.delete(k); });
const NEW_URL = url.toString();
window.history.replaceState({}, 'Restore', NEW_URL);
}
class cleanBili {
}
// Remove Bilibili metadata
function removeBiliMetadData() {
const metas = document.getElementsByTagName('meta');
for (let i = 0; i < metas.length; i += 1) {
if (metas[i].name === 'spm_prefix') {
metas[i].remove();
}
}
}
// Remove Bilibili Card Ads
function removeBiliAds() {
let index = 0;
do {
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);
}
// clean <a> links
function cleanBiliLinks(site) {
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
if (links[i].href !== '') {
const url = new URL(links[i].href);
site.forEach((k) => { url.searchParams.delete(k); });
links[i].href = url.toString();
}
}
}
// block clicking events (link, button, li)
function blockClickEvents() {
function blockLinkEvents() {
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
if (links[i].getAttribute('data-video-time') === null) {
const isLinkJump = links[i].classList.contains('jump-link');
const isVideoJump = links[i].classList.contains('video-time') || links[i].classList.contains('video');
if (!(isLinkJump && isVideoJump)) {
links[i].addEventListener('click', (e) => {
e.stopPropagation();
}, true);
}
}
}
}
blockLinkEvents();
const buttons = document.getElementsByTagName('button');
for (let i = 0; i < buttons.length; i += 1) {
buttons[i].addEventListener('click', () => {
blockLinkEvents();
removeBiliAds();
setTimeout(() => { blockLinkEvents(); removeBiliAds(); }, DELAY_TIME.fast);
setTimeout(() => { blockLinkEvents(); removeBiliAds(); }, DELAY_TIME.normal);
});
}
const userAvatars = document.getElementsByClassName('cover');
for (let i = 0; i < userAvatars.length; i += 1) {
userAvatars[i].addEventListener('mouseover', () => {
setInterval(() => { blockLinkEvents(); }, 80);
}, true);
}
const userNames = document.getElementsByClassName('title');
for (let i = 0; i < userNames.length; i += 1) {
userNames[i].addEventListener('mouseover', () => {
setInterval(() => { blockLinkEvents(); }, 80);
}, true);
}
// bili-dyn-avatar bili-dyn-title
}
// clean top menu events
function cleanBLTopMenu() {
setTimeout(() => {
const topEntries = document.getElementsByClassName('v-popover-wrap'); // li
for (let i = 0; i < topEntries.length; i += 1) {
topEntries[i].addEventListener('mouseover', () => {
blockClickEvents();
}, 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'); // div
for (let i = 0; i < rightItems.length; i += 1) {
rightItems[i].addEventListener('click', (e) => {
e.stopPropagation();
}, true);
}
// 收藏 - 稍后再看
const favTabs = document.getElementsByClassName('tab-item'); // div
for (let i = 0; i < favTabs.length; i += 1) {
favTabs[i].addEventListener('click', () => {
setTimeout(() => { blockClickEvents(); }, 800);
}, true);
}
}, DELAY_TIME.slow);
}
// www.bilibili.com/*, ww.bilibili.com/v/popular/*
function cleanBMainURL() {
restoreState(sites[0]);
function onFresh() {
// www.bilibili.com/v/popular/
function blockPopEvents() {
// block default events
const videoCards = document.getElementsByClassName('video-card__content'); // div
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'); // div
for (let i = 0; i < naviItems.length; i += 1) {
naviItems[i].addEventListener('click', () => {
setTimeout(() => { blockPopEvents(); blockClickEvents(); }, DELAY_TIME.fast + 100);
setTimeout(() => { blockPopEvents(); }, DELAY_TIME.normal + 200);
});
}
// block traking link events after rank-tab clicked
const tagUL = document.getElementsByClassName('rank-tab')[0]; // li
if (tagUL != null) {
const tagLIs = tagUL.getElementsByTagName('li');
for (let i = 0; i < tagLIs.length; i += 1) {
tagLIs[i].addEventListener('click', () => {
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast + 100);
});
}
}
}
}
onFresh();
cleanBiliLinks(sites[0]);
removeBiliAds();
blockClickEvents();
// Loop execution while scrolling
window.onscroll = () => {
let topScroll = 0;
// Scroll range
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
cleanBiliLinks(sites[0]);
removeBiliAds();
blockClickEvents();
onFresh();
topScroll = scrolls;
}
};
}
// bilibili search events
function blockBSearchItemEvents() {
function blockSearchEvents() {
// input suggested items
const suggestItems = document.getElementsByClassName('suggest-item');
for (let i = 0; i < suggestItems.length; i += 1) {
suggestItems[i].addEventListener('click', () => {
blockClickEvents();
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast);
});
}
// search trending items
const topSearchs = document.getElementsByClassName('trending-item');
for (let i = 0; i < topSearchs.length; i += 1) {
topSearchs[i].addEventListener('click', () => {
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast);
});
}
// search history items
const historyItems = document.getElementsByClassName('history-item');
for (let i = 0; i < historyItems.length; i += 1) {
historyItems[i].addEventListener('click', () => {
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast);
});
}
}
// search input area
const searchInputs = document.getElementsByClassName('search-input-el');
searchInputs[0].addEventListener('click', () => {
blockSearchEvents();
});
// clear icon
const clearIcon = document.getElementsByClassName('clear-icon')[0];
clearIcon.addEventListener('click', () => {
setTimeout(() => { blockSearchEvents(); }, DELAY_TIME.fast);
});
}
// search.bilibili.com/*
function cleanBSearch() {
restoreState(sites[0]);
blockClickEvents();
blockBSearchItemEvents();
// vui_tabs--nav-item
const lines = document.getElementsByTagName('li');
for (let i = 0; i < lines.length; i += 1) {
lines[i].addEventListener('click', () => {
blockClickEvents();
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast + 100);
});
}
// paging button clicking event
const pageButtons = document.getElementsByClassName('vui_pagenation--btn'); // div
for (let i = 0; i < pageButtons.length; i += 1) {
pageButtons[i].addEventListener('click', () => {
blockClickEvents();
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast + 100);
restoreState(sites[0]);
});
}
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast + 100);
// loop execution while scrolling
window.onscroll = () => {
let topScroll = 0;
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
restoreState(sites[0]);
cleanBiliLinks(sites[0]);
blockClickEvents();
removeBiliAds();
topScroll = scrolls;
}
};
}
// www.bilibili.com/video/*
function cleanBVideoURL() {
restoreState(sites[0]);
cleanBiliLinks(sites[0]);
blockClickEvents();
const unfoldVideo = document.getElementsByClassName('rec-footer');
unfoldVideo[0].addEventListener('click', () => {
cleanBiliLinks(sites[0]);
blockClickEvents();
restoreState(sites[0]);
});
window.onscroll = () => {
let topScroll = 0;
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
restoreState(sites[0]);
cleanBiliLinks(sites[0]);
blockClickEvents();
removeBiliAds();
topScroll = scrolls;
}
};
// video episodes/collections tracking state after clicked
const episodes = document.getElementsByClassName('rec-footer'); // div
for (let i = 0; i < episodes.length; i += 1) {
episodes[i].addEventListener('click', () => {
cleanBiliLinks(sites[0]);
removeBiliAds();
setTimeout(() => {
restoreState(sites[0]); blockClickEvents();
}, 1000);
}, true);
}
setTimeout(() => {
restoreState(sites[0]);
cleanBiliLinks(sites[0]);
blockClickEvents();
}, DELAY_TIME.slow);
}
// space.bilibili.com/*
function cleanBSpaceURL() {
cleanBiliLinks(sites[0]);
blockClickEvents();
function run() {
// paging class = 'be-pager'
const lines = document.getElementsByTagName('li'); // li
for (let i = 0; i < lines.length; i += 1) {
lines[i].addEventListener('click', () => {
blockClickEvents();
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast);
});
}
// side navigation bar click events class = 'text'
const links = document.getElementsByTagName('a'); // a
for (let i = 0; i < links.length; i += 1) {
links[i].addEventListener('click', () => {
blockClickEvents();
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast);
});
}
// navigation inputs (sorting) class = 'be-tab-input'
const inputs = document.getElementsByTagName('input');
for (let i = 0; i < inputs.length; i += 1) {
inputs[i].addEventListener('click', () => {
blockClickEvents();
setTimeout(() => { blockClickEvents(); }, DELAY_TIME.fast);
});
}
}
run();
window.onscroll = () => {
let topScroll = 0;
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
cleanBiliLinks(sites[0]);
run();
blockClickEvents();
topScroll = scrolls;
}
};
}
// live.bilibili.coom popups
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 = '';
}
}
}
};
// live.bilibili.com/*
function cleanBLive() {
cleanBiliLinks(sites[0]);
blockClickEvents();
const navis = document.getElementsByClassName('tabs__tag-item');
for (let i = 0; i < navis.length; i += 1) {
navis[i].addEventListener('click', () => {
setTimeout(() => { cleanBiliLinks(sites[0]); }, 100);
setTimeout(() => { cleanBiliLinks(sites[0]); }, DELAY_TIME.normal);
});
}
const tabItems = document.getElementsByClassName('tab-item');
for (let i = 0; i < tabItems.length; i += 1) {
tabItems[i].addEventListener('click', () => {
blockClickEvents();
setTimeout(() => { cleanBiliLinks(sites[0]); }, 100);
setTimeout(() => { cleanBiliLinks(sites[0]); }, DELAY_TIME.normal);
});
}
window.onscroll = () => {
let topScroll = 0;
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
cleanBiliLinks(sites[0]);
topScroll = scrolls;
}
};
const liveIntervalId = setInterval(livePopupBlock(BlockLivePopups), DELAY_TIME.normal);
setTimeout(() => { clearInterval(liveIntervalId); }, DELAY_TIME.slow + 1000 * 300);
}
// Baidu related search, Hot search URL cleaning
function cleanBaiduURL() {
function cleanLinks(site) {
const links = document.getElementsByTagName('a');
for (let i = 0; i < links.length; i += 1) {
if (links[i].href !== '') {
const url = new URL(links[i].href);
site.forEach((k) => { url.searchParams.delete(k); });
// Mar. 2023 404 of zhidao.baidu.com/q?word=
if (url.host.includes('zhidao.baidu.com') && url.pathname === '/q') { url.pathname = '/search'; }
links[i].href = url.toString().replace('from=', '');
}
}
}
cleanLinks(sites[1]);
window.onscroll = () => {
let topScroll = 0;
const scrolls = document.documentElement.scrollTop || document.body.scrollTop;
if (scrolls - topScroll > 120) {
cleanLinks(sites[1]);
topScroll = scrolls;
}
};
}
// Handle different sites
window.onload = () => {
const realLocation = window.location;
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 isBaidu = realLocation.hostname.includes('baidu.com');
const isDouyin = realLocation.hostname.includes('douyin.com');
switch (true) {
case isBilibili: // Bilibili
restoreState(sites[0]);
cleanBiliLinks(sites[0]);
removeBiliMetadData();
removeBiliAds();
cleanBLTopMenu();
switch (isBilibili) {
case isBmain:
if (isBvideo) {
setTimeout(() => { cleanBVideoURL(); }, DELAY_TIME.fast);
} else {
setTimeout(() => { cleanBMainURL(); }, DELAY_TIME.fast);
}
break;
case isBsearch:
cleanBSearch();
break;
case isBspace:
setTimeout(() => { cleanBSpaceURL(); }, DELAY_TIME.fast);
break;
case isBlive:
cleanBLive();
setTimeout(() => { cleanBiliLinks(sites[0]); }, DELAY_TIME.normal + 200);
setTimeout(() => { cleanBiliLinks(sites[0]); }, DELAY_TIME.slow);
break;
default: // passport account message member t app manga show link
blockClickEvents();
break;
}
break;
case isBaidu: // Baidu <Related search> <Hot search>
restoreState(sites[1]);
cleanBaiduURL();
setTimeout(() => { cleanBaiduURL(); }, DELAY_TIME.normal);
break;
case isDouyin:
restoreState(sites[2]);
break;
default:
break;
}
};
})();
/*
# Changelog
v0.4.5 2023.03.09
- Clean more URL under Baidu.com, replace search URL state. [Baidu]
- Script optimisation and bug fixes. [bilibili]
- Code reduction.
v0.4.4 2023.03.05
- Restore history state at live.bilibili.com. [Bilibili]
- Clean Bilibili Manga & Show links. [manga/show.bilibili.com]
- Clean redundant params at douyin.com search page. [Douyin]
- Code reduction.
v0.4.3.1 2023.03.01
- Clean more links at live.bilibili.com. [Bilibili]
- Script optimisation.
v0.4.3 2023.02.24
- Block more tracking events. [Bilibili]
- Clean more links.[Bilibili]
- Restore link jump events at comment area. [Bilibili]
- Script optimisation. [Bilibili]
v0.4.2.1 2023.02.22
- Restore `<a>` link click-events on precise time jump at comment area.[www.bilibili.com/video]
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.
v0.3.4 2022.12.23
- Code optimisation. Fixed script's effect range. [Bilibili]
v0.3.3 2022.12.23
- Added site support:Clean Baidu <Related Search> URLs.
- Script optimisations. [space.bilibili.com]
v0.3.2 2022.12.22
- Restore pushstate session (address bar url display, replace history). [Bilibili]
- Minor optimisations. [Bilibili]
v0.3.1 2022.12.22
- Optimized the effective range. [Bilibili]
v0.3 2022.12.22
- Added Bilibili Home page, Popular/Rank page, now it can takeeffect on most pages. [Bilibili]
v0.2 2022.12.21
- Added missing tags. [Bilibili]
v0.1 2022.12.20
- Initial release.
*/