Jable.tv

https://jable.tv/#xh

分享者: xiaohan231 (515)发布时间: 2024/09/11

修改:1、优化页面样式;by:xiaohan231-2024/08/25

修改:1、优化长按倍速播放功能;by:xiaohan231-2024/08/24

修改:1、优化播放器样式;2、选择播放倍速后,点击屏幕不再恢复成正常;3、添加长按2倍速播放功能,想要设置成其他的可以在内容规则根据注释修改;by:xiaohan231-2024/08/21

修改:1、调用Plyr插件搭建网页播放器;2、设置播放器默认比例为16/9,以防止加载时播放器高度变动;3、优化播放器样式;by:xiaohan231-2024/08/20

修改:1、增加收藏关键词;2、视频不再采用第三方解析,改为调用原生播放器;3、添加视频封面;by:xiaohan231-2024/08/18

修改:1、优化女优信息获取;2、优化内容规则;by:xiaohan231-2024/08/17

修改:1、增加源站更新切换;2、优化分类获取;3、更换视频解析接口;by:xiaohan231-2024/08/16

by:xiaohan231-2024/08/15
二维码导入
{
    "articleStyle": 1,
    "concurrentRate": "20\/10000",
    "contentBlacklist": "",
    "customOrder": 19,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "<js>\nheaders={\n    \"User-Agent\": \"Mozilla\/5.0 (Linux; Android 10; K) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/127.0.0.0 Mobile Safari\/537.36 EdgA\/127.0.0.0\",\n    \"Referer\": String(source.getKey()).replace(\/(.*\\\/\\\/[a-z0-9.-]+).*\/, '$1')\n}\nJSON.stringify(headers);\n<\/js>",
    "injectJs": "",
    "jsLib": "function get(tag,num) {\n    sort = ['post_date_and_popularity','post_date','video_viewed','most_favourited'];\n    sort1 = ['','post_date_and_popularity','post_date','video_viewed','most_favourited'];\n    var e = eval(tag + '[' + num + ']');\n    return e;\n}\nfunction Get(e) {\n    const { java, source, cookie, cache } = this;\n    var get = JSON.parse(source.getLoginHeader());\n    return get[e];\n}\nfunction Map(e) {\n    const { java, source, cookie, cache } = this;\n    var infomap = source.getLoginInfoMap();\n    var map = (infomap !== null && infomap.get(e)) ? infomap.get(e) : '';\n    return String(map);\n}",
    "lastUpdateTime": 0,
    "loadWithBaseUrl": true,
    "loginCheckJs": "",
    "loginUi": "[\n  { name: \"  查看当前  \", type: \"button\", action: \"look(0)\" },\n  { name: \"   查看历史   \", type: \"button\", action: \"look(1)\" },\n  { name: \"  恢复默认  \", type: \"button\", action: \"test(0)\" },\n\n  {\n    name: \"            💡   源   站   更   新   💡            \",\n    type: \"button\",\n    action: \"update()\"\n  },\n\n  { name: \"                      ༺ˇ»`ʚ  点击切换源站  ɞ´«ˇ༻                    \", type: \"button\" },\n  { name: \"       ①国际网址✈️       \", type: \"button\", action: \"$(1)\"},\n  { name: \"       ②国内网址🐰       \", type: \"button\", action: \"$(2)\"},\n\n  { name: \"                      ༺ˇ»`ʚ  点击切换分类  ɞ´«ˇ༻                    \", type: \"button\" },\n  { name: \"           主题标签           \", type: \"button\", action: \"o(0)\" },\n  { name: \"           女优一览           \", type: \"button\", action: \"o(1)\" },\n\n  { name: \"                      ༺ˇ»`ʚ  列表影片排序  ɞ´«ˇ༻                    \", type: \"button\" },\n  { name: \" 近 期   \", type: \"button\", action: \"q(0)\" },\n  { name: \" 更 新   \", type: \"button\", action: \"q(1)\" },\n  { name: \" 观 看   \", type: \"button\", action: \"q(2)\" },\n  { name: \" 收 藏 \", type: \"button\", action: \"q(3)\" },\n\n  { name: \"                      ༺ˇ»`ʚ  搜索影片排序  ɞ´«ˇ༻                    \", type: \"button\" },\n  { name: \"  最高相关  \", type: \"button\", action: \"r(0)\" },\n  { name: \"   近期最佳   \", type: \"button\", action: \"r(1)\" },\n  { name: \"  最近更新  \", type: \"button\", action: \"r(2)\" },\n  { name: \"  最多观看  \", type: \"button\", action: \"r(3)\" },\n  { name: \"   最高收藏   \", type: \"button\", action: \"r(4)\" },\n  { name: \"                    \", type: \"button\" },\n\n  { name: \"                      ༺ˇ»`ʚ  分类女优排序  ɞ´«ˇ༻                    \", type: \"button\" },\n  { name: \" 热 度   \", type: \"button\", action: \"p(0)\" },\n  { name: \" 名 字   \", type: \"button\", action: \"p(1)\" },\n  { name: \" 更 新   \", type: \"button\", action: \"p(2)\" },\n  { name: \" 数 量 \", type: \"button\", action: \"p(3)\" },\n\n  { name: \"                      ༺ˇ»`ʚ  女优加载页数  ɞ´«ˇ༻                    \", type: \"button\", action: \"login('【加载页数】' + n(2) + '填写数字或范围,如:15或10-20')\" },\n  { name: \"页数:\", type: \"text\" },\n\n  { name: \"                      ༺ˇ»`ʚ  填写收藏词条  ɞ´«ˇ༻                    \", type: \"button\", action: \"login('【收藏词条】' + n(2) + '填写搜索关键词\\\\n多个关键词用英文逗号”,“隔开')\" },\n  { name: \"收藏:\", type: \"text\" },\n\n  {\n    name: \"            💡   源   站   打   印   💡            \",\n    type: \"button\",\n    action: \"test()\"\n  }\n]",
    "loginUrl": "var fburl = 'https:\/\/alldayj.com';\noriginal = {\n    'o': 0,\n    'p': 0,\n    'q': 0,\n    'r': 0,\n    'url': 'https:\/\/jable.tv',\n    'urls': [\n        'https:\/\/jable.tv',\n        'https:\/\/jable.tv'\n    ]\n};\ntry {\n    $$$ = JSON.parse(source.getLoginHeader());\n    if ($$$ == null) {\n        error;\n    } else {\n        '';\n    };\n} catch (e) {\n    $$$ = original;\n    put($$$);\n}\nx = '⓪①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚';\nvar Headers = String(cache.get(java.md5Encode16(Get('url') + \"headers\")));\nvar Option = {\n    \"method\": \"GET\",\n    \"headers\": Headers\n};\nfunction test(e) {\n    if (e == undefined) {\n        return java.log('\\n' + JSON.stringify($$$['urls'], null, '\\t')) + login('【源站输出提示】' + n(2) + '源站已打印完毕,请到日志查看');\n    }\n    if (e == 0) {\n        login('【初始化提示】' + n(2) + '已恢复默认设置');\n        return put(original);\n    }\n    date1 = new Date().getTime();\n    html = java.ajax($$$.urls[e]);\n    if(html.includes('no-js')){\n        cookie.removeCookie(Get('url'));\n        java.startBrowserAwait($$$.urls[e],\"验证\").body();\n        date1 = new Date().getTime();\n        html = java.ajax($$$.urls[e]);\n    }\n    date2 = new Date().getTime();\n    t = date2 - date1;\n    time = t \/ 1000 + 's';\n    c = String(html).indexOf('新作');\n    logTime = '【' + name(e) + '】\\n┋┋\\n' + '解析时间:' + time;\n    if (c == -1 || t > 5000) {\n        return login('【访问失败提示】' + n(2) + '┏┅━┅━┅━┅━┅━┅━┅━┅━┅┓\\n┋┋\\n' + logTime + '\\n┋┋\\n♣️源站已失效(可能被墙)♣️\\n┋┋\\n请更新网址\/切换源站\/切换网络环境\\n┋┋' + '\\n┗┅━┅━┅━┅━┅━┅━┅━┅━┅┛');\n    } else if (t < 1000) {\n        return login('【网络环境优良】' + n(2) + '┏┅━┅━┅━┅━┅━┅━┅━┅━┅┓\\n┋┋\\n' + logTime + '\\n┋┋\\n❤️延迟低,推荐使用此站❤️\\n┋┋\\n网络环境优良,请继续保持状态\\n┋┋' + '\\n┗┅━┅━┅━┅━┅━┅━┅━┅━┅┛');\n    } else if (t >= 1000 && t < 2000) {\n        return login('【网络环境一般】' + n(2) + '┏┅━┅━┅━┅━┅━┅━┅━┅━┅┓\\n┋┋\\n' + logTime + '\\n┋┋\\n♦️延迟一般,勉强可使用♦️\\n┋┋\\n请切换其他源站或切换网络环境\\n┋┋' + '\\n┗┅━┅━┅━┅━┅━┅━┅━┅━┅┛');\n    } else if (t >= 2000 && t < 5000) {\n        return login('【网络环境堪忧】' + n(2) + '┏┅━┅━┅━┅━┅━┅━┅━┅━┅┓\\n┋┋\\n' + logTime + '\\n┋┋\\n♠延迟过高,不建议使用♠\\n┋┋\\n请切换其他源站或切换网络环境\\n┋┋' + '\\n┗┅━┅━┅━┅━┅━┅━┅━┅━┅┛');\n    }\n}\nfunction put(data) {\n    return source.putLoginHeader(JSON.stringify(data, null, '\\t'));\n}\nfunction update() {\n    $$$['urls'].splice(original['urls'].length);\n    time = new Date().getTime();\n    html = java.webViewGetOverrideUrl(null, fburl + '?t=' + time, null, '');\n    J = org.jsoup.Jsoup.parse(html);\n    u = J.select('.col-md-8 a');\n    for (i in u) {\n        host = String(u[i].attr('href'));\n        if (String($$$['urls']).indexOf(host) === -1) {\n            java.log('\\n✅已添加源站:\\n' + host);\n            $$$['urls'].push(host);\n            put($$$);\n        }\n    }\n    return login('【源站更新提示】' + n(2) + '源站更新完毕,请到日志查看');\n}\nfunction name(e) {\n    if (e == undefined) {\n        e = 0;\n    }\n    return x[e] + $$$.urls[e];\n}\nfunction login(e) {\n    if (e == undefined) {\n        return;\n    }\n    java.longToast(e);\n}\nfunction n(e) {\n    n = '\\n';\n    for (m = 1; m < e; m++) {\n        n = n + '\\n';\n    }\n    return n;\n}\nfunction k(e) {\n    k = ' ';\n    for (q = 1; q < e; q++) {\n        k = k + ' ';\n    }\n    return k;\n}\nfunction l(e) {\n    l = '';\n    for (o = 1; o < e; o++) {\n        l = l + '';\n    }\n    return l;\n}\nfunction look(e) {\n    if (e == 0) {\n        return login('【查看当前源站】\\n\\n┏┅━┅━┅━┅━┅━┅━┅━┅━┅┓\\n┋┋' + ('\\n ' + '📌' + name($$$.ci0)) + '\\n┋┋' + ('\\n' + '🗳订阅分类:' + typeO($$$.o)) + '\\n┋┋' + ('\\n' + '👩‍🎤女优排序:' + typeP($$$.p)) + '\\n┋┋' + ('\\n' + '📚分类排序:' + typeQ($$$.q)) + '\\n┋┋' + ('\\n' + '📚搜索排序:' + typeR($$$.r)) + '\\n┋┋' + '\\n┗┅━┅━┅━┅━┅━┅━┅━┅━┅┛');\n    } else {\n        return login('【查看历史接口】\\n\\n┏┅━┅━┅━┅━┅━┅━┅━┅━┅┓\\n┋┋' + ('\\n ci1:' + name($$$.ci1)) + '\\n┋┋' + ('\\n ci2:' + name($$$.ci2)) + '\\n┋┋' + ('\\n ci3:' + name($$$.ci3)) + '\\n┋┋' + '\\n┗┅━┅━┅━┅━┅━┅━┅━┅━┅┛');\n    }\n}\nfunction $(e) {\n    if (e == undefined) {\n        e = result['序号:'];\n        e = e > 0 ? e : '0';\n    }\n    if (\/^ci[123]$\/.test(e)) {\n        eval('i=$$$.' + e);\n    }\n    if (\/\\D|^$\/.test(e) || e < 0 || e >= $$$['urls'].length) {\n        return login('【源站错误提示】' + n(2) + '已选择的源站无效,请重新选择');\n    }\n    $$$['url'] = $$$['urls'][e];\n    $$$['ci3'] = $$$['ci2'];\n    $$$['ci2'] = $$$['ci1'];\n    $$$['ci1'] = $$$['ci0'];\n    $$$['ci0'] = e;\n    put($$$);\n    test(e);\n}\nO = ['主题标签','全部女优'];\nfunction typeO(e) {\n    if (e == undefined) {\n        e = 0;\n    }\n    return O[e];\n}\nfunction o(e) {\n    if (o == undefined) {\n        o = result.o;\n    }\n    if (e == $$$.o) {\n        return login('【分类切换提示】' + n(2) + '已经选择此分类,无需更换');\n    }\n    login('【分类切换提示】' + n(2) + '已经切换到[' + typeO(e) + ']分类,请刷新分类');\n    $$$.o = e;\n    return put($$$);\n}\nP = ['热度优先','名字排序','最近更新','影片数量'];\nfunction typeP(e) {\n    if (e == undefined) {\n        e = 0;\n    }\n    return P[e];\n}\nfunction p(e) {\n    if (p == undefined) {\n        p = result.p;\n    }\n    if (e == $$$.p) {\n        return login('【女优排序提示】' + n(2) + '已经选择此排序,无需更换');\n    }\n    login('【女优排序提示】' + n(2) + '已经切换到[' + typeP(e) + ']排序,请刷新分类');\n    $$$.p = e;\n    return put($$$);\n}\nQ = ['近期最佳','最近更新','最多观看','最高收藏'];\nfunction typeQ(e) {\n    if (e == undefined) {\n        e = 0;\n    }\n    return Q[e];\n}\nfunction q(e) {\n    if (q == undefined) {\n        q = result.q;\n    }\n    if (e == $$$.q) {\n        return login('【分类影片排序】' + n(2) + '已经选择此排序,无需更换');\n    }\n    login('【分类影片排序】' + n(2) + '已经切换到[' + typeQ(e) + ']排序');\n    $$$.q = e;\n    return put($$$);\n}\nR = ['最高相关','近期最佳','最近更新','最多观看','最高收藏'];\nfunction typeR(e) {\n    if (e == undefined) {\n        e = 0;\n    }\n    return R[e];\n}\nfunction r(e) {\n    if (r == undefined) {\n        r = result.r;\n    }\n    if (e == $$$.r) {\n        return login('【搜索影片排序】' + n(2) + '已经选择此排序,无需更换');\n    }\n    login('【搜索影片排序】' + n(2) + '已经切换到[' + typeR(e) + ']排序');\n    $$$.r = e;\n    return put($$$);\n}",
    "ruleArticles": ".mb-e-20",
    "ruleContent": "<js>\n\/\/获取集数\nvar n = 0;\nvar names = ['原版视频'];\nvar list = [];\nURL = baseUrl;\nlist.push(URL);\njishu = list.map(($, i)=>{\n    var value = '',name = '',bt = '',fm = '';\n    html = $ == baseUrl ? result : java.ajax($);\n    J = org.jsoup.Jsoup.parse(html);\n    name = names[i];\n    var Value = [];\n    url = html.match(\/hlsUrl\\s*=\\s*'(.*?)'\/)[1];\n    Value.push({src:url,size:'0'});\n    value = JSON.stringify(Value);\n    bt = J.select('h4')[0].text();\n    fm = J.select('video')[0].attr('poster');\n    return `<button onclick=\"jishu(this)\" value=${value} data-bt=\"${bt}\"  data-fm=\"${fm}\"><b>${name}<\/b><\/button>`;\n}).join('\\n');\n\nstyle = ' style=\"display:none;\"';\njishu = `<div class=\"jishu\" data-n=\"${n}\"${style}>\\n<p>🎥 视频版本:&lrm;<\/p>\\n<p>${jishu}<\/p>\\n<\/div>\\n`;\n\n\/\/返回json\nJSON.stringify({\n    jishu: jishu\n})\n<\/js>\n<!DOCTYPE html>\n<html lang=\"zh-Hans\">\n<head>\n<title><\/title>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no\">\n<link rel=\"stylesheet\" href=\"https:\/\/cdn.plyr.io\/3.6.12\/plyr.css\">\n<style>\n* {\n    z-index: 0;\n    margin: 0;\n    padding: 0;\n}\n\nbody {\n    margin: auto;\n    background: #ccc;\n    width: 100%;\n}\n\nbody>p:first-of-type {\n    width: 100%;\n    position: sticky;\n    top: 0px;\n    text-indent: 0px;\n    height: 16px;\n    font-size: 0.7rem;\n    border-radius: 0px 0px 0px 0px;\n    background: #000;\n    color: #fff;\n    white-space: nowrap;\n    overflow: auto;\n    z-index: 4;\n}\n\nvideo {\n    visibility: hidden;\n}\n\n.video-container {\n    position: relative;\n    min-height: 56.25vw;\n    z-index: 3;\n}\n\n#player {\n    position: relative;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n}\n\n:root {\n    --plyr-color-main: #00aaff;\/* 播放器主要颜色 *\/\n    --plyr-control-color: #fff;\/* 播放器控件图标颜色 *\/\n    --plyr-control-background: transparent;\/* 播放器控件背景颜色 *\/\n    --plyr-video-background: transparent;\/* 视频背景颜色 *\/\n    --plyr-range-fill-background: #0099ee;\/* 进度条已填充部分的颜色 *\/\n    --plyr-range-thumb-background: #fff;\/* 进度条滑块的颜色 *\/\n}\n\n.plyr__control--overlaid {\n    background: transparent;\n    border: 0;\n    border-radius: 100%;\n    color: #fff;\n    left: calc(50% - 30px);\n    top: calc(50% - 45px);\n    transform: none;\n    width: 60px;\n    height: 60px;\n    padding: 0;\n    z-index: 2;\n}\n\n.plyr__control--overlaid svg {\n    width: 50px;\n    height: 50px;\n    left: calc(50% - 25px);\n    top: calc(50% - 25px);\n    transform: none;\n    fill: #fff;\/* 大播放器控件图标颜色 *\/\n}\n\n.plyr--video .plyr__control.plyr__tab-focus,.plyr--video .plyr__control:hover,.plyr--video .plyr__control[aria-expanded=true] {\n    background: transparent;\/* 播放器控件悬停\/点击背景颜色 *\/\n    color: #00aaff;\/* 播放器控件悬停\/点击图标颜色 *\/\n}\n\n.plyr__controls .plyr__controls__item {\n    margin-left: auto;\n    margin: calc(var(--plyr-control-spacing,10px)\/4);\n}\n\n.plyr__time--duration {\n    display: inline-block!important;\n}\n\n.plyr__time+.plyr__time:before {\n    margin-right: 8px!important\n}\n\n@media (max-width: 640px) {\n    .plyr__captions {\n        margin-bottom:-8px\n    }\n\n    .plyr__progress__container {\n        margin-right: 5px\n    }\n\n    .plyr__time {\n        position: absolute;\n        bottom: 29px;\n    }\n\n    .plyr__time--current {\n        left: 108px\n    }\n\n    .plyr__time+.plyr__time:before {\n        content: \"\"!important\n    }\n\n    .plyr__time--duration {\n        right: 110px;\n    }\n\n    .plyr__volume {\n        width: auto;\n        max-width: 32px!important;\n        min-width: 32px!important\n    }\n\n    input[id^=plyr-volume-] {\n        display: none!important;\n    }\n\n    .plyr--airplay-supported [data-plyr=airplay],.plyr--captions-enabled [data-plyr=captions],.plyr--pip-supported [data-plyr=pip] {\n        display: none!important;\n    }\n}\n\n.all-info {\n    position: absolute;\n    background: #ccc;\/* 详情信息背景颜色 *\/\n    margin: auto;\n    width: 100%;\n    height: auto;\n}\n\n.all-info>div {\n    width: 100%;\n    margin: auto;\n}\n\n.all-info>p {\n    text-indent: 0px;\n}\n\n.all-info>div>p {\n    width: 90%;\n    margin: 5px 5%;\n    outline: none;\n    text-align: left;\n    word-wrap: break-word;\n}\n\ndetails {\n    width: 100%;\n    height: auto;\n    margin: auto;\n    padding: 0;\n    border-bottom: 0.5px solid #333;\n}\n\ndetails>img {\n    width: 100%;\n}\n\ndetails[open] {\n    border-bottom: none;\n}\n\nsummary {\n    width: 90%;\n    margin: 5px 3%;\n    outline: none;\n    line-height: 1.5;\n    text-align: left;\n    word-wrap: break-word;\n}\n\nsummary::-webkit-details-marker {\n    display: none;\n}\n\nbutton {\n    width: 29.5%;\n    margin: 1.25%;\n    padding: 5px;\n    outline: none;\n    border-radius: 8px;\n    font-size: 0.7rem;\n    text-overflow: ellipsis;\n    overflow: hidden;\n}\n\nbutton.active {\n    color: #166188;\n    position: sticky;\n    left: 0;\n    right: 0;\n}\n<\/style>\n<\/head>\n<body>\n<p>{{src.match(\/hlsUrl\\s*=\\s*'(.*?)'\/)[1]}}<\/p>\n<div class=\"video-container\">\n  <video id=\"player\" playsinline controls preload=\"auto\" poster=\"https:\/\/qyyuapi.com\/img\/noposter.png\">\n  <\/video>\n<\/div>\n<div class=\"all-info\">\n<details>\n  <summary>\n    <h3>{{@@h4.0@text}}<\/h3>\n  <\/summary>\n  <img src={{@@video@poster}}>\n<\/details>\n{{JSON.parse(result).jishu}}\n<div>\n    <p>📆 更新:{{@@.mr-3.0@text}}<\/p>\n    <p>🎥 播放:{{@@.mr-3.1@text##\\s}}<\/p>\n    <p>❤ 收藏:{{@@.count@text}}<\/p>\n    <p>👩‍🎤 女优:{{@@.rounded-circle@title}}<\/p>\n    <p>📦 主题:{{@@.tags.h6-md@text##•.*$}}<\/p>\n    <p>🔖 标签:{{@@.tags.h6-md@text##^.*•}}<\/p>\n<\/div>\n<\/div>\n\n<script src=\"https:\/\/cdn.plyr.io\/3.6.12\/plyr.js\"><\/script>\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/hls.js@latest\"><\/script>\n\n<script>\n\/\/ 选中标签\nfunction $(rule) {\n    return document.querySelectorAll(rule);\n}\n\n\/\/ 删除选中标签的class\nfunction omit(items) {\n    return Array.from(items, (item) => {\n        item.className = \"\";\n    });\n}\n\n\/\/ 选中标签的class增加active\nfunction active(items, index) {\n    items[index].className = \"active\";\n}\n\n\/\/ 播放器实例\nlet player = null;\n\n\/\/ 获取视频URL并更新视频源\nfunction geturl() {\n    let zyurl = $(\".jishu button.active\")[0].value;\n    let img = $('img')[0];\n    let fm = $(\".jishu button.active\")[0].dataset.fm;\n\n    \/\/ 更新视频封面\n    $(\".video-container\")[0].style.background = `#000 url('${fm}') no-repeat center center \/ cover`;\n\n    \/\/ 设置不同分辨率的视频源\n    let sources = JSON.parse(zyurl);\n\n    return { sources: sources };\n}\n\n\/\/ 初始化播放器\nfunction initializePlayer(sources) {\n    const video = $('video')[0];\n    const qualityOptions = sources.map(source => parseInt(source.size));\n\n    \/\/ 立即重新初始化 Plyr 实例\n    player = new Plyr(video, {\n        controls: [\n            'play-large',   \/\/ 大播放按钮\n            'rewind',       \/\/ 倒退\n            'play',         \/\/ 播放\n            'fast-forward', \/\/ 快进\n            'progress',     \/\/ 进度条\n            'current-time', \/\/ 当前时间\n            'duration',     \/\/ 总时长\n            'mute',         \/\/ 静音\n            'volume',       \/\/ 音量\n            'captions',     \/\/ 字幕\n            'settings',     \/\/ 设置\n            'pip',          \/\/ 画中画\n            'airplay',      \/\/ Airplay\n            'fullscreen'    \/\/ 全屏\n        ],\n        settings: ['quality', 'speed'],\n        quality: {\n            default: qualityOptions[0],\n            options: qualityOptions,\n            forced: true,\n            onChange: (newQuality) => {\n                changeVideoQuality(newQuality, sources);\n            }\n        },\n        fullscreen: {\n            enabled: true,\n            fallback: true,\n            iosNative: true,\n            container: null,\n        },\n        speed: {\n            selected: 1, \/\/ 设置默认播放倍数\n            options: [0.25, 0.5, 1, 1.5, 2],\n        },\n        i18n: {\n            restart: '重新开始',\n            rewind: '倒退 {seektime} 秒',\n            play: '播放',\n            pause: '暂停',\n            fastForward: '快进 {seektime} 秒',\n            seek: '进度',\n            seekLabel: '{currentTime} \/ {duration}',\n            played: '播放',\n            buffered: '缓冲',\n            currentTime: '当前时间',\n            duration: '持续时间',\n            volume: '音量',\n            mute: '静音',\n            unmute: '取消静音',\n            enableCaptions: '启用字幕',\n            disableCaptions: '禁用字幕',\n            enterFullscreen: '进入全屏',\n            exitFullscreen: '退出全屏',\n            frameTitle: '播放器',\n            captions: '字幕',\n            settings: '设置',\n            speed: '速度',\n            normal: '正常',\n            quality: '画质',\n            qualityLabel: {\n                0: '自动',\n            },\n            pip: '画中画',\n            loop: '循环',\n            start: '开始',\n            end: '结束',\n            all: '全部',\n            reset: '重置',\n            disabled: '禁用',\n            advertisement: '广告'\n        },\n        keyboard: {\n            focused: true,\n            global: true,\n        },\n        tooltips: {\n            controls: true,\n            seek: true\n        },\n        captions: {\n            active: true,\n            update: true,\n            language: 'auto',\n        },\n    });\n\n    player.on('ready', () => {\n        video.style.visibility = 'visible';\n\n        \/\/ 添加长按倍速播放功能\n        let longPressTimeout = null;\n        let initialSpeed = 1;\n        let isLongPress = false;\n        const controls = document.querySelector('.plyr__controls');\n        const overlaid = document.querySelector('.plyr__control--overlaid');\n\n        const startLongPress = (e) => {\n            e.stopPropagation();\n            initialSpeed = player.speed;\n            longPressTimeout = setTimeout(() => {\n                setTimeout(() => {\n                    controls.style.display = 'none';\n                    overlaid.style.display = 'none';\n                }, 1000);\n                isLongPress = true;\n                player.speed = 2; \/\/ 长按时设置2倍速播放\n            }, 500);\n        };\n\n        const endLongPress = (e) => {\n            e.stopPropagation();\n            clearTimeout(longPressTimeout);\n            if (isLongPress) {\n                player.speed = initialSpeed;\n                isLongPress = false;\n                setTimeout(() => {\n                    controls.style.display = 'flex';\n                    overlaid.style.display = 'flex';\n                }, 2000);\n            }\n        };\n\n        \/\/ 监听播放器区域的pointerdown和pointerup事件\n        const playerContainer = document.querySelector('.plyr__video-wrapper');\n\n        playerContainer.addEventListener('pointerdown', startLongPress, true);\n        playerContainer.addEventListener('pointerup', endLongPress, true);\n        playerContainer.addEventListener('pointerleave', endLongPress, true);\n\n        \/\/ 处理全屏模式下的特殊情况\n        document.addEventListener('fullscreenchange', () => {\n            if (!document.fullscreenElement) {\n                endLongPress();\n            }\n        });\n    });\n}\n\n\/\/ 切换视频质量的函数\nfunction changeVideoQuality(quality, sources) {\n    const video = $('video')[0];\n    const selectedSource = sources.find(source => source.size === quality.toString());\n    const currentTime = video.currentTime;\n    const wasPlaying = !video.paused;\n\n    if (wasPlaying) {\n        $(\".video-container\")[0].style.background = '#000';\n    }\n    $(\"body>p\")[0].innerText = selectedSource.src;\n\n    if (selectedSource) {\n        if (Hls.isSupported() && selectedSource.src.endsWith('.m3u8')) {\n            const hls = new Hls();\n            hls.loadSource(selectedSource.src);\n            hls.attachMedia(video);\n            hls.on(Hls.Events.MANIFEST_PARSED, () => {\n                video.currentTime = currentTime;\n                if (wasPlaying) {\n                    video.play();\n                }\n            });\n        } else {\n            video.pause();\n            video.src = selectedSource.src;\n            video.load();\n            video.currentTime = currentTime;\n            if (wasPlaying) {\n                video.play();\n            }\n        }\n    }\n}\n\n\/\/ 点击集数按钮时调用的函数\nfunction jishu(item) {\n    if (player && typeof player.destroy === 'function') {\n        player.destroy();\n        player = null;\n    }\n    omit($('.jishu button.active'));\n    item.className = \"active\";\n    const { sources } = geturl();\n    initializePlayer(sources);\n}\n\n\/\/ 页面加载时初始化播放器\n(() => {\n    let n = $(\".jishu\")[0].dataset.n;\n    active($('.jishu button'), n);\n    const { sources } = geturl();\n    initializePlayer(sources);\n})();\n<\/script>\n<\/body>\n<\/html>",
    "ruleDescription": "",
    "ruleImage": "img@data-src",
    "ruleLink": "a.0@href",
    "ruleNextPage": "page",
    "rulePubDate": "⌚️ {{@@.label@text}}    🎥 {{@@.sub-title@html}}\n@js:\nresult.replace(\/<p[\\s\\S]*?<\\\/svg>|<\\\/p>|\\n\/gm,'').replace(\/<svg[\\s\\S]*?<\\\/svg>\/m,'  ❤ ').replace(\/(\\d)\\s+(\\d)\/g,'$1$2')",
    "ruleTitle": ".title@text",
    "singleUrl": false,
    "sortUrl": "@js:\neval(String(source.loginUrl));\nvar exploreUrl = [];\nvar Sort = `{{get('sort',Get('q'))}}`;\nvar Sort1 = `{{get('sort1',Get('r'))}}`;\nfunction explore(e, f, g) {\n    if (g=='收藏') {\n        style = `${e}::@js:\\`${f}\\`\\n`;\n    } else if (g=='主题') {\n        style = `${e}::@js:\\`${f}?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=${Sort}&from={{page}}&_={{new Date().getTime()}}\\`\\n`;\n    } else if (g=='标签') {\n        style = `${e}::@js:\\`${f}?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=${Sort}&from={{page}}&_={{new Date().getTime()}}\\`\\n`;\n    } else {\/\/女优\n        style = `${e}::@js:\\`${f}?mode=async&function=get_block&block_id=list_videos_common_videos_list&sort_by=${Sort}&from={{page}}&_={{new Date().getTime()}}\\`\\n`;\n    }\n    return style;\n}\n\nsc = Map('收藏:');\nscs = sc !== '' ? sc.split(\",\") : [];\nif (scs.length > 0) {\n    scs.forEach((sc) => {\n        let scHref = `{{Get('url')}}\/search\/${sc}\/?mode=async&function=get_block&block_id=list_videos_videos_list_search_result&q=${sc}&sort_by=${Sort1}&from={{page}}&_={{new Date().getTime()}}`;\n        exploreUrl.push(explore(sc, scHref, '收藏'));\n    });\n}\n\nhtml = java.ajax(Get('url')+'\/categories\/');\nif(String(html).includes('no-js')){\n    cookie.removeCookie(Get('url'));\n    java.startBrowserAwait(Get('url'),'验证');\n}\n\nJ = org.jsoup.Jsoup.parse(html);\n\nif (Get('o') == 0) {\n    java.toast(\"正在获取主题标签数据,请稍后!\")\n    categories = J.select('.pb-e-lg-40 a');\n    for (i in categories) {\n        exploreUrl.push(explore(categories[i].select('h4').text()+'('+String(categories[i].select('span').text()).replace(\/(\\d+).*$\/, '$1')+')', `{{Get('url')}}${String(categories[i].attr('href')).replace(\/.*\\\/\\\/[a-z0-9.-]+\/, '')}`, '主题'));\n    }\n    tags = J.select('.gutter-20.pb-3 a');\n    for (i in tags) {\n        exploreUrl.push(explore(tags[i].text(), `{{Get('url')}}${String(tags[i].attr('href')).replace(\/.*\\\/\\\/[a-z0-9.-]+\/, '')}`, '标签'));\n    }\n}\n\nnsort = ['avg_videos_popularity','title','last_content_date','total_videos'];\nif (Get('o') == 1) {\n    java.toast(\"正在获取女优数据,请耐心等待!\");\n    Fpage = \/-\/.test(Map('页数:')) ? Map('页数:').match(\/(\\d+)\/g)[0] : '1';\n    Lpage = \/-\/.test(Map('页数:')) ? Map('页数:').match(\/(\\d+)\/g)[1] : (\/\\d+\/.test(Map('页数:')) ? Map('页数:') : '5');\n    var murl = [];\n    for (let i = Fpage; i <= Lpage; i++) {\n        murl.push(Get('url')+'\/models\/?mode=async&function=get_block&block_id=list_models_models_list&sort_by='+nsort[Get('p')]+'&from='+i+'&_='+(new Date().getTime())); \n    }\n    htmls = java.ajaxAll(murl);\n    for (let i = 0; i < htmls.length; i++) {\n        let models = org.jsoup.Jsoup.parse(htmls[i].body()).select('.horizontal-img-box');\n        models.forEach((model) => {\n            let modelName = model.select('.title').text();\n            let modelSpanText = model.select('span').text();\n            let modelVideosCount = String(modelSpanText).replace(\/(\\d+).*$\/, '$1');\n            let modelHref = `{{Get('url')}}${String(model.select('a').attr('href')).replace(\/.*\\\/\\\/[a-z0-9.-]+\/, '')}`;\n            exploreUrl.push(explore(`${modelName}(${modelVideosCount})`, modelHref, '女优'));\n        });\n    }\n}\n\n`变量搜索::@js:\\`{{Get('url')}}\/search\/{{v=source.getVariable();if(\/^\\s*$\/.test(v)||v==null)source.setVariable('秘密');source.getVariable()}}\/?mode=async&function=get_block&block_id=list_videos_videos_list_search_result&q=${source.getVariable()}&sort_by=${Sort1}&from={{page}}&_={{new Date().getTime()}}\\`\\n\n${exploreUrl.join('\\n')}`",
    "sourceComment": "修改:1、优化页面样式;by:xiaohan231-2024\/08\/25\n\n修改:1、优化长按倍速播放功能;by:xiaohan231-2024\/08\/24\n\n修改:1、优化播放器样式;2、选择播放倍速后,点击屏幕不再恢复成正常;3、添加长按2倍速播放功能,想要设置成其他的可以在内容规则根据注释修改;by:xiaohan231-2024\/08\/21\n\n修改:1、调用Plyr插件搭建网页播放器;2、设置播放器默认比例为16\/9,以防止加载时播放器高度变动;3、优化播放器样式;by:xiaohan231-2024\/08\/20\n\n修改:1、增加收藏关键词;2、视频不再采用第三方解析,改为调用原生播放器;3、添加视频封面;by:xiaohan231-2024\/08\/18\n\n修改:1、优化女优信息获取;2、优化内容规则;by:xiaohan231-2024\/08\/17\n\n修改:1、增加源站更新切换;2、优化分类获取;3、更换视频解析接口;by:xiaohan231-2024\/08\/16\n\nby:xiaohan231-2024\/08\/15",
    "sourceGroup": "🔭 其他,📽 视频",
    "sourceIcon": "https:\/\/krseoul.imgtbl.com\/i\/2024\/08\/17\/66bfb45e25be1.png",
    "sourceName": "Jable.tv",
    "sourceUrl": "https:\/\/jable.tv\/#xh",
    "style": ""
}
广告