Greasy Fork

Greasy Fork is available in English.

解除B站区域限制

把获取视频地址相关接口的返回值替换成biliplus的接口的返回值, 因为替换值的操作是同步的, 所有会卡几下..., 又因为biliplus的接口不支持跨域请求, 所以使用了我自己的服务器做反向代理(-_-#);

当前为 2016-12-16 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         解除B站区域限制
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  把获取视频地址相关接口的返回值替换成biliplus的接口的返回值, 因为替换值的操作是同步的, 所有会卡几下..., 又因为biliplus的接口不支持跨域请求, 所以使用了我自己的服务器做反向代理(-_-#);
// @author       ipcjs
// @include      http://bangumi.bilibili.com/anime/*
// @include      http://bangumi.bilibili.com/anime/v/*
// @include      http://www.bilibili.com/html/html5player.html*
// @run-at       document-start
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @connect      biliplus.com
// @connect      biliplus.ipcjsdev.tk
// ==/UserScript==

(function () {
    'use strict';
    var biliplusHost = 'http://biliplus.ipcjsdev.tk';
    // var biliplusHost = 'https://www.biliplus.com';
    console.log('[' + GM_info.script.name + '] run on: ' + unsafeWindow.location.href);
    if (!unsafeWindow.jQuery) { // 若还未加载jQuery, 则监听
        var jQuery;
        Object.defineProperty(unsafeWindow, 'jQuery', {
            configurable: true, enumerable: true, set: function (v) {
                jQuery = v;
                injectDataFilter();// 设置jQuery后, 立即注入
            }, get: function () {
                return jQuery;
            }
        });
    } else {
        injectDataFilter();
    }

    function injectDataFilter() {
        unsafeWindow.jQuery.ajaxSetup({
            dataFilter: function (data, type) {
                var json, obj, group;
                // console.log(arguments, this);
                if (this.url.startsWith('http://bangumi.bilibili.com/web_api/get_source')) {
                    // 获取cid API
                    console.log(data);
                    json = JSON.parse(data);
                    if (json.code === -40301) {
                        $.ajax({
                            url: biliplusHost + '/api/view?id=' + unsafeWindow.aid,
                            async: false,
                            success: function (result) {
                                obj = {
                                    code: 0, message: 'success', result: {
                                        episode_status: 2,
                                        pre_ad: 0,
                                        season_status: 2
                                    }
                                };
                                obj.result.aid = result.id;
                                obj.result.cid = result.list[0].cid;
                                obj.result.player = result.list[0].type;
                                obj.result.vid = result.list[0].vid;
                                data = JSON.stringify(obj);
                                console.log('==>', data);
                                // console.log('success', arguments, this);
                            },
                            error: function () {
                                console.log('error', arguments, this);
                            }
                        });
                    }
                } else if (this.url.startsWith('https://bangumi.bilibili.com/player/web_api/playurl')) {
                    // 获取视频地址 API
                    console.log(data);
                    json = JSON.parse(data);
                    if (json.durl.length === 1 && json.durl[0].length === 15126 && json.durl[0].size === 124627) {
                        group = unsafeWindow.location.href.match(/cid=(\d+)/);
                        $.ajax({
                            // url: biliplusHost+'/BPplayurl.php?cid=' + group[1] +'|bangumi&player=1&ts=' + parseInt(new Date().getTime() / 1000),
                            url: biliplusHost + '/BPplayurl.php?cid=' + group[1] + '|bangumi',
                            async: false,
                            xhrFields: {withCredentials: true},
                            success: function (result) {
                                // console.log('success', arguments, this);
                                obj = xml2obj(result.documentElement);
                                obj.accept_quality && (obj.accept_quality = obj.accept_quality.split(',').map(function (item) {
                                    return Number(item);
                                }));
                                if (!obj.durl.push) {
                                    obj.durl = [obj.durl];
                                }
                                obj.durl.forEach(function (item) {
                                    if (item.backup_url === '') {
                                        item.backup_url = undefined;
                                    } else if (item.backup_url && item.backup_url.url) {
                                        item.backup_url = item.backup_url.url;
                                    }
                                });
                                if (obj.durl.length === 1 && obj.durl[0].length == 15126 && obj.durl[0].size === 124627) {
                                    if (confirm('试图解除区域限制失败, 请登录biliplus' +
                                            '\n注意: 因为反向代理服务器没有证书, 只能在http下用密码方式登录, 有泄漏密码的风险, 需要自行承担...'
                                        )) {
                                        unsafeWindow.top.location = biliplusHost + '/login';
                                    }
                                } else {
                                    data = JSON.stringify(obj);
                                    console.log('==>', data);
                                }
                            },
                            error: function () {
                                console.log('error', arguments, this);
                            }
                        });
                    }
                } else if (this.url.startsWith('http://bangumi.bilibili.com/web_api/season_area')) {
                    // 番剧页面是否要隐藏番剧列表 API
                    console.log(data);
                    json = JSON.parse(data);
                    // 限制区域时的data为:
                    // {"code":0,"message":"success","result":{"play":0}}
                    if (json.code === 0 && json.result && json.result.play === 0) {
                        json.result.play = 1; // 改成1就能够显示
                        data = JSON.stringify(json);
                        console.log('==>', data);
                    }
                }
                return data;
            }
        });
    }

    function xml2obj(xml) {
        try {
            var obj = {}, text;
            var children = xml.children;
            if (children.length > 0) {
                for (var i = 0; i < children.length; i++) {
                    var item = children.item(i);
                    var nodeName = item.nodeName;

                    if (typeof (obj[nodeName]) == "undefined") { // 若是新的属性, 则往obj中添加
                        obj[nodeName] = xml2obj(item);
                    } else {
                        if (typeof (obj[nodeName].push) == "undefined") { // 若老的属性没有push方法, 则把属性改成Array
                            var old = obj[nodeName];

                            obj[nodeName] = [];
                            obj[nodeName].push(old);
                        }
                        obj[nodeName].push(xml2obj(item));
                    }
                }
            } else {
                text = xml.textContent;
                if (/^\d+(\.\d+)?$/.test(text)) {
                    obj = Number(text);
                } else if (text === 'true' || text === 'false') {
                    obj = Boolean(text);
                } else {
                    obj = text;
                }
            }
            return obj;
        } catch (e) {
            console.log(e.message);
        }
    }
})();