增加后端代理,解决部分网页的播放问题
This commit is contained in:
parent
407d8aa791
commit
cb03151232
25
app.py
25
app.py
@ -9,11 +9,12 @@ from flask_migrate import Migrate
|
|||||||
from base import config
|
from base import config
|
||||||
from base.database import db
|
from base.database import db
|
||||||
from utils.log import logger
|
from utils.log import logger
|
||||||
from utils.system import get_wlan_info,getHost
|
from utils.system import get_wlan_info, getHost
|
||||||
from controllers import *
|
from controllers import *
|
||||||
from js.rules import getRuleLists
|
from js.rules import getRuleLists
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
||||||
def create_flask_app():
|
def create_flask_app():
|
||||||
app = Flask(__name__, static_folder='static', static_url_path='/static')
|
app = Flask(__name__, static_folder='static', static_url_path='/static')
|
||||||
app.config.from_object(config) # 单独的配置文件里写了,这里就不用弄json中文显示了
|
app.config.from_object(config) # 单独的配置文件里写了,这里就不用弄json中文显示了
|
||||||
@ -31,22 +32,28 @@ def create_flask_app():
|
|||||||
# logger.info(f"自定义播放解析地址:{lsg.getItem('PLAY_URL')}")
|
# logger.info(f"自定义播放解析地址:{lsg.getItem('PLAY_URL')}")
|
||||||
logger.info(f'当前操作系统{sys.platform}')
|
logger.info(f'当前操作系统{sys.platform}')
|
||||||
rule_list = getRuleLists()
|
rule_list = getRuleLists()
|
||||||
wlan_info,_ = get_wlan_info()
|
wlan_info, _ = get_wlan_info()
|
||||||
logger.info(rule_list)
|
logger.info(rule_list)
|
||||||
logger.info(f'局域网: {getHost(1, app.config.get("HTTP_PORT"))}/index\n本地: {getHost(0, app.config.get("HTTP_PORT"))}/index\nwlan_info:{wlan_info}')
|
logger.info(
|
||||||
|
f'局域网: {getHost(1, app.config.get("HTTP_PORT"))}/index\n本地: {getHost(0, app.config.get("HTTP_PORT"))}/index\nwlan_info:{wlan_info}')
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
db.app = app
|
db.app = app
|
||||||
db.create_all(app=app)
|
db.create_all(app=app)
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
app = create_flask_app()
|
app = create_flask_app()
|
||||||
migrate = Migrate(app, db)
|
migrate = Migrate(app, db)
|
||||||
|
|
||||||
now_python_ver = ".".join([str(i) for i in sys.version_info[:3]])
|
now_python_ver = ".".join([str(i) for i in sys.version_info[:3]])
|
||||||
if sys.version_info < (3,9):
|
if sys.version_info < (3, 9):
|
||||||
from gevent.pywsgi import WSGIServer
|
from gevent.pywsgi import WSGIServer
|
||||||
|
|
||||||
# from gevent import monkey
|
# from gevent import monkey
|
||||||
# monkey.patch_socket() # 开启socket异步
|
# monkey.patch_all() # 多线程,只能放在最开头,import其它包之前
|
||||||
|
|
||||||
|
from gevent import monkey
|
||||||
|
monkey.patch_socket() # 开启socket异步
|
||||||
print(f'当前python版本{now_python_ver}为3.9.0及以下,支持gevent')
|
print(f'当前python版本{now_python_ver}为3.9.0及以下,支持gevent')
|
||||||
else:
|
else:
|
||||||
print(f'当前python版本{now_python_ver}为3.9.0及以上,不支持gevent')
|
print(f'当前python版本{now_python_ver}为3.9.0及以上,不支持gevent')
|
||||||
@ -54,10 +61,16 @@ else:
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
http_port = int(app.config.get('HTTP_PORT', 5705))
|
http_port = int(app.config.get('HTTP_PORT', 5705))
|
||||||
http_host = app.config.get('HTTP_HOST', '0.0.0.0')
|
http_host = app.config.get('HTTP_HOST', '0.0.0.0')
|
||||||
|
threaded = app.config.get('Thread')
|
||||||
|
if threaded is None:
|
||||||
|
threaded = True
|
||||||
|
# https://www.zhihu.com/question/64096559
|
||||||
|
print('threaded:',threaded)
|
||||||
|
# if sys.version_info < (3, 9) and not sys.platform.startswith('win'):
|
||||||
if sys.version_info < (3, 9):
|
if sys.version_info < (3, 9):
|
||||||
# server = WSGIServer(('0.0.0.0', 5705), app, handler_class=WebSocketHandler,log=app.logger)
|
# server = WSGIServer(('0.0.0.0', 5705), app, handler_class=WebSocketHandler,log=app.logger)
|
||||||
# server = WSGIServer(('0.0.0.0', 5705), app, handler_class=WebSocketHandler,log=None)
|
# server = WSGIServer(('0.0.0.0', 5705), app, handler_class=WebSocketHandler,log=None)
|
||||||
server = WSGIServer((http_host, http_port), app, log=logger)
|
server = WSGIServer((http_host, http_port), app, log=logger)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
else:
|
else:
|
||||||
app.run(debug=False, host=http_host, port=http_port)
|
app.run(debug=False, host=http_host, port=http_port, threaded=threaded)
|
||||||
@ -56,3 +56,4 @@ JS_PROXY = 'http://localhost:5705/admin/view/=>https://ghproxy.net/https://raw.g
|
|||||||
ALI_TOKEN = '' # 适用于初始配置的阿里云token
|
ALI_TOKEN = '' # 适用于初始配置的阿里云token
|
||||||
ENV = '{"bili_cookie":""}' # 自定义环境变量
|
ENV = '{"bili_cookie":""}' # 自定义环境变量
|
||||||
UPDATE_PROXY = 'https://ghproxy.net/' # 检测升级代理
|
UPDATE_PROXY = 'https://ghproxy.net/' # 检测升级代理
|
||||||
|
Thread = True # 开启windows多线程调用
|
||||||
|
|||||||
@ -6,10 +6,11 @@
|
|||||||
import functools
|
import functools
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from urllib.parse import urljoin
|
||||||
|
import requests
|
||||||
from flask import Blueprint, abort, request, render_template, send_from_directory, render_template_string, jsonify, \
|
from flask import Blueprint, abort, request, render_template, send_from_directory, render_template_string, jsonify, \
|
||||||
make_response, redirect, \
|
make_response, redirect, \
|
||||||
current_app
|
current_app, url_for
|
||||||
from time import time
|
from time import time
|
||||||
from utils.web import getParmas, get_interval
|
from utils.web import getParmas, get_interval
|
||||||
from utils.cfg import cfg
|
from utils.cfg import cfg
|
||||||
@ -38,12 +39,14 @@ def custom_static_cms(filename):
|
|||||||
# print(filename)
|
# print(filename)
|
||||||
return send_from_directory('templates/cms', filename)
|
return send_from_directory('templates/cms', filename)
|
||||||
|
|
||||||
|
|
||||||
@web.route('/player/<path:filename>')
|
@web.route('/player/<path:filename>')
|
||||||
def custom_static_player(filename):
|
def custom_static_player(filename):
|
||||||
# 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
# 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
|
||||||
# print(filename)
|
# print(filename)
|
||||||
return send_from_directory('templates/player', filename)
|
return send_from_directory('templates/player', filename)
|
||||||
|
|
||||||
|
|
||||||
@web.route('/<web_name>/<theme>')
|
@web.route('/<web_name>/<theme>')
|
||||||
def web_index(web_name, theme):
|
def web_index(web_name, theme):
|
||||||
ctx = {'web_name': web_name, 'key': '关键词', 'description': '描述'}
|
ctx = {'web_name': web_name, 'key': '关键词', 'description': '描述'}
|
||||||
@ -67,7 +70,7 @@ def web_index(web_name, theme):
|
|||||||
ctx['tid'] = tid
|
ctx['tid'] = tid
|
||||||
ctx['tname'] = tname
|
ctx['tname'] = tname
|
||||||
ctx['url'] = url
|
ctx['url'] = url
|
||||||
print('tid:',tid)
|
print('tid:', tid)
|
||||||
|
|
||||||
file_path = os.path.abspath(f'js/{web_name}.js')
|
file_path = os.path.abspath(f'js/{web_name}.js')
|
||||||
print(file_path)
|
print(file_path)
|
||||||
@ -86,4 +89,51 @@ def web_index(web_name, theme):
|
|||||||
else:
|
else:
|
||||||
return render_template(f'cms/{theme}/homeContent.html', ctx=ctx)
|
return render_template(f'cms/{theme}/homeContent.html', ctx=ctx)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return render_template('404.html', ctx=ctx, error=f'发生错误的原因可能是下面路径未找到:{e}')
|
return render_template('404.html', ctx=ctx, error=f'发生错误的原因可能是下面路径未找到:{e}')
|
||||||
|
|
||||||
|
|
||||||
|
@web.route('/302redirect')
|
||||||
|
def get302UrlResponse():
|
||||||
|
url = getParmas('url')
|
||||||
|
if not url:
|
||||||
|
abort(403)
|
||||||
|
params = {}
|
||||||
|
if not url.startswith('http'):
|
||||||
|
url = urljoin(request.root_url, url)
|
||||||
|
# url = urljoin('http://localhost:5705/',url)
|
||||||
|
print(url)
|
||||||
|
items = url.split('vod?')[1].split('&')
|
||||||
|
for item in items:
|
||||||
|
params[item.split('=')[0]] = item.split('=')[1]
|
||||||
|
print(params)
|
||||||
|
# abort(403)
|
||||||
|
|
||||||
|
timeout = getParmas('timeout') or 5000
|
||||||
|
rurl = url
|
||||||
|
try:
|
||||||
|
timeout = int(timeout)
|
||||||
|
headers = {
|
||||||
|
# 'referer': url,
|
||||||
|
'user-agent': 'Mozilla/5.0'
|
||||||
|
}
|
||||||
|
print('开始调用接口:', url)
|
||||||
|
r = requests.get(url, headers=headers, timeout=timeout, verify=False)
|
||||||
|
rurl = r.url
|
||||||
|
|
||||||
|
# rurl = url_for('vod.vod_home', **params)
|
||||||
|
# print(rurl)
|
||||||
|
print('结束调用接口:', rurl)
|
||||||
|
return jsonify({
|
||||||
|
'url': rurl,
|
||||||
|
'redirect': rurl != url,
|
||||||
|
'data': r.text,
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f'发生了错误:{e}')
|
||||||
|
return jsonify({
|
||||||
|
'url': rurl,
|
||||||
|
'redirect': rurl != url,
|
||||||
|
'data': None,
|
||||||
|
'error': f'{e}',
|
||||||
|
})
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
3.9.41beta26
|
3.9.41beta27
|
||||||
@ -277,7 +277,7 @@
|
|||||||
{% for rule in rules.list %}
|
{% for rule in rules.list %}
|
||||||
<div class="red">
|
<div class="red">
|
||||||
<div class="mz"><a class="view" href="javascript:void(0);">{{ rule.name }}</a></div>
|
<div class="mz"><a class="view" href="javascript:void(0);">{{ rule.name }}</a></div>
|
||||||
<div class="sa"><a class="preview_home" href="/web/{{ rule.name }}/mxpro" value="{{ rule.name }}">🌐</a></div>
|
<div class="sa"><a class="preview_home" href="/web/{{ rule.name }}/mxpro" value="{{ rule.name }}" target="_blank">🌐</a></div>
|
||||||
<div class="sj"><a class="view_home" href="javascript:void(0);" value="{{ rule.name }}">🏠</a></div>
|
<div class="sj"><a class="view_home" href="javascript:void(0);" value="{{ rule.name }}">🏠</a></div>
|
||||||
<div class="ss"><a class="view_search" href="javascript:void(0);" value="{{ rule.name }}">🔍️</a></div>
|
<div class="ss"><a class="view_search" href="javascript:void(0);" value="{{ rule.name }}">🔍️</a></div>
|
||||||
<div class="sc"><a class="clear" href="javascript:void(0);" value="{{ rule.name }}">🗑</a></div>
|
<div class="sc"><a class="clear" href="javascript:void(0);" value="{{ rule.name }}">🗑</a></div>
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
<script src="/static/js/axios.min.js"></script>
|
<script src="/static/js/axios.min.js"></script>
|
||||||
<script src="/static/js/eruda.js"></script>
|
<script src="/static/js/eruda.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/web/cms/mxpro/js/commonUtil.js"></script>
|
||||||
<script src="/web/cms/mxpro/js/commonUI.js"></script>
|
<script src="/web/cms/mxpro/js/commonUI.js"></script>
|
||||||
<link rel="stylesheet" href="/web/cms/mxpro/css/commonUI.css" type="text/css" />
|
<link rel="stylesheet" href="/web/cms/mxpro/css/commonUI.css" type="text/css" />
|
||||||
<script>var maccms={"path":"","mid":"1","url":"5imv.cc","wapurl":"www.5imv.cc","mob_status":"2"};</script>
|
<script>var maccms={"path":"","mid":"1","url":"5imv.cc","wapurl":"www.5imv.cc","mob_status":"2"};</script>
|
||||||
@ -243,39 +244,72 @@ const app = createApp({
|
|||||||
const photoVisible = ref(false);
|
const photoVisible = ref(false);
|
||||||
const iframeRef = ref(null);
|
const iframeRef = ref(null);
|
||||||
var sniffer;
|
var sniffer;
|
||||||
|
const {isVideo,getRealUrl} = commonUtil;
|
||||||
|
// get302UrlResponse('/vod?pwd=dzyyds&rule=007影视&ext=&play_url=https%3A//www.007ts.me/play/69636-3-1.html',(resp)=>{
|
||||||
|
// console.log('重定向到:',resp);
|
||||||
|
// });
|
||||||
|
// getRealUrl('/vod?pwd=dzyyds&rule=007影视&ext=&play_url=https%3A//www.007ts.me/play/69636-3-1.html',(res)=>{
|
||||||
|
// console.log('重定向到:',res);
|
||||||
|
// });
|
||||||
const methods = {
|
const methods = {
|
||||||
async lazyPlay(url){
|
async lazyPlay(url){
|
||||||
iframeShow.value = true;
|
iframeShow.value = true;
|
||||||
console.log('准备处理播放地址:'+url);
|
console.log('准备处理播放地址:'+url);
|
||||||
clearInterval(sniffer);
|
clearInterval(sniffer);
|
||||||
try {
|
try {
|
||||||
if(/\.(m3u8|mp4)/.test(url)){
|
if(isVideo(url)){
|
||||||
console.log('直接播放');
|
console.log('直接播放');
|
||||||
methods.setPlayUrl(url);
|
methods.setPlayUrl(url);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const res = await axios.get(url,{maxRedirects: 0});
|
const res =await getRealUrl(url,(resp)=>{
|
||||||
const { status, headers: { Location } } = res;
|
// console.log('代理数据:',resp.data);
|
||||||
// console.log(status);
|
return resp.data
|
||||||
console.log(res.request.responseURL);
|
});
|
||||||
if (status === 302) {
|
// console.log(res);
|
||||||
console.log(Location);
|
let res_data = res.data;
|
||||||
|
try {
|
||||||
|
res_data = JSON.parse(res_data);
|
||||||
|
}catch (e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
console.log(res.data);
|
// console.log(res_data);
|
||||||
if(typeof(res.data)==='string' && /#EXTM3U/.test(res.data)){
|
// console.log(res.url);
|
||||||
|
// console.log(res.redirect);
|
||||||
|
if(res.redirect){ // 重定向的直接设置播放器的值
|
||||||
|
if(isVideo(res.url)){ // 判断重定向的为直链
|
||||||
|
methods.setPlayUrl(res.url);
|
||||||
|
}else{
|
||||||
|
console.log('重定向待嗅探页面,但是由于跨域问题,只好内嵌播放页播放');
|
||||||
|
iframeSrc.value = res.url;
|
||||||
|
}
|
||||||
|
return
|
||||||
|
// throw new Error('重定向网页直接播放,尝试嗅探(存在跨域无法嗅探问题,暂时考虑直接内嵌人家的播放页)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// const res = await axios.get(url,{maxRedirects: 0});
|
||||||
|
// const { status, headers: { Location } } = res;
|
||||||
|
// // console.log(status);
|
||||||
|
// console.log(res.request.responseURL);
|
||||||
|
// if (status === 302) {
|
||||||
|
// console.log(Location);
|
||||||
|
// }
|
||||||
|
// console.log(res.data);
|
||||||
|
|
||||||
|
console.log(res_data);
|
||||||
|
if(typeof(res_data)==='string'){
|
||||||
iframeRef.value.contentWindow.location.reload();
|
iframeRef.value.contentWindow.location.reload();
|
||||||
iframeSrc.value = url;
|
iframeSrc.value = url;
|
||||||
throw new Error('重定向类文件无法直接播放,尝试嗅探');
|
throw new Error('返回的数据是文本无法直接播放,尝试嗅探');
|
||||||
} else if(!res.data.parse&&res.data.url){
|
} else if(!res_data.parse&&res_data.url){
|
||||||
methods.setPlayUrl(res.data.url);
|
methods.setPlayUrl(res_data.url);
|
||||||
}else if(/url=/.test(res.data.url)){
|
}else if(/url=/.test(res_data.url)){
|
||||||
iframeSrc.value = res.data.url;
|
iframeSrc.value = res_data.url;
|
||||||
} else if((res.data.parse||res.data.jx)&&res.data.url){
|
} else if((res_data.parse||res_data.jx)&&res_data.url){
|
||||||
console.log(ctx.value);
|
console.log(ctx.value);
|
||||||
iframeSrc.value = res.data.url;
|
iframeSrc.value = res_data.url;
|
||||||
if(confirm('该视频来自其它正版地址,drpy网页暂未实现解析功能,是否跳到正版站通过油猴插件等手段播放?')){
|
if(confirm('该视频来自其它正版地址,drpy网页暂未实现解析功能,是否跳到正版站通过油猴插件等手段播放?')){
|
||||||
open(res.data.url);
|
open(res_data.url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}catch (e) {
|
}catch (e) {
|
||||||
@ -365,6 +399,7 @@ const app = createApp({
|
|||||||
photoVisible:photoVisible,
|
photoVisible:photoVisible,
|
||||||
iframeRef:iframeRef,
|
iframeRef:iframeRef,
|
||||||
sniffer:sniffer,
|
sniffer:sniffer,
|
||||||
|
isVideo,getRealUrl
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -392,6 +427,7 @@ eruda.init();
|
|||||||
<!--<script charset="UTF-8" id="LA_COLLECT" src="/web/cms/mxpro/js/js-sdk-pro.min.js"></script>-->
|
<!--<script charset="UTF-8" id="LA_COLLECT" src="/web/cms/mxpro/js/js-sdk-pro.min.js"></script>-->
|
||||||
<!--<script>LA.init({id:"JYQUFCtAOBTUMsNQ",ck:"JYQUFCtAOBTUMsNQ"})</script>-->
|
<!--<script>LA.init({id:"JYQUFCtAOBTUMsNQ",ck:"JYQUFCtAOBTUMsNQ"})</script>-->
|
||||||
<script type="text/javascript" src="/web/cms/mxpro/js/stui_default.js "></script>
|
<script type="text/javascript" src="/web/cms/mxpro/js/stui_default.js "></script>
|
||||||
|
|
||||||
<!--弹窗样式和自动弹窗方法-->
|
<!--弹窗样式和自动弹窗方法-->
|
||||||
<link rel="stylesheet" href="/web/cms/mxpro/css/notice.css" type="text/css">
|
<link rel="stylesheet" href="/web/cms/mxpro/css/notice.css" type="text/css">
|
||||||
<script type="text/javascript" src="/web/cms/mxpro/js/mxhtml.js"></script>
|
<script type="text/javascript" src="/web/cms/mxpro/js/mxhtml.js"></script>
|
||||||
|
|||||||
39
templates/cms/mxpro/js/commonUtil.js
Normal file
39
templates/cms/mxpro/js/commonUtil.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
var commonUtil = {
|
||||||
|
isVideo(playUrl){
|
||||||
|
let res_url = playUrl.split('?')[0];
|
||||||
|
if(playUrl.endsWith('.m3u8')||res_url.endsWith('.m3u8')){
|
||||||
|
return true
|
||||||
|
}else if(playUrl.endsWith('.mp4')||res_url.endsWith('.mp4')){
|
||||||
|
return true
|
||||||
|
}else if(/\.(m4a|mp3|flv|aac)$/.test(playUrl)||/\.(m4a|mp3|flv|aac)$/.test(res_url)){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
getLocationFromRedirect(
|
||||||
|
originUrl,
|
||||||
|
method = "GET"
|
||||||
|
){
|
||||||
|
return new Promise<string>((resolve, reject) => {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open(method, originUrl, true);
|
||||||
|
xhr.onload = function () {
|
||||||
|
resolve(xhr.responseURL);
|
||||||
|
};
|
||||||
|
xhr.onerror = reject;
|
||||||
|
xhr.send(null);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
get302UrlResponse(url, callback) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', url, true);
|
||||||
|
xhr.onload = function () {
|
||||||
|
callback(xhr.responseURL);
|
||||||
|
}
|
||||||
|
xhr.send(null);
|
||||||
|
},
|
||||||
|
async getRealUrl(url,callback){
|
||||||
|
const res = await axios.get(`web/302redirect?url=${encodeURIComponent(url)}`);
|
||||||
|
return callback(res);
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user