1
0
mirror of https://github.com/hjdhnx/dr_py.git synced 2025-05-01 03:54:01 -04:00

增加后端代理,解决部分网页的播放问题

This commit is contained in:
晚风拂柳颜 2023-05-12 12:02:47 +08:00
parent 407d8aa791
commit cb03151232
7 changed files with 169 additions and 30 deletions

25
app.py

@ -9,11 +9,12 @@ from flask_migrate import Migrate
from base import config
from base.database import db
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 js.rules import getRuleLists
import sys
def create_flask_app():
app = Flask(__name__, static_folder='static', static_url_path='/static')
app.config.from_object(config) # 单独的配置文件里写了这里就不用弄json中文显示了
@ -31,22 +32,28 @@ def create_flask_app():
# logger.info(f"自定义播放解析地址:{lsg.getItem('PLAY_URL')}")
logger.info(f'当前操作系统{sys.platform}')
rule_list = getRuleLists()
wlan_info,_ = get_wlan_info()
wlan_info, _ = get_wlan_info()
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.app = app
db.create_all(app=app)
return app
app = create_flask_app()
migrate = Migrate(app, db)
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 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')
else:
print(f'当前python版本{now_python_ver}为3.9.0及以上,不支持gevent')
@ -54,10 +61,16 @@ else:
if __name__ == "__main__":
http_port = int(app.config.get('HTTP_PORT', 5705))
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):
# 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((http_host, http_port), app, log=logger)
server.serve_forever()
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
ENV = '{"bili_cookie":""}' # 自定义环境变量
UPDATE_PROXY = 'https://ghproxy.net/' # 检测升级代理
Thread = True # 开启windows多线程调用

@ -6,10 +6,11 @@
import functools
import json
import os
from urllib.parse import urljoin
import requests
from flask import Blueprint, abort, request, render_template, send_from_directory, render_template_string, jsonify, \
make_response, redirect, \
current_app
current_app, url_for
from time import time
from utils.web import getParmas, get_interval
from utils.cfg import cfg
@ -38,12 +39,14 @@ def custom_static_cms(filename):
# print(filename)
return send_from_directory('templates/cms', filename)
@web.route('/player/<path:filename>')
def custom_static_player(filename):
# 自定义静态目录 {{ url_for('custom_static',filename='help.txt')}}
# print(filename)
return send_from_directory('templates/player', filename)
@web.route('/<web_name>/<theme>')
def web_index(web_name, theme):
ctx = {'web_name': web_name, 'key': '关键词', 'description': '描述'}
@ -67,7 +70,7 @@ def web_index(web_name, theme):
ctx['tid'] = tid
ctx['tname'] = tname
ctx['url'] = url
print('tid:',tid)
print('tid:', tid)
file_path = os.path.abspath(f'js/{web_name}.js')
print(file_path)
@ -86,4 +89,51 @@ def web_index(web_name, theme):
else:
return render_template(f'cms/{theme}/homeContent.html', ctx=ctx)
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 %}
<div class="red">
<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="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>

@ -22,6 +22,7 @@
<script src="/static/js/axios.min.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>
<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>
@ -243,39 +244,72 @@ const app = createApp({
const photoVisible = ref(false);
const iframeRef = ref(null);
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 = {
async lazyPlay(url){
iframeShow.value = true;
console.log('准备处理播放地址:'+url);
clearInterval(sniffer);
try {
if(/\.(m3u8|mp4)/.test(url)){
if(isVideo(url)){
console.log('直接播放');
methods.setPlayUrl(url);
return
}
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);
const res =await getRealUrl(url,(resp)=>{
// console.log('代理数据:',resp.data);
return resp.data
});
// console.log(res);
let res_data = res.data;
try {
res_data = JSON.parse(res_data);
}catch (e) {
}
console.log(res.data);
if(typeof(res.data)==='string' && /#EXTM3U/.test(res.data)){
// console.log(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();
iframeSrc.value = url;
throw new Error('重定向类文件无法直接播放,尝试嗅探');
} else if(!res.data.parse&&res.data.url){
methods.setPlayUrl(res.data.url);
}else if(/url=/.test(res.data.url)){
iframeSrc.value = res.data.url;
} else if((res.data.parse||res.data.jx)&&res.data.url){
throw new Error('返回的数据是文本无法直接播放,尝试嗅探');
} else if(!res_data.parse&&res_data.url){
methods.setPlayUrl(res_data.url);
}else if(/url=/.test(res_data.url)){
iframeSrc.value = res_data.url;
} else if((res_data.parse||res_data.jx)&&res_data.url){
console.log(ctx.value);
iframeSrc.value = res.data.url;
iframeSrc.value = res_data.url;
if(confirm('该视频来自其它正版地址,drpy网页暂未实现解析功能,是否跳到正版站通过油猴插件等手段播放?')){
open(res.data.url);
open(res_data.url);
}
}
}catch (e) {
@ -365,6 +399,7 @@ const app = createApp({
photoVisible:photoVisible,
iframeRef:iframeRef,
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>LA.init({id:"JYQUFCtAOBTUMsNQ",ck:"JYQUFCtAOBTUMsNQ"})</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">
<script type="text/javascript" src="/web/cms/mxpro/js/mxhtml.js"></script>

@ -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);
}
};