屏蔽 BiliBili PCDN

前言

用了 Mac 之后使用 Chrome 看 BiliBili 的视频总是会特别的卡顿,明明带宽没占满,速度确是一直起不来,后面发现原来是 CDN 的问题录播姬整理的 CDN论坛老哥整理的CDNbilivideo.com子域名大全

V2EX

B 站的 video host 有四种类型:(我将其添加个称呼好标注,非官方称呼)
upos-sz-mirrorkodo.bilivideo.com / upos-sz-mirrorcos.bilivideo.com / Mirror 型
cn-gdgz4-cmcc-v-09.bilivideo.com / cn-gdst-cmcc-bcache-02.bilivideo.com / Cache 型
xy112x48x59x98xy.mcdn.bilivideo.cn / xy110x85x55x73xy.mcdn.bilivideo.cn / MCDN 型
a93lt21v.v1d.szbdyd.com / hz6xy5t6.v1d.szbdyd.com / PCDN 型
以上几种是在广东移动的场景下测的,其他运营商应该也差不多。

B 站官方测速地址

https://www.bilibili.com/blackboard/app-speed-test.html

解决办法

脚本

  1. Make BiliBili Great Again

    这篇文章说要把 108 行处 urlObj.port = 443 改为 urlObj.port = 4483,我也不知道改了有什么用

  2. 【哔哩哔哩】屏蔽视频PCDN地址

脚本是挺方便的,但是手机用不了啊,看到这一篇文章发现大佬把PCDN的域名给总结出来,那我就直接用了😁

又找到一个佬关于B站 PCDN 的规则

https://github.com/elysias123/bilibili-rule/blob/main/bilibili-pcdn.yaml

Noodseek:https://www.nodeseek.com/post-139229-1

anti-AD:https://github.com/privacy-protection-tools/anti-AD/blob/master/discretion/pcdn.txt

Mosdns(推荐)

Mosdns 支持正则表达式,所以可以使用以下参数:

点我展开看废弃代码

domain:gjfzpt.cn
domain:szbdyd.com
domain:bsccdn.net
domain:pkoplink.com
domain:saxysec.com
domain:uhabo.com
domain:xycdn.com
domain:kuiniuca.com
domain:onethingpcs.com
domain:jomodns.cn
domain:p2p.huya.com
domain:stun.douyucdn.cn
domain:stun.hitv.com
domain:stun1.douyucdn.cn
domain:mcdn.bilivideo.cn
domain:tpa-hcdn.iqiyi.com
domain:pcdn.xmcdn.com
domain:pcdn.yximgs.com
domain:dyp2p-ali.douyucdn.cn
domain:dyp2p-hw.douyucdn.cn
domain:p2p-ali.douyucdn.cn
domain:p2p.qq.com
domain:p2pchunk-hw.douyucdn.cn
domain:p2pchunk-table.douyucdn.cn
domain:p2pchunk-ws.douyucdn.cn
domain:p2perrorlog.douyucdn.cn
domain:p2plive-ali.douyucdn.cn
domain:p2plive-ws.douyucdn.cn
domain:p2plog.douyucdn.cn
domain:p2ptun.qq.com
domain:p2pupdate.gamedl.qq.com
domain:p2pupgrade.gamedl.qq.com
domain:p2pvod-ws.douyucdn.cn
regexp:.*pcdn.*biliapi\.net
regexp:.*pcdn.*youku\.com
regexp:.*p2p.*douyucdn\.cn
regexp:.*p2p.*qq\.com
regexp:.*pcdn.*biliapi\.net
regexp:.*pcdn.*youku\.com
regexp:cn-.*\.bilivideo\.com            #屏蔽这个会导致看不了直播
  

由于旧版误伤过多,所以精简了很多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
domain:gjfzpt.cn
domain:szbdyd.com
domain:bsccdn.net
domain:pkoplink.com
domain:saxysec.com
domain:uhabo.com
domain:xycdn.com
domain:kuiniuca.com
domain:onethingpcs.com
domain:jomodns.cn
domain:p2p.huya.com
domain:stun.douyucdn.cn
domain:stun.hitv.com
domain:mcdn.bilivideo.cn
domain:tpa-hcdn.iqiyi.com
domain:pcdn.xmcdn.com
domain:pcdn.yximgs.com
domain:pcdn.yximgs.com
regexp:.*pcdn.*biliapi\.net
regexp:.*pcdn.*youku\.com
regexp:.*p2p.*douyucdn\.cn
regexp:.*p2p.*qq\.com
regexp:.*pcdn.*biliapi.net
regexp:.*pcdn.*youku.com

Clash

使用 Clash 规则时,需要添加好对应的端口,例如:

xy111x51x181x119xy.mcdn.bilivideo.cn:4483,使用的是京东云,在clash的代理端口上需要把对应的TCP 端口加上 4483 8082,有点麻烦

我整理的地址大佬的GitHub地址

Other

1.Make BiliBili Great Again 有一些优化代码还是挺有用的,去除“ 去 P2P CDN”后的代码如下

点我展开

// ==UserScript==
// @name         Make BiliBili Great Again
// @namespace    https://www.kookxiang.com/
// @version      1.5.5
// @description  useful tweaks for bilibili.com
// @author       kookxiang
// @match        https://*.bilibili.com/*
// @run-at       document-body
// @grant        unsafeWindow
// @grant        GM_addStyle
// @grant        GM_notification
// @downloadURL https://update.greasyfork.org/scripts/415714/Make%20BiliBili%20Great%20Again.user.js
// @updateURL https://update.greasyfork.org/scripts/415714/Make%20BiliBili%20Great%20Again.meta.js
// ==/UserScript==
// 去掉叔叔去世时的全站黑白效果
GM_addStyle("html, body { -webkit-filter: none !important; filter: none !important; }");

// 没用的 URL 参数
const uselessUrlParams = [
‘buvid’,
‘is_story_h5’,
‘launch_id’,
‘live_from’,
‘mid’,
‘session_id’,
‘timestamp’,
‘up_id’,
‘vd_source’,
/^share/,
/^spm/,
];

// Block WebRTC,CNM 陈睿你就缺这点棺材钱?
try {
Object.defineProperty(unsafeWindow, ‘webkitRTCPeerConnection’, { value: undefined, enumerable: false, writable: false });
} catch (e) { }

// 移除鸿蒙字体,系统自带它不香吗?
window.addEventListener(‘load’, function () {
document.body.classList.remove(‘harmony-font’);
})

// 首页优化
if (location.host === “www.bilibili.com“) {
GM_addStyle(‘.feed2 .feed-card:has(a[href*=”cm.bilibili.com”]) { display: none } .feed2 .container > * { margin-top: 0 !important }’);
}

// 动态页面优化
if (location.host === “t.bilibili.com”) {
GM_addStyle(“html[wide] #app { display: flex; } html[wide] .bili-dyn-home–member { box-sizing: border-box;padding: 0 10px;width: 100%;flex: 1; } html[wide] .bili-dyn-content { width: initial; } html[wide] main { margin: 0 8px;flex: 1;overflow: hidden;width: initial; } #wide-mode-switch { margin-left: 0;margin-right: 20px; } .bili-dyn-list__item:has(.bili-dyn-card-goods), .bili-dyn-list__item:has(.bili-rich-text-module.goods) { display: none !important }”);
if (!localStorage.WIDE_OPT_OUT) {
document.documentElement.setAttribute(‘wide’, ‘wide’);
}
window.addEventListener(‘load’, function () {
const tabContainer = document.querySelector(‘.bili-dyn-list-tabs__list’);
const placeHolder = document.createElement(‘div’);
placeHolder.style.flex = 1;
const switchButton = document.createElement(‘a’);
switchButton.id = ‘wide-mode-switch’;
switchButton.className = ‘bili-dyn-list-tabs__item’;
switchButton.textContent = ‘宽屏模式’;
switchButton.addEventListener(‘click’, function (e) {
e.preventDefault();
if (localStorage.WIDE_OPT_OUT) {
localStorage.removeItem(‘WIDE_OPT_OUT’);
document.documentElement.setAttribute(‘wide’, ‘wide’);
} else {
localStorage.setItem(‘WIDE_OPT_OUT’, ‘1’);
document.documentElement.removeAttribute(‘wide’);
}
})
tabContainer.appendChild(placeHolder);
tabContainer.appendChild(switchButton);
})
}

// 去广告
GM_addStyle(‘.ad-report, a[href*=”cm.bilibili.com”] { display: none !important; }’);
if (unsafeWindow.INITIAL_STATE?.adData) {
for (const key in unsafeWindow.INITIAL_STATE.adData) {
if (!Array.isArray(unsafeWindow.INITIAL_STATE.adData[key])) continue;
for (const item of unsafeWindow.INITIAL_STATE.adData[key]) {
item.name = ‘B 站未来有可能会倒闭,但绝不会变质’;
item.pic = ‘https://static.hdslb.com/images/transparent.gif‘;
item.url = ‘https://space.bilibili.com/208259‘;
}
}
}

// 去充电列表(叔叔的跳过按钮越做越小了,就尼玛离谱)
if (unsafeWindow.INITIAL_STATE?.elecFullInfo) {
delete unsafeWindow.INITIAL_STATE.elecFullInfo;
}

// 修复文章区复制
if (location.href.startsWith(‘https://www.bilibili.com/read/cv‘)) {
unsafeWindow.original.reprint = “1”;
document.querySelector(‘.article-holder’).classList.remove(“unable-reprint”);
document.querySelector(‘.article-holder’).addEventListener(‘copy’, e => e.stopImmediatePropagation(), true);
}

// 真·原画直播
if (location.href.startsWith(‘https://live.bilibili.com/‘)) {
unsafeWindow.forceHighestQuality = true;
let recentErrors = 0;
setInterval(() => recentErrors > 0 ? recentErrors / 2 : null, 10000);

const oldFetch = unsafeWindow.fetch;
unsafeWindow.fetch = function (url) {
    try {
        const mcdnRegexp = /[xy0-9]+\.mcdn\.bilivideo\.cn:\d+/
        const qualityRegexp = /(live-bvc\/\d+\/live_\d+_\d+)_\w+/;
        if (mcdnRegexp.test(arguments[0]) && unsafeWindow.disableMcdn) {
            return Promise.reject();
        }
        if (qualityRegexp.test(arguments[0]) && unsafeWindow.forceHighestQuality) {
            arguments[0] = arguments[0]
                .replace(qualityRegexp, '$1')
                .replace(/(\d+)_(mini|pro)hevc/g, '$1');
        }
        const promise = oldFetch.apply(this, arguments);
        promise.then(response => {
            if (!url.match(/\.(m3u8|m4s)/)) return;
            if ([403, 404].includes(response.status)) recentErrors++;
            if (recentErrors >= 5 && unsafeWindow.forceHighestQuality) {
                recentErrors = 0;
                unsafeWindow.forceHighestQuality = false;
                GM_notification({ title: '最高清晰度可能不可用', text: '已为您自动切换至播放器上选择的清晰度.', timeout: 3000, silent: true });
            }
        });
        return promise;
    } catch (e) { }
    return oldFetch.apply(this, arguments);
}

}

// 视频裁切
if (location.href.startsWith(‘https://www.bilibili.com/video/‘)) {
GM_addStyle(“body[video-fit] #bilibili-player video { object-fit: cover; } .bpx-player-ctrl-setting-fit-mode { display: flex;width: 100%;height: 32px;line-height: 32px; } .bpx-player-ctrl-setting-box .bui-panel-wrap, .bpx-player-ctrl-setting-box .bui-panel-item { min-height: 172px !important; }”);
let timer;
function toggleMode(enabled) {
if (enabled) {
document.body.setAttribute(‘video-fit’, ‘’);
} else {
document.body.removeAttribute(‘video-fit’);
}
}
function injectButton() {
if (!document.querySelector(‘.bpx-player-ctrl-setting-menu-left’)) {
return;
}
clearInterval(timer);
const parent = document.querySelector(‘.bpx-player-ctrl-setting-menu-left’);
const item = document.createElement(‘div’);
item.className = ‘bpx-player-ctrl-setting-fit-mode bui bui-switch’;
item.innerHTML = ‘‘;
parent.insertBefore(item, document.querySelector(‘.bpx-player-ctrl-setting-more’));
document.querySelector(‘.bpx-player-ctrl-setting-fit-mode input’).addEventListener(‘change’, e => toggleMode(e.target.checked));
document.querySelector(‘.bpx-player-ctrl-setting-box .bui-panel-item’).style.height = ‘’;
}
timer = setInterval(injectButton, 200);
}

// 去除地址栏多余参数
unsafeWindow.history.replaceState(undefined, undefined, removeTracking(location.href));
const pushState = unsafeWindow.history.pushState;
unsafeWindow.history.pushState = function (state, unused, url) {
return pushState.apply(this, [state, unused, removeTracking(url)]);
}
const replaceState = unsafeWindow.history.replaceState;
unsafeWindow.history.replaceState = function (state, unused, url) {
return replaceState.apply(this, [state, unused, removeTracking(url)]);
}

function removeTracking(url) {
if (!url) return url;
try {
const [base, search] = url.split(‘?’);
if (!search) return url;
const searchParams = new URLSearchParams(‘?’ + search);
const keys = Array.from(searchParams.keys());
for (const key of keys) {
uselessUrlParams.forEach(item => {
if (typeof item === ‘string’) {
if (item === key) searchParams.delete(key);
} else if (item instanceof RegExp) {
if (item.test(key)) searchParams.delete(key);
}
});
}
if (location.pathname === base && !searchParams.size) return;
return [base, searchParams.toString()].filter(Boolean).join(‘?’);
} catch (e) {
return url;
}
}

// 去掉 B 站的傻逼上报
!function () {
const oldFetch = unsafeWindow.fetch;
unsafeWindow.fetch = function (url) {
if (typeof url === ‘string’ && url.includes(‘data.bilibili.com’))
return Promise.resolve(new Response());
return oldFetch.apply(this, arguments);
}
const oldSend = unsafeWindow.XMLHttpRequest.prototype.open;
unsafeWindow.XMLHttpRequest.prototype.open = function (method, url) {
if (typeof url === ‘string’ && url.includes(‘data.bilibili.com’)) {
this.send = function () { };
return;
}
return oldSend.apply(this, arguments);
}
unsafeWindow.navigator.sendBeacon = () => Promise.resolve();

unsafeWindow.MReporter = function () { };
unsafeWindow.MReporter.appear = function () { };
unsafeWindow.MReporter.click = function () { };
unsafeWindow.MReporter.tech = function () { };
unsafeWindow.MReporter.pv = function () { };
unsafeWindow.MReporter.import = { auto() { } };

const sentryHub = class { bindClient() { } }
const fakeSentry = {
    SDK_NAME: 'sentry.javascript.browser',
    SDK_VERSION: '0.0.0',
    BrowserClient: class { },
    Hub: sentryHub,
    Integrations: {
        Vue: class { },
        GlobalHandlers: class { },
        InboundFilters: class { },
    },
    init() { },
    configureScope() { },
    getCurrentHub: () => new sentryHub(),
    setContext() { },
    setExtra() { },
    setExtras() { },
    setTag() { },
    setTags() { },
    setUser() { },
    wrap() { },
}
if (!unsafeWindow.Sentry || unsafeWindow.Sentry.SDK_VERSION !== fakeSentry.SDK_VERSION) {
    if (unsafeWindow.Sentry) { delete unsafeWindow.Sentry }
    Object.defineProperty(unsafeWindow, 'Sentry', { value: fakeSentry, enumerable: false, writable: false });
}
Object.defineProperty(unsafeWindow, 'ReporterPb', { value: class { click() { } custom() { } exposure() { } report() { } tech() { } pv() { } }, enumerable: false, writable: false });

Object.defineProperty(unsafeWindow, '__biliUserFp__', {
    get() { return { init() { }, queryUserLog() { return [] } } },
    set() { },
});
Object.defineProperty(unsafeWindow, '__USER_FP_CONFIG__', { get() { return undefined }, set() { } });
Object.defineProperty(unsafeWindow, '__MIRROR_CONFIG__', { get() { return undefined }, set() { } });

}()

大家可以去看看大佬文章的说明,我这就不贴了