发布新版本,drpy源全面支持hostJs,具体写法参考8k影视

This commit is contained in:
晚风拂柳颜 2023-06-07 14:43:03 +08:00
parent d668f49e6c
commit aa8d9ecac6
9 changed files with 306 additions and 235 deletions

View File

@ -14,8 +14,10 @@ from utils.web import *
from utils.system import getHost from utils.system import getHost
from utils.config import playerConfig from utils.config import playerConfig
from utils.log import logger from utils.log import logger
from utils.encode import base64Encode,base64Decode,fetch,post,request,getCryptoJS,getPreJs,buildUrl,getHome,atob,btoa from utils.encode import base64Encode, base64Decode, fetch, post, request, getCryptoJS, getPreJs, buildUrl, getHome, \
from utils.encode import verifyCode,setDetail,join,urljoin2,parseText,requireCache,forceOrder,base64ToImage,encodeStr, decodeStr atob, btoa
from utils.encode import verifyCode, setDetail, join, urljoin2, parseText, requireCache, forceOrder, base64ToImage, \
encodeStr, decodeStr
from utils.encode import md5 as mmd5 from utils.encode import md5 as mmd5
from utils.safePython import safePython from utils.safePython import safePython
from utils.parser import runPy, runJScode, JsObjectWrapper, PyJsObject, PyJsString from utils.parser import runPy, runJScode, JsObjectWrapper, PyJsObject, PyJsString
@ -26,6 +28,7 @@ from flask import url_for,redirect,render_template_string
from easydict import EasyDict as edict from easydict import EasyDict as edict
from controllers.service import storage_service from controllers.service import storage_service
def setItem(key, value): def setItem(key, value):
lsg = storage_service() lsg = storage_service()
if isinstance(key, PyJsString): if isinstance(key, PyJsString):
@ -34,6 +37,7 @@ def setItem(key,value):
value = parseText(str(value)) value = parseText(str(value))
return lsg.setItem(key, value) return lsg.setItem(key, value)
def getItem(key, value=''): def getItem(key, value=''):
lsg = storage_service() lsg = storage_service()
if isinstance(key, PyJsString): if isinstance(key, PyJsString):
@ -42,12 +46,14 @@ def getItem(key,value=''):
value = parseText(str(value)) value = parseText(str(value))
return lsg.getItem(key, value) return lsg.getItem(key, value)
def clearItem(key): def clearItem(key):
lsg = storage_service() lsg = storage_service()
if isinstance(key, PyJsString): if isinstance(key, PyJsString):
key = parseText(str(key)) key = parseText(str(key))
return lsg.clearItem(key) return lsg.clearItem(key)
def encodeUrl(url): def encodeUrl(url):
# return base64Encode(quote(url)) # return base64Encode(quote(url))
# return base64Encode(url) # return base64Encode(url)
@ -57,31 +63,38 @@ def encodeUrl(url):
url = parseText(str(url)) url = parseText(str(url))
return quote(url) return quote(url)
def stringify(obj): def stringify(obj):
if isinstance(obj, PyJsObject): if isinstance(obj, PyJsObject):
# obj = obj.to_dict() # obj = obj.to_dict()
obj = parseText(str(obj)) obj = parseText(str(obj))
return json.dumps(obj, separators=(',', ':'), ensure_ascii=False) return json.dumps(obj, separators=(',', ':'), ensure_ascii=False)
def requireObj(url): def requireObj(url):
if isinstance(url, PyJsString): if isinstance(url, PyJsString):
url = parseText(str(url)) url = parseText(str(url))
return requireCache(url) return requireCache(url)
def md5(text): def md5(text):
if isinstance(text, PyJsString): if isinstance(text, PyJsString):
text = parseText(str(text)) text = parseText(str(text))
return mmd5(text) return mmd5(text)
py_ctx = { py_ctx = {
'requests': requests, 'print': print, 'base64Encode': base64Encode, 'base64Decode': base64Decode, 'requests': requests, 'print': print, 'base64Encode': base64Encode, 'base64Decode': base64Decode,
'log': logger.info, 'fetch': fetch, 'post': post, 'request': request, 'getCryptoJS': getCryptoJS, 'log': logger.info, 'fetch': fetch, 'post': post, 'request': request, 'getCryptoJS': getCryptoJS,
'buildUrl': buildUrl, 'getHome': getHome, 'setDetail': setDetail, 'join': join, 'urljoin2': urljoin2, 'buildUrl': buildUrl, 'getHome': getHome, 'setDetail': setDetail, 'join': join, 'urljoin2': urljoin2,
'PC_UA': PC_UA, 'MOBILE_UA': MOBILE_UA, 'UC_UA': UC_UA, 'UA': UA, 'IOS_UA': IOS_UA, 'PC_UA': PC_UA, 'MOBILE_UA': MOBILE_UA, 'UC_UA': UC_UA, 'UA': UA, 'IOS_UA': IOS_UA,
'setItem': setItem, 'getItem': getItem, 'clearItem': clearItem, 'stringify': stringify, 'encodeUrl': encodeUrl, 'setItem': setItem, 'getItem': getItem, 'clearItem': clearItem, 'stringify': stringify, 'encodeUrl': encodeUrl,
'requireObj':requireObj,'md5':md5,'atob': atob, 'btoa':btoa,'base64ToImage': base64ToImage, 'encodeStr': encodeStr, 'requireObj': requireObj, 'md5': md5, 'atob': atob, 'btoa': btoa, 'base64ToImage': base64ToImage,
'encodeStr': encodeStr,
'decodeStr': decodeStr 'decodeStr': decodeStr
} }
# print(getCryptoJS()) # print(getCryptoJS())
class CMS: class CMS:
@ -150,6 +163,32 @@ class CMS:
self.PlayParse = PlayParse self.PlayParse = PlayParse
host = rule.get('host', '').rstrip('/') host = rule.get('host', '').rstrip('/')
host = unquote(host) host = unquote(host)
HOST = host
hostJs = rule.get('hostJs', '')
if hostJs:
try:
jsp = jsoup(HOST)
py_ctx.update({
'HOST': HOST,
'jsp': jsp,
'jq': jsp,
'TYPE': 'init',
})
ctx = py_ctx
jscode = getPreJs() + hostJs.strip().replace('js:', '', 1)
# print(jscode)
loader, _ = runJScode(jscode, ctx=ctx)
# print(loader.toString())
HOST = loader.eval('HOST')
# print(vods)
# 一般都是正常的str
if isinstance(HOST, PyJsString): # JsObjectWrapper
HOST = parseText(str(HOST))
host = HOST.rstrip('/')
print('host:',host)
except Exception as e:
logger.info(f'执行{hostJs}获取host发生错误:{e}')
timeout = rule.get('timeout', 5000) timeout = rule.get('timeout', 5000)
homeUrl = rule.get('homeUrl', '/') homeUrl = rule.get('homeUrl', '/')
url = rule.get('url', '') url = rule.get('url', '')
@ -451,7 +490,6 @@ class CMS:
except Exception as e: except Exception as e:
return f'{name}发生了错误:{e}' return f'{name}发生了错误:{e}'
def homeContent(self, fypage=1): def homeContent(self, fypage=1):
# yanaifei # yanaifei
# https://yanetflix.com/vodtype/dianying.html # https://yanetflix.com/vodtype/dianying.html
@ -528,7 +566,9 @@ class CMS:
video_result = self.homeVideoContent(html, fypage) video_result = self.homeVideoContent(html, fypage)
except Exception as e: except Exception as e:
logger.info(f'{self.getName()}主页发生错误:{e}') logger.info(f'{self.getName()}主页发生错误:{e}')
classes = list(filter(lambda x:not self.cate_exclude or not jsoup(self.url).test(self.cate_exclude, x['type_name']),classes)) classes = list(
filter(lambda x: not self.cate_exclude or not jsoup(self.url).test(self.cate_exclude, x['type_name']),
classes))
result['class'] = classes result['class'] = classes
if self.filter: if self.filter:
if isinstance(self.filter, dict): if isinstance(self.filter, dict):
@ -586,12 +626,14 @@ class CMS:
return self.blank() return self.blank()
jsp = jsoup(self.homeUrl) jsp = jsoup(self.homeUrl)
pp = self.一级.split(';') pp = self.一级.split(';')
def getPP(p, pn, pp, ppn): def getPP(p, pn, pp, ppn):
try: try:
ps = pp[ppn] if p[pn] == '*' and len(pp) > ppn else p[pn] ps = pp[ppn] if p[pn] == '*' and len(pp) > ppn else p[pn]
return ps return ps
except Exception as e: except Exception as e:
return '' return ''
p0 = getPP(p, 0, pp, 0) p0 = getPP(p, 0, pp, 0)
is_json = str(p0).startswith('json:') is_json = str(p0).startswith('json:')
if is_json: if is_json:
@ -628,7 +670,8 @@ class CMS:
desc = pdfh(item2, p4) desc = pdfh(item2, p4)
except: except:
desc = '' desc = ''
links = [pd(item2, _p5) if not self.detailUrl else pdfh(item2, _p5) for _p5 in p5.split('+')] links = [pd(item2, _p5) if not self.detailUrl else pdfh(item2, _p5) for _p5 in
p5.split('+')]
vid = '$'.join(links) vid = '$'.join(links)
if len(p) > 6 and p[6]: if len(p) > 6 and p[6]:
content = pdfh(item2, p6) content = pdfh(item2, p6)
@ -896,7 +939,8 @@ class CMS:
result['total'] = cnt result['total'] = cnt
# print(result) # print(result)
# print(result['pagecount']) # print(result['pagecount'])
logger.info(f'{self.getName()}获取分类{fyclass}{fypage}页耗时:{get_interval(t1)}毫秒,共计{round(len(str(result)) / 1000, 2)} kb') logger.info(
f'{self.getName()}获取分类{fyclass}{fypage}页耗时:{get_interval(t1)}毫秒,共计{round(len(str(result)) / 1000, 2)} kb')
nodata = { nodata = {
'list': [{'vod_name': '无数据,防无限请求', 'vod_id': 'no_data', 'vod_remarks': '不要点,会崩的', 'list': [{'vod_name': '无数据,防无限请求', 'vod_id': 'no_data', 'vod_remarks': '不要点,会崩的',
'vod_pic': 'https://ghproxy.net/https://raw.githubusercontent.com/hjdhnx/dr_py/main/404.jpg'}], 'vod_pic': 'https://ghproxy.net/https://raw.githubusercontent.com/hjdhnx/dr_py/main/404.jpg'}],
@ -938,7 +982,8 @@ class CMS:
vod['vod_pic'] = vod_pic vod['vod_pic'] = vod_pic
vod['vod_play_url'] = '嗅探播放$' + play_url + url.split('@@')[0] vod['vod_play_url'] = '嗅探播放$' + play_url + url.split('@@')[0]
elif not p or (not isinstance(p, dict) and not isinstance(p, str)) or (isinstance(p, str) and not str(p).startswith('js:')): elif not p or (not isinstance(p, dict) and not isinstance(p, str)) or (
isinstance(p, str) and not str(p).startswith('js:')):
pass pass
else: else:
is_json = p.get('is_json', False) if isinstance(p, dict) else False # 二级里加is_json参数 is_json = p.get('is_json', False) if isinstance(p, dict) else False # 二级里加is_json参数
@ -989,6 +1034,7 @@ class CMS:
vod_play_from = '$$$' vod_play_from = '$$$'
playFrom = [] playFrom = []
init_flag = {'ctx': False} init_flag = {'ctx': False}
def js_pre(): def js_pre():
headers['Referer'] = getHome(url) headers['Referer'] = getHome(url)
py_ctx.update({ py_ctx.update({
@ -1004,6 +1050,7 @@ class CMS:
'jsp': jsp, 'jq': jsp, 'setDetail': setDetail, 'play_url': play_url 'jsp': jsp, 'jq': jsp, 'setDetail': setDetail, 'play_url': play_url
}) })
init_flag['ctx'] = True init_flag['ctx'] = True
if p.get('重定向') and str(p['重定向']).startswith('js:'): if p.get('重定向') and str(p['重定向']).startswith('js:'):
if not init_flag['ctx']: if not init_flag['ctx']:
js_pre() js_pre()
@ -1118,9 +1165,11 @@ class CMS:
# vodList = [pq(i).text()+'$'+pd(i,'a&&href') for i in vodList] # 拼接成 名称$链接 # vodList = [pq(i).text()+'$'+pd(i,'a&&href') for i in vodList] # 拼接成 名称$链接
# pq(i).text() # pq(i).text()
if self.play_parse: # 自动base64编码 if self.play_parse: # 自动base64编码
vodList = [(pdfh(html, tab_ext) if tab_ext else tab_name) + '$' + play_url + encodeUrl(i) for i vodList = [(pdfh(html, tab_ext) if tab_ext else tab_name) + '$' + play_url + encodeUrl(i)
for i
in vodList] if is_json else \ in vodList] if is_json else \
[pdfh(i,list_text) + '$' + play_url + encodeUrl(pd(i, list_url)) for i in vodList] # 拼接成 名称$链接 [pdfh(i, list_text) + '$' + play_url + encodeUrl(pd(i, list_url)) for i in
vodList] # 拼接成 名称$链接
else: else:
vodList = [(pdfh(html, tab_ext) if tab_ext else tab_name) + '$' + play_url + i for i in vodList = [(pdfh(html, tab_ext) if tab_ext else tab_name) + '$' + play_url + i for i in
vodList] if is_json else \ vodList] if is_json else \
@ -1140,7 +1189,8 @@ class CMS:
# print(vod_play_from) # print(vod_play_from)
vod['vod_play_url'] = vod_play_url vod['vod_play_url'] = vod_play_url
logger.info(f'{self.getName()}仅二级渲染{len(vod_play_url.split("$$$")[0].split("$"))}集耗时:{get_interval(tt1)}毫秒,共计{round(len(str(vod)) / 1000, 2)} kb') logger.info(
f'{self.getName()}仅二级渲染{len(vod_play_url.split("$$$")[0].split("$"))}集耗时:{get_interval(tt1)}毫秒,共计{round(len(str(vod)) / 1000, 2)} kb')
if show_name: if show_name:
vod['vod_content'] = f'({self.id}){vod.get("vod_content", "")}' vod['vod_content'] = f'({self.id}){vod.get("vod_content", "")}'
@ -1219,7 +1269,8 @@ class CMS:
else: else:
vod = self.blank_vod() vod = self.blank_vod()
else: else:
vod = self.二级渲染(p,detailUrl=detailUrl,orId=orUrl,url=url,vod=vod,show_name=show_name,jsp=jsp,fyclass=fyclass) vod = self.二级渲染(p, detailUrl=detailUrl, orId=orUrl, url=url, vod=vod, show_name=show_name, jsp=jsp,
fyclass=fyclass)
except Exception as e: except Exception as e:
logger.info(f'{self.getName()}获取单个详情页{detailUrl}出错{e}') logger.info(f'{self.getName()}获取单个详情页{detailUrl}出错{e}')
if self.图片来源: if self.图片来源:
@ -1238,7 +1289,8 @@ class CMS:
""" """
# print('进入二级') # print('进入二级')
t1 = time() t1 = time()
array = array if len(array) <= self.limit else array[(fypage-1)*self.limit:min(self.limit*fypage,len(array))] array = array if len(array) <= self.limit else array[
(fypage - 1) * self.limit:min(self.limit * fypage, len(array))]
thread_pool = ThreadPoolExecutor(min(self.limit, len(array))) # 定义线程池来启动多线程执行此任务 thread_pool = ThreadPoolExecutor(min(self.limit, len(array))) # 定义线程池来启动多线程执行此任务
obj_list = [] obj_list = []
try: try:
@ -1256,7 +1308,8 @@ class CMS:
result = { result = {
'list': vod_list 'list': vod_list
} }
logger.info(f'{self.getName()}获取详情页耗时:{get_interval(t1)}毫秒,共计{round(len(str(result)) / 1000, 2)} kb') logger.info(
f'{self.getName()}获取详情页耗时:{get_interval(t1)}毫秒,共计{round(len(str(result)) / 1000, 2)} kb')
except Exception as e: except Exception as e:
result = { result = {
'list': [] 'list': []
@ -1293,6 +1346,7 @@ class CMS:
return ps return ps
except: except:
return '' return ''
if is_js: if is_js:
headers['Referer'] = getHome(url) headers['Referer'] = getHome(url)
py_ctx.update({ py_ctx.update({
@ -1484,7 +1538,8 @@ class CMS:
if isinstance(lazy_url, str) and lazy_url.startswith('http'): if isinstance(lazy_url, str) and lazy_url.startswith('http'):
play_url = lazy_url play_url = lazy_url
else: else:
jscode = str(self.lazy).strip().replace('js:', '', 1) if str(self.lazy).startswith('js:') else js_code jscode = str(self.lazy).strip().replace('js:', '', 1) if str(self.lazy).startswith(
'js:') else js_code
jsp = jsoup(self.url) jsp = jsoup(self.url)
# jscode = f'var input={play_url};{jscode}' # jscode = f'var input={play_url};{jscode}'
# print(jscode) # print(jscode)
@ -1492,7 +1547,8 @@ class CMS:
py_ctx.update({ py_ctx.update({
'input': play_url, 'input': play_url,
'oheaders': self.d.oheaders, 'oheaders': self.d.oheaders,
'fetch_params':{'headers':self.headers,'timeout':self.d.timeout,'encoding':self.d.encoding}, 'fetch_params': {'headers': self.headers, 'timeout': self.d.timeout,
'encoding': self.d.encoding},
'd': self.d, 'd': self.d,
'jxs': jxs, 'jxs': jxs,
'getParse': self.d.getParse, 'getParse': self.d.getParse,
@ -1558,11 +1614,13 @@ class CMS:
logger.info(f'最终返回play_url:{play_url}') logger.info(f'最终返回play_url:{play_url}')
return play_url return play_url
if __name__ == '__main__': if __name__ == '__main__':
print(urljoin('https://api.web.360kan.com/v1/f', print(urljoin('https://api.web.360kan.com/v1/f',
'//0img.hitv.com/preview/sp_images/2022/01/28/202201281528074643023.jpg')) '//0img.hitv.com/preview/sp_images/2022/01/28/202201281528074643023.jpg'))
# exit() # exit()
from utils import parser from utils import parser
# js_path = f'js/玩偶姐姐.js' # js_path = f'js/玩偶姐姐.js'
# js_path = f'js/555影视.js' # js_path = f'js/555影视.js'
with open('../js/模板.js', encoding='utf-8') as f: with open('../js/模板.js', encoding='utf-8') as f:

View File

@ -15,6 +15,7 @@ var rule = {
编码:'',//不填就默认utf-8 编码:'',//不填就默认utf-8
搜索编码:'',//不填则不编码默认都是按utf-8.可优先于全局编码属性.比如网页源码编码是gbk,这里可以指定utf-8搜索独立编码。多数情况这个属性不填或者填写gbk应对特殊的网站搜索 搜索编码:'',//不填则不编码默认都是按utf-8.可优先于全局编码属性.比如网页源码编码是gbk,这里可以指定utf-8搜索独立编码。多数情况这个属性不填或者填写gbk应对特殊的网站搜索
host:'',//网页的域名根,包含http头如 https://www,baidu.com host:'',//网页的域名根,包含http头如 https://www,baidu.com
hostJS:'print(HOST);let html=request(HOST,{headers:{"User-Agent":PC_UA}});let src = jsp.pdfh(html,"ul&&li&&a&&href");print(src);HOST=src.replace("/index.php","")',//网页域名根动态抓取js代码。通过HOST=赋值
homeUrl:'/latest/',//网站的首页链接,可以是完整路径或者相对路径,用于分类获取和推荐获取 fyclass是分类标签 fypage是页数 homeUrl:'/latest/',//网站的首页链接,可以是完整路径或者相对路径,用于分类获取和推荐获取 fyclass是分类标签 fypage是页数
url:'/fyclass/fypage.html[/fyclass/]',//网站的分类页面链接 url:'/fyclass/fypage.html[/fyclass/]',//网站的分类页面链接
detailUrl:'https://yanetflix.com/voddetail/fyid.html',//非必填,二级详情拼接链接,感觉没啥卵用 detailUrl:'https://yanetflix.com/voddetail/fyid.html',//非必填,二级详情拼接链接,感觉没啥卵用

View File

@ -1,3 +1,11 @@
###### 2023/06/07
- [X] 后台管理增加p2p播放器
- [X] 3.9.43beta1 drpy新增hostJs属性可以用js动态捕捉网页根地址下面是一个示例
对应8K影视.js
```javascript
hostJs:'print(HOST);let html=request(HOST,{headers:{"User-Agent":PC_UA}});let src = jsp.pdfh(html,"ul&&li&&a&&href");print(src);HOST=src.replace("/index.php","")'
```
###### 2023/06/02 ###### 2023/06/02
- [X] 3.9.42beta22 后台管理增加两套通用在线播放器地址 - [X] 3.9.42beta22 后台管理增加两套通用在线播放器地址

View File

@ -6,6 +6,7 @@ var rule={
title:'8K影视', title:'8K影视',
模板:'mxone5', 模板:'mxone5',
host:'http://www.8kvod.com', host:'http://www.8kvod.com',
hostJs:'print(HOST);let html=request(HOST,{headers:{"User-Agent":PC_UA}});let src = jsp.pdfh(html,"ul&&li&&a&&href");print(src);HOST=src.replace("/index.php","")',
// host:'http://www.xn--45q.top', // host:'http://www.xn--45q.top',
homeUrl:'/index.php', homeUrl:'/index.php',
url:'/t/fyclass-fypage/', url:'/t/fyclass-fypage/',

View File

@ -1 +1 @@
{"showTime":89200000,"txt":"drpy 3.9.42beta25 -道长"} {"showTime":89200000,"txt":"drpy 3.9.43beta1 -道长"}

View File

@ -1 +1 @@
3.9.42beta27 3.9.43beta1

View File

@ -55,7 +55,7 @@ function pre(){
} }
let rule = {}; let rule = {};
const VERSION = 'drpy1 3.9.41beta14 20230428'; const VERSION = 'drpy1 3.9.43beta1 20230607';
/** /**
* 1.影魔的jinjia2引擎不支持 {{fl}}对象直接渲染 (有能力解决的话尽量解决下支持对象直接渲染字符串转义,如果加了|safe就不转义)[影魔牛逼最新的文件发现这问题已经解决了] * 1.影魔的jinjia2引擎不支持 {{fl}}对象直接渲染 (有能力解决的话尽量解决下支持对象直接渲染字符串转义,如果加了|safe就不转义)[影魔牛逼最新的文件发现这问题已经解决了]
* Array.prototype.append = Array.prototype.push; 这种js执行后有毛病,for in 循环列表会把属性给打印出来 (这个大毛病需要重点排除一下) * Array.prototype.append = Array.prototype.push; 这种js执行后有毛病,for in 循环列表会把属性给打印出来 (这个大毛病需要重点排除一下)

View File

@ -41,7 +41,7 @@ function pre(){
let rule = {}; let rule = {};
let vercode = typeof(pdfl) ==='function'?'drpy2.1':'drpy2'; let vercode = typeof(pdfl) ==='function'?'drpy2.1':'drpy2';
const VERSION = vercode+' 3.9.41beta14 20230428'; const VERSION = vercode+' 3.9.43beta1 20230607';
/** /**
* 1.影魔的jinjia2引擎不支持 {{fl}}对象直接渲染 (有能力解决的话尽量解决下支持对象直接渲染字符串转义,如果加了|safe就不转义)[影魔牛逼最新的文件发现这问题已经解决了] * 1.影魔的jinjia2引擎不支持 {{fl}}对象直接渲染 (有能力解决的话尽量解决下支持对象直接渲染字符串转义,如果加了|safe就不转义)[影魔牛逼最新的文件发现这问题已经解决了]
* Array.prototype.append = Array.prototype.push; 这种js执行后有毛病,for in 循环列表会把属性给打印出来 (这个大毛病需要重点排除一下) * Array.prototype.append = Array.prototype.push; 这种js执行后有毛病,for in 循环列表会把属性给打印出来 (这个大毛病需要重点排除一下)

View File

@ -229,7 +229,10 @@ function request(url,obj){
}else{ }else{
new_obj = obj||{} new_obj = obj||{}
} }
if(!new_obj||!new_obj.headers||(!new_obj.headers['User-Agent']&&!new_obj.headers['user-agent'])){ if(!new_obj||!new_obj.headers){
new_obj.headers = {};
}
if(!new_obj.headers['User-Agent']&&!new_obj.headers['user-agent']){
new_obj.headers['User-Agent'] = MOBILE_UA; new_obj.headers['User-Agent'] = MOBILE_UA;
} }
// delete new_obj.headers['Referer']; // delete new_obj.headers['Referer'];