drpy源是一种用于TVBox、海阔视界、ZYPlayer等播放器的视频源格式,使用JavaScript编写,支持动态内容抓取和解析。本技能提供完整的drpy源创建指南,包含属性配置、模板继承、正则表达式编写、常见问题调试等。
以下是基础的drpy源模板:
javascript
var rule = {
// 影视|听书|漫画|小说
类型: '影视',
// 规则标题
title: '示例源',
// 网页的域名根
host: 'https://www.example.com',
// 网站的首页链接
homeUrl: '/latest/',
// 分类页面链接
url: '/fyclass/fypage.html',
// 搜索链接
searchUrl: '/vodsearch/紧箍咒/page/fypage.html',
// 是否启用全局搜索
searchable: 1,
// 是否启用快速搜索
quickSearch: 0,
// 是否启用筛选
filterable: 0,
// 请求头
headers: {
'User-Agent': 'MOBILE_UA',
},
// 请求超时(毫秒)
timeout: 5000,
// 是否需要调用免嗅lazy函数
play_parse: true,
// 静态分类名称
class_name: '电影&电视剧&动漫&综艺',
// 静态分类标识
class_url: '1&2&3&4',
}
第一步:获取网站源码
python
import requests
headers = {'User-Agent': 'Mozilla/5.0...'}
resp = requests.get('https://www.pitv.cc/', headers=headers)
html = resp.text
第二步:确认关键选择器
text
✓ .hl-vod-list - 列表容器存在
✓ .hl-list-item - 列表项存在
✓ a&&title - 标题属性存在
✓ a&&data-original - 图片属性存在
✗ .remarks - 状态class不存在(实际是.hl-pic-text span)
第三步:修正选择器
javascript
// 错误(参考代码)
推荐: '.hl-vod-list;li;a&&title;a&&data-original;.remarks&&Text;a&&href',
// 正确(实际HTML结构)
推荐: '.hl-vod-list;li;a&&title;a&&data-original;.hl-pic-text span&&Text;a&&href',
第四步:验证搜索功能
第五步:最终可用配置
javascript
var rule = {
title: '皮皮影视',
host: 'https://www.pitv.cc',
url: '/show/fyclassfyfilter/page/fypage/',
searchable: 0, // 搜索需要验证码,禁用
class_name: '剧集&电影&动漫',
class_url: '1&2&3',
推荐: '.hl-vod-list;li;a&&title;a&&data-original;.hl-pic-text span&&Text;a&&href',
一级: '.hl-vod-list&&.hl-list-item;a&&title;a&&data-original;.hl-pic-text span&&Text;a&&href',
二级: {
title: 'h1&&Text',
img: '.hl-lazy&&data-original',
tabs: '.hl-plays-from&&a',
lists: '.hl-plays-list:eq(#id)&&a',
},
}
属性类型说明示例类型string源类型:'影视'、'听书'、'漫画'、'小说''影视'titlestring规则标题,在播放器中显示的名称'鸭奈飞'hoststring网站域名根,包含http/https协议' https://yanetflix.com'homeUrlstring网站首页链接,用于获取分类和推荐'/latest/'urlstring分类页面链接模板'/vod/show/id/fyclass/page/fypage.html'searchUrlstring搜索链接模板'/vodsearch/紧箍咒/page/fypage.html'searchablenumber是否启用全局搜索1(启用)或0(禁用)quickSearchnumber是否启用快速搜索1(启用)或0(禁用)filterablenumber是否启用筛选1(启用)或0(禁用)
javascript
// 静态分类配置
class_name: '电影&电视剧&动漫&综艺',
class_url: '1&2&3&4',
// 动态分类获取(推荐)
class_parse: '#side-menu:lt(1) li;a&&Text;a&&href;com/(.*?)/',
// 格式:列表选择器;标题选择器;链接选择器;正则提取(可选)
javascript
// 请求头配置
headers: {
'User-Agent': 'MOBILE_UA',
'Cookie': 'searchneed=ok',
'Referer': 'https://www.example.com/'
},
// 超时设置(毫秒)
timeout: 5000,
// 动态获取host(优先级最高)
hostJs: async function () {
let {HOST} = this;
return HOST
},
// 预处理(初始化时执行一次)
预处理: async function () {
let {HOST} = this;
return HOST
},
drpy源的核心解析函数,用于获取不同页面的内容:
javascript
// 推荐内容获取
推荐: async function () {
let {input} = this;
// input为homeUrl的内容
return []
},
// 一级列表获取
一级: async function () {
let {input} = this;
// input为url模板填入后的链接
return []
},
// 二级详情获取
二级: async function () {
let {input} = this;
// input为一级返回的链接
return {}
},
// 搜索内容获取
搜索: async function () {
let {input} = this;
// input为searchUrl模板填入后的链接
return []
},
javascript
// 免嗅播放解析
play_parse: true,
// lazy函数处理播放地址
lazy: async function () {
let {input} = this;
return {
url: input,
parse: 0
}
},
// 辅助嗅探规则
sniffer: 1,
isVideo: "http((?!http).){26,}\\.(m3u8|mp4|flv|avi|mkv|wmv|mpg|mpeg|mov|ts|3gp|rm|rmvb|asf|m4a|mp3|wma)",
javascript
var rule = Object.assign(muban.mxpro, {
title: '鸭奈飞',
host: 'https://yanetflix.com',
url: '/index.php/vod/show/id/fyclass/page/fypage.html',
class_parse: `.navbar-items li:gt(1):lt(6);a&&Text;a&&href;.*/(.*?).html`,
});
javascript
var rule = {
title: 'cokemv',
模板: 'mxpro',
host: 'https://cokemv.me',
class_parse: `.navbar-items li:gt(1):lt(7);a&&Text;a&&href;/(\\d+).html`,
}
javascript
var rule = {
模板: '自动',
模板修改: $js.toString(() => {
Object.assign(muban.自动.二级, {
tab_text: 'div--small&&Text',
});
}),
title: '剧圈圈[自动]',
host: 'https://www.jqqzx.cc/',
url: '/vodshow/id/fyclass/page/fypage.html',
searchUrl: '/vodsearch**/page/fypage.html',
class_parse: '.navbar-items li:gt(2):lt(8);a&&Text;a&&href;.*/(.*?)\.html',
cate_exclude: '今日更新|热榜',
}
标准的视频源,支持电影、电视剧、动漫等内容。
用法与影视源一致,播放音频内容。
需要在 lazy 函数处理后返回 pics:// 协议:
javascript
lazy: async function () {
return "pics://图片链接1,图片链接2,图片链接3";
}
需要在 lazy 函数处理后返回 novel:// 协议:
javascript
lazy: async function () {
return 'novel://{"title":"章节名称","content":"章节内容"}';
}
在字符串属性(如 class_parse)中使用正则表达式时需要注意转义:
需求JavaScript正则drpy字符串写法数字/(\d+)/``(\\d+)任意字符/.*/``.*非贪婪匹配/(.*?)/``(.*?)多个分组/(\d+)-(\w+)/``(\\d+)-(\\w+)
javascript
proxy_rule: `js:
log(input);
input = [200,'text;plain','hello drpy']
`,
本地代理的 input 参数格式为三元素数组:
[status_code, content_type, data]
示例:
javascript
// 返回M3U8文件
input = [200,'application/vnd.apple.mpegurl', m3u8_content];
// 返回文本
input = [200,'text/plain', 'hello world'];
host 是否正确timeout 值(默认5000毫秒)log() 函数调试输出play_parse 设置lazy 函数返回正确格式sniffer 规则是否匹配视频链接class_parse 格式正确bash
# 安装uglify-js
npm install uglify-js -g
# 压缩JS文件
uglifyjs source.js -o source.min.js
where uglifyjsC:\Users\username\AppData\Roaming\npm\uglifyjs.cmd$FileName$ -o $FileNameWithoutExtension$.min.js$FileDir$log() 函数输出调试信息javascript
// 加密
RSA.encode(data, key, option);
// 解密
RSA.decode(data, key, option);
javascript
// 线路顺序
tab_order: ['lzm3u8', 'wjm3u8', '1080zyk'],
// 线路名替换
tab_rename: {
'lzm3u8': '量子资源',
'1080zyk': '1080看',
},
// 移除线路
tab_remove: ['tkm3u8'],
javascript
// 图片替换
图片替换: 'https://old-domain.com/=>https://new-domain.com/',
// 图片来源(添加referer)
图片来源: '@Referer=http://www.example.com@User-Agent=custom-ua',
在drpy源的二级详情或其他交互页面中,可以通过返回 action 对象来定义按钮行为:
javascript
二级: async function () {
return {
// 视频详情信息
vod_name: "影片名称",
vod_play_from: "播放来源",
vod_play_url: "第1集$播放地址",
// Action配置
action: {
button: 2, // 按钮类型:0-关闭, 1-取消, 2-确定和取消, 3-确定/取消/重置, 4-确定/取消/重置/预览
// 其他action属性...
},
};
},
值按钮组合适用场景0关闭按钮只提供关闭功能1取消按钮简单确认场景2确定和取消需要用户确认的操作3确定、取消、重置表单或设置页面4确定、取消、重置、预览复杂的编辑页面
除了按钮,action还可以包含其他指令:
javascript
action: {
button: 2,
message: "操作提示信息",
redirect: "目标URL",
// 其他自定义属性
},
drpy源可以通过压缩减少文件大小:
bash
# 安装uglify-js
npm install uglify-js -g
# 压缩JS文件
uglifyjs source.js -o source.min.js
# 推荐配置
uglifyjs source.js -o source.min.js -c -m --comments '/@license|@preserve/'
where uglifyjsC:\Users\username\AppData\Roaming\npm\uglifyjs.cmd$FileName$ -o $FileNameWithoutExtension$.min.js$FileDir$详细格式化指南见: formatting.md
症状:分类能显示,但点击后列表为空
原因:参考代码的选择器与实际HTML不符
排查方法:
python
import requests
from bs4 import BeautifulSoup
headers = {'User-Agent': 'Mozilla/5.0...'}
html = requests.get('https://example.com/', headers=headers).text
soup = BeautifulSoup(html, 'html.parser')
# 检查选择器是否存在
print('hl-vod-list:', bool(soup.find(class_='hl-vod-list')))
print('hl-list-item:', bool(soup.find(class_='hl-list-item')))
print('remarks:', bool(soup.find(class_='remarks'))) # 可能不存在
# 查找实际的class名
for elem in soup.find_all(class_=True):
if 'pic' in str(elem.get('class')) or 'text' in str(elem.get('class')):
print(elem.name, elem.get('class'))
解决方案:
javascript
// 错误
推荐: '.hl-vod-list;li;a&&title;a&&data-original;.remarks&&Text;a&&href',
// 正确(根据实际HTML调整)
推荐: '.hl-vod-list;li;a&&title;a&&data-original;.hl-pic-text span&&Text;a&&href',
症状:搜索返回空结果或报错
排查方法:
python
# 测试搜索URL
search_resp = requests.get('https://example.com/search/关键词/', headers=headers)
print('状态码:', search_resp.status_code)
print('是否包含验证码:', '验证码' in search_resp.text)
print('是否包含结果:', 'hl-vod-list' in search_resp.text)
常见情况:
searchable: 0 禁用搜索症状:能进入详情页,但无播放列表
排查方法:
python
# 获取详情页HTML
detail_html = requests.get('https://example.com/vod/123/', headers=headers).text
# 检查关键元素
print('h1:', 'h1' in detail_html)
print('hl-plays-list:', 'hl-plays-list' in detail_html)
print('hl-plays-from:', 'hl-plays-from' in detail_html)
解决方案:
javascript
// 根据实际HTML调整二级选择器
二级: {
title: 'h1&&Text', // 使用h1而不是.hl-dc-title
img: '.hl-lazy&&data-original',
tabs: '.hl-plays-from&&a', // 播放源
lists: '.hl-plays-list:eq(#id)&&a', // 剧集列表
}
症状:分类点击后跳转错误页面
排查方法:
python
# 测试URL模板
# 参考代码: /show/fyclassfyfilter/page/fypage/
# 实际测试
for cls in ['1', '2', '3']:
url = f'https://example.com/show/{cls}--------/page/1/'
resp = requests.get(url, headers=headers)
print(f'{url} -> {resp.status_code}')
解决方案:
javascript
// 确认URL格式
url: '/show/fyclassfyfilter/page/fypage/', // fyclass和fyfilter连在一起
// 或
url: '/type/fyclass/', // 简单的分类格式
javascript
推荐: `js:
let html = request(input);
log('首页HTML长度:', html.length);
log('是否包含视频列表:', html.includes('hl-vod-list'));
let items = pdfa(html, '.hl-vod-list li');
log('提取到视频数量:', items.length);
// 继续解析...
`,
javascript
// 先测试基础功能
var rule = {
title: '测试源',
host: 'https://example.com',
url: '/type/fyclass/',
class_name: '分类1&分类2',
class_url: '1&2',
推荐: 'a;a&&Text;;;a&&href', // 只取标题和链接
一级: 'a;a&&Text;;;a&&href',
二级: '*',
lazy: ''
};
任务参考文档新建一个drpy源基础模板了解所有属性含义属性详解使用模板继承模板继承编写解析函数解析函数调试源问题问题排查压缩源代码代码格式化分析网站结构analyze_site.py
核心原则:
提示:创建drpy源时,建议先使用简单的模板测试基础功能,再逐步添加高级功能。使用模板继承可以大大简化开发过程。