diff --git a/app.py b/app.py index b83792ebcde32c69bd3b959f753473c7cd459a61..1e9a562287049809fa54aed05884d2aab48c164c 100644 --- a/app.py +++ b/app.py @@ -22,6 +22,7 @@ def create_flask_app(): app.register_blueprint(vod.vod, url_prefix='') app.register_blueprint(cls.cls, url_prefix='/cls') app.register_blueprint(layui.layui, url_prefix='/layui') + app.register_blueprint(parse.parse, url_prefix='/parse') app.logger.name = "drLogger" # lsg = service.storage_service() logger.info(f"默认解析地址:{app.config.get('PLAY_URL')}") diff --git a/controllers/__init__.py b/controllers/__init__.py index 937be10cc3ef6a73fd3aee73a48d3a2155b80d57..cac280e561d7454e38368c800967efb2b2453222 100644 --- a/controllers/__init__.py +++ b/controllers/__init__.py @@ -11,4 +11,5 @@ from . import vod from . import cms from . import cls from . import classes -from . import layui \ No newline at end of file +from . import layui +from . import parse \ No newline at end of file diff --git a/controllers/home.py b/controllers/home.py index 68d6c791ad84e44486e260e2f36bdc9bdac82df9..cbabc859fb45242bffd0acb59fe2e999919ac91e 100644 --- a/controllers/home.py +++ b/controllers/home.py @@ -210,7 +210,7 @@ def config_render(mode): # print(ali_token) customConfig = getCustonDict(host,ali_token) # print(customConfig) - jxs = getJxs() + jxs = getJxs(host=host) lsg = storage_service() use_py = lsg.getItem('USE_PY') pys = getPys() if use_py else [] @@ -242,7 +242,6 @@ def config_gen(): store_conf_dict = lsg.getStoreConfDict() new_conf.update(store_conf_dict) try: - jxs = getJxs() lsg = storage_service() use_py = lsg.getItem('USE_PY') pys = getPys() if use_py else False @@ -250,26 +249,32 @@ def config_gen(): alists_str = json.dumps(alists,ensure_ascii=False) rules = getRules('js') rules = get_multi_rules(rules) - set_local = render_template('config.txt',pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,0),mode=0,host=getHost(0),jxs=jxs) + host0 = getHost(0) + jxs = getJxs(host=host0) + set_local = render_template('config.txt',pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,0),mode=0,host=host0,jxs=jxs) # print(set_local) - set_area = render_template('config.txt',pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,1),mode=1,host=getHost(1),jxs=jxs) - set_online = render_template('config.txt',pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,2),mode=1,host=getHost(2),jxs=jxs) + host1 = getHost(1) + jxs = getJxs(host=host1) + set_area = render_template('config.txt',pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,1),mode=1,host=host1,jxs=jxs) + host2 = getHost(2) + jxs = getJxs(host=host2) + set_online = render_template('config.txt',pys=pys,rules=rules,alists=alists,alists_str=alists_str,live_url=get_live_url(new_conf,2),mode=1,host=host2,jxs=jxs) ali_token = new_conf.ALI_TOKEN with open('txt/pycms0.json','w+',encoding='utf-8') as f: - customConfig = getCustonDict(getHost(0),ali_token) + customConfig = getCustonDict(host0,ali_token) set_dict = custom_merge(parseText(set_local), customConfig) merged_hide(set_dict) # set_dict = json.loads(set_local) f.write(json.dumps(set_dict,ensure_ascii=False,indent=4)) with open('txt/pycms1.json','w+',encoding='utf-8') as f: - customConfig = getCustonDict(getHost(1),ali_token) + customConfig = getCustonDict(host1,ali_token) set_dict = custom_merge(parseText(set_area), customConfig) merged_hide(set_dict) # set_dict = json.loads(set_area) f.write(json.dumps(set_dict,ensure_ascii=False,indent=4)) with open('txt/pycms2.json','w+',encoding='utf-8') as f: - customConfig = getCustonDict(getHost(2),ali_token) + customConfig = getCustonDict(host2,ali_token) set_dict = custom_merge(parseText(set_online), customConfig) merged_hide(set_dict) # set_dict = json.loads(set_online) diff --git a/controllers/parse.py b/controllers/parse.py new file mode 100644 index 0000000000000000000000000000000000000000..5f89c13a8e1310b4bf687acb95ce2fb13194ba3b --- /dev/null +++ b/controllers/parse.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# File : parse.py +# Author: DaShenHan&道长-----先苦后甜,任凭晚风拂柳颜------ +# Date : 2022/9/24 +from flask import Blueprint, jsonify +from utils.web import getParmas,get_interval +import os +from utils.log import logger +from utils.pyctx import py_ctx,getPreJs,runJScode,JsObjectWrapper,PyJsString,parseText,jsoup,time + +parse = Blueprint("parse", __name__) + +class R(object): + + @classmethod + def ok(self, msg='操作成功', url=None, extra=None): + if extra is None: + extra = {} + result = {"code": 200, "msg": msg, "url":url} + result.update(extra) + return jsonify(result) + + @classmethod + def error(self,msg="系统异常",code=404,extra=None): + if extra is None: + extra = {} + result = {"code": code, "msg": msg} + result.update(extra) + return jsonify(result) + + @classmethod + def success(self,msg='操作成功', url=None,extra=None): + return self.ok(msg,url,extra) + + @classmethod + def failed(self,msg="系统异常", code=404,extra=None): + return self.error(msg,code,extra) + +@parse.route('/api/') +def parse_home(filename): + url = getParmas('url') + # http://localhost:5705/parse/api/%E6%97%A0%E5%90%8D.js?url=https://www.iqiyi.com/v_ik3832z0go.html + if not url or not url.startswith('http'): + return R.failed(f'url必填!{url},且必须是http开头') + base_path = 'jiexi' + os.makedirs(base_path, exist_ok=True) + file_path = os.path.join(base_path, filename) + if not os.path.exists(file_path): + return R.failed(f'{file_path}文件不存在') + logger.info(f'开始尝试通过{filename}解析:{url}') + + jsp = jsoup(url) + py_ctx.update({ + 'vipUrl': url, + 'fetch_params': {'headers': {'Referer':url}, 'timeout': 10, 'encoding': 'utf-8'}, + 'jsp':jsp + }) + ctx = py_ctx + with open(file_path,encoding='utf-8') as f: + code = f.read() + jscode = getPreJs() + code.strip().replace('js:', '', 1) + # print(jscode) + t1 = time() + try: + loader, _ = runJScode(jscode, ctx=ctx) + realUrl = loader.eval('realUrl') + if not realUrl: + return R.failed(f'解析失败:{realUrl}') + if isinstance(realUrl, PyJsString): + realUrl = parseText(str(realUrl)) + return R.success(f'{filename}解析成功',realUrl,{'time':f'{get_interval(t1)}毫秒'}) + except Exception as e: + msg = f'{filename}解析出错:{e}' + logger.info(msg) + return R.failed(msg,extra={'time':f'{get_interval(t1)}毫秒'}) \ No newline at end of file diff --git "a/jiexi/\346\227\240\345\220\215.js" "b/jiexi/\346\227\240\345\220\215.js" new file mode 100644 index 0000000000000000000000000000000000000000..6c71b9581206076c2e8c3a1bdfa585e36de8c281 --- /dev/null +++ "b/jiexi/\346\227\240\345\220\215.js" @@ -0,0 +1,12 @@ +let jxUrl = 'http://api.ckflv.cn/?url='; +fetch_params.headers.Referer = jxUrl; +try { + // realUrl = null; + let html = request(jxUrl+vipUrl); + log(html); + realUrl = jsp.pjfh(html,'$..url'); + log('解析到真实播放地址:'+realUrl); +}catch (e) { + log('解析发生错误:'+e.message); + realUrl = vipUrl; +} \ No newline at end of file diff --git a/js/rules.py b/js/rules.py index 67451d092a1855643a980edc70fc02d7839f1bcd..5c02827131b6166116be0ac8fb26becf92e57a0b 100644 --- a/js/rules.py +++ b/js/rules.py @@ -10,6 +10,7 @@ import js2py from utils.log import logger # from utils.web import get_interval,UA from utils.ua import UA,get_interval +from flask import render_template_string def getRuleLists(): base_path = os.path.dirname(os.path.abspath(__file__)) # 当前文件所在目录 @@ -86,8 +87,12 @@ def getRules(path='cache'): logger.info(f'自动配置装载耗时:{get_interval(t1)}毫秒') return rules -def jxTxt2Json(text:str): - data = text.strip().split('\n') +def jxTxt2Json(text:str,host:str): + try: + data = render_template_string(text,host=host).strip().split('\n') + except Exception as e: + logger.info(f'jxTxt2Json发生错误:{e}') + data = [] jxs = [] for i in data: i = i.strip() @@ -104,7 +109,7 @@ def jxTxt2Json(text:str): logger.info(f'解析行有错误:{e}') return jxs -def getJxs(path='js'): +def getJxs(path='js',host=None): custom_jx = 'base/解析.conf' if not os.path.exists(custom_jx): with open(custom_jx,'w+',encoding='utf-8') as f1: @@ -118,10 +123,10 @@ def getJxs(path='js'): with open(f'{path}/解析.conf',encoding='utf-8') as f: text = f.read() - jxs = jxTxt2Json(text) + jxs = jxTxt2Json(text,host) with open(custom_jx,encoding='utf-8') as f2: text = f2.read() - jxs2 = jxTxt2Json(text) + jxs2 = jxTxt2Json(text,host) jxs.extend(jxs2) print(f'共计{len(jxs)}条解析') return jxs diff --git a/js/version.txt b/js/version.txt index 7560320b40def2175dd2341eb555aef650172499..bf462cbbd1ccae8527674eca47640a22dcefb8f9 100644 --- a/js/version.txt +++ b/js/version.txt @@ -1 +1 @@ -3.7.9 \ No newline at end of file +3.7.10 \ No newline at end of file diff --git "a/js/\350\247\243\346\236\220.conf" "b/js/\350\247\243\346\236\220.conf" index d007fd9c42e8d955f7d7d261691774634e8a85fd..29a8dc5c88c7520d8468cc67e01b940b3c3ac859 100644 --- "a/js/\350\247\243\346\236\220.conf" +++ "b/js/\350\247\243\346\236\220.conf" @@ -8,7 +8,8 @@ # 快看,http://api.8a5.cn/parse/kuaikan/de.php?url=,1 # 钢铁侠,https://json.freejx.in/?url=,1 # 绿叶,https://hc.izny.cn/json.php?url=,1 -无名1,http://api.ckflv.cn/?url=,1 +# 无名1,http://api.ckflv.cn/?url=,1 +无名1,{{host}}/parse/api/无名.js?url=,1 BT5V,https://rx.bt5v.com/json/jsonindex.php/?url=,1 # 查询,https://chaxun.truechat365.com/?url= # 这个解析真的牛逼,只能电脑看 # llq,https://hc.izny.cn/json.php?url=,1 diff --git a/readme.md b/readme.md index 6eb13e31e7410b0533caf1b93cd022e331dfa2f1..37ff0cca34c89939f2406f190ce2cb38d2f47eaf 100644 --- a/readme.md +++ b/readme.md @@ -46,6 +46,9 @@ [dockerfile教程](https://blog.csdn.net/qq_46158060/article/details/125718218) [获取本地设备信息](https://blog.csdn.net/cui_yonghua/article/details/125508991) [获取本地设备信息](https://m.jb51.net/article/140716.htm) +###### 2022/09/25 +- [X] 1.v3.7.10 增加了自定义解析功能,解析.conf支持变量{{host}} +- [X] 2.新增了 jiexi/无名.js作为示例,接受vipUrl返回realUrl ###### 2022/09/23 - [X] 1.v3.7.5 优化了首图2模板的搜索定位以及几个相关的源 - [X] 2.二级渲染功能拆分,js单独调用 diff --git a/utils/pyctx.py b/utils/pyctx.py new file mode 100644 index 0000000000000000000000000000000000000000..e95300c17c1efc7d5fa51bf0ca613cde701b0757 --- /dev/null +++ b/utils/pyctx.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# File : pyctx.py +# Author: DaShenHan&道长-----先苦后甜,任凭晚风拂柳颜------ +# Date : 2022/9/24 + +import json + +import requests +from utils.web import * +from utils.log import logger +from utils.encode import base64Encode,baseDecode,fetch,post,request,getCryptoJS,getPreJs,buildUrl,getHome,parseText +from utils.encode import setDetail,join,urljoin2,parseText,requireCache +from utils.encode import md5 as mmd5 +from utils.parser import runPy,runJScode,JsObjectWrapper,PyJsObject,PyJsString +from urllib.parse import quote +from utils.htmlParser import jsoup +from controllers.service import storage_service + +def setItem(key,value): + lsg = storage_service() + if isinstance(key,PyJsString): + key = parseText(str(key)) + if isinstance(value,PyJsString): + value = parseText(str(value)) + return lsg.setItem(key,value) + +def getItem(key,value=''): + lsg = storage_service() + if isinstance(key,PyJsString): + key = parseText(str(key)) + if isinstance(value,PyJsString): + value = parseText(str(value)) + return lsg.getItem(key,value) + +def clearItem(key): + lsg = storage_service() + if isinstance(key,PyJsString): + key = parseText(str(key)) + return lsg.clearItem(key) + +def encodeUrl(url): + # return base64Encode(quote(url)) + # return base64Encode(url) + # print(type(url)) + if isinstance(url,PyJsString): + # obj = obj.to_dict() + url = parseText(str(url)) + return quote(url) + +def stringify(obj): + if isinstance(obj,PyJsObject): + # obj = obj.to_dict() + obj = parseText(str(obj)) + return json.dumps(obj, separators=(',', ':'), ensure_ascii=False) + +def requireObj(url): + if isinstance(url,PyJsString): + url = parseText(str(url)) + return requireCache(url) + +def md5(text): + if isinstance(text,PyJsString): + text = parseText(str(text)) + return mmd5(text) + +py_ctx = { +'requests':requests,'print':print,'base64Encode':base64Encode,'baseDecode':baseDecode, +'log':logger.info,'fetch':fetch,'post':post,'request':request,'getCryptoJS':getCryptoJS, +'buildUrl':buildUrl,'getHome':getHome,'setDetail':setDetail,'join':join,'urljoin2':urljoin2, +'PC_UA':PC_UA,'MOBILE_UA':MOBILE_UA,'UC_UA':UC_UA,'IOS_UA':IOS_UA, +'setItem':setItem,'getItem':getItem,'clearItem':clearItem,'stringify':stringify,'encodeUrl':encodeUrl, +'requireObj':requireObj,'md5':md5 +} \ No newline at end of file diff --git a/utils/update.py b/utils/update.py index 491a866ef9c4e52c2c84a271aee86d81b8fa16b7..195b1b7913171618056acacee1da8f23b3c3cb5b 100644 --- a/utils/update.py +++ b/utils/update.py @@ -127,8 +127,8 @@ def copy_to_update(): logger.info(f'升级失败,找不到目录{dr_path}') return False # 千万不能覆盖super,base - paths = ['js','models','controllers','libs','static','templates','utils','txt'] - exclude_files = ['txt/pycms0.json','txt/pycms1.json','txt/pycms2.json'] + paths = ['js','models','controllers','libs','static','templates','utils','txt','jiexi'] + exclude_files = ['txt/pycms0.json','txt/pycms1.json','txt/pycms2.json','base/rules.db'] for path in paths: force_copy_files(os.path.join(dr_path, path),os.path.join(base_path, path),exclude_files) try: