发布新版本,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.config import playerConfig
from utils.log import logger
from utils.encode import base64Encode,base64Decode,fetch,post,request,getCryptoJS,getPreJs,buildUrl,getHome,atob,btoa
from utils.encode import verifyCode,setDetail,join,urljoin2,parseText,requireCache,forceOrder,base64ToImage,encodeStr, decodeStr
from utils.encode import base64Encode, base64Decode, fetch, post, request, getCryptoJS, getPreJs, buildUrl, getHome, \
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.safePython import safePython
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 controllers.service import storage_service
def setItem(key, value):
lsg = storage_service()
if isinstance(key, PyJsString):
@ -34,6 +37,7 @@ def setItem(key,value):
value = parseText(str(value))
return lsg.setItem(key, value)
def getItem(key, value=''):
lsg = storage_service()
if isinstance(key, PyJsString):
@ -42,12 +46,14 @@ def getItem(key,value=''):
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)
@ -57,31 +63,38 @@ def encodeUrl(url):
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, 'base64Decode': base64Decode,
'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, 'UA': UA, 'IOS_UA': IOS_UA,
'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
}
# print(getCryptoJS())
class CMS:
@ -150,6 +163,32 @@ class CMS:
self.PlayParse = PlayParse
host = rule.get('host', '').rstrip('/')
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)
homeUrl = rule.get('homeUrl', '/')
url = rule.get('url', '')
@ -451,7 +490,6 @@ class CMS:
except Exception as e:
return f'{name}发生了错误:{e}'
def homeContent(self, fypage=1):
# yanaifei
# https://yanetflix.com/vodtype/dianying.html
@ -528,7 +566,9 @@ class CMS:
video_result = self.homeVideoContent(html, fypage)
except Exception as 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
if self.filter:
if isinstance(self.filter, dict):
@ -586,12 +626,14 @@ class CMS:
return self.blank()
jsp = jsoup(self.homeUrl)
pp = self.一级.split(';')
def getPP(p, pn, pp, ppn):
try:
ps = pp[ppn] if p[pn] == '*' and len(pp) > ppn else p[pn]
return ps
except Exception as e:
return ''
p0 = getPP(p, 0, pp, 0)
is_json = str(p0).startswith('json:')
if is_json:
@ -628,7 +670,8 @@ class CMS:
desc = pdfh(item2, p4)
except:
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)
if len(p) > 6 and p[6]:
content = pdfh(item2, p6)
@ -896,7 +939,8 @@ class CMS:
result['total'] = cnt
# print(result)
# 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 = {
'list': [{'vod_name': '无数据,防无限请求', 'vod_id': 'no_data', 'vod_remarks': '不要点,会崩的',
'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_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
else:
is_json = p.get('is_json', False) if isinstance(p, dict) else False # 二级里加is_json参数
@ -989,6 +1034,7 @@ class CMS:
vod_play_from = '$$$'
playFrom = []
init_flag = {'ctx': False}
def js_pre():
headers['Referer'] = getHome(url)
py_ctx.update({
@ -1004,6 +1050,7 @@ class CMS:
'jsp': jsp, 'jq': jsp, 'setDetail': setDetail, 'play_url': play_url
})
init_flag['ctx'] = True
if p.get('重定向') and str(p['重定向']).startswith('js:'):
if not init_flag['ctx']:
js_pre()
@ -1118,9 +1165,11 @@ class CMS:
# vodList = [pq(i).text()+'$'+pd(i,'a&&href') for i in vodList] # 拼接成 名称$链接
# pq(i).text()
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 \
[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:
vodList = [(pdfh(html, tab_ext) if tab_ext else tab_name) + '$' + play_url + i for i in
vodList] if is_json else \
@ -1140,7 +1189,8 @@ class CMS:
# print(vod_play_from)
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:
vod['vod_content'] = f'({self.id}){vod.get("vod_content", "")}'
@ -1219,7 +1269,8 @@ class CMS:
else:
vod = self.blank_vod()
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:
logger.info(f'{self.getName()}获取单个详情页{detailUrl}出错{e}')
if self.图片来源:
@ -1238,7 +1289,8 @@ class CMS:
"""
# print('进入二级')
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))) # 定义线程池来启动多线程执行此任务
obj_list = []
try:
@ -1256,7 +1308,8 @@ class CMS:
result = {
'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:
result = {
'list': []
@ -1293,6 +1346,7 @@ class CMS:
return ps
except:
return ''
if is_js:
headers['Referer'] = getHome(url)
py_ctx.update({
@ -1484,7 +1538,8 @@ class CMS:
if isinstance(lazy_url, str) and lazy_url.startswith('http'):
play_url = lazy_url
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)
# jscode = f'var input={play_url};{jscode}'
# print(jscode)
@ -1492,7 +1547,8 @@ class CMS:
py_ctx.update({
'input': play_url,
'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,
'jxs': jxs,
'getParse': self.d.getParse,
@ -1558,11 +1614,13 @@ class CMS:
logger.info(f'最终返回play_url:{play_url}')
return play_url
if __name__ == '__main__':
print(urljoin('https://api.web.360kan.com/v1/f',
'//0img.hitv.com/preview/sp_images/2022/01/28/202201281528074643023.jpg'))
# exit()
from utils import parser
# js_path = f'js/玩偶姐姐.js'
# js_path = f'js/555影视.js'
with open('../js/模板.js', encoding='utf-8') as f:

View File

@ -15,6 +15,7 @@ var rule = {
编码:'',//不填就默认utf-8
搜索编码:'',//不填则不编码默认都是按utf-8.可优先于全局编码属性.比如网页源码编码是gbk,这里可以指定utf-8搜索独立编码。多数情况这个属性不填或者填写gbk应对特殊的网站搜索
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是页数
url:'/fyclass/fypage.html[/fyclass/]',//网站的分类页面链接
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
- [X] 3.9.42beta22 后台管理增加两套通用在线播放器地址

View File

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

View File

@ -41,7 +41,7 @@ function pre(){
let rule = {};
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就不转义)[影魔牛逼最新的文件发现这问题已经解决了]
* Array.prototype.append = Array.prototype.push; 这种js执行后有毛病,for in 循环列表会把属性给打印出来 (这个大毛病需要重点排除一下)

View File

@ -229,7 +229,10 @@ function request(url,obj){
}else{
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;
}
// delete new_obj.headers['Referer'];