diff --git a/lib/170av.json b/lib/170av.json new file mode 100644 index 0000000..51989ec --- /dev/null +++ b/lib/170av.json @@ -0,0 +1,86 @@ +{ +//永久地址:https://www.190av.cc/ +"规则名": "170AV", +"规则作者": "飞鱼", +"请求头参数": "PC_UA", +"网页编码格式": "UTF-8", +"图片是否需要代理": "0", +"是否开启获取首页数据": "1", +"首页推荐链接": "https://www.170av.cc/label/new.html", +"首页列表数组规则": "#app", +"首页片单列表数组规则": ".col-style", +"首页片单是否Jsoup写法": "1", +"首页片单标题": ".title&&Text", +"首页片单链接": "a&&href", +"首页片单图片": "img&&src", +"首页片单副标题": "'⏱️'+.likes&&Text+'🔥'+.views&&Text", +"首页片单链接加前缀": "https://www.170av.cc", +"首页片单链接加后缀": "", +"分类起始页码": "1", +"分类链接": "https://www.170av.cc{cateId}-{catePg}.html", +//https://iook1.cc/vodtype/1-2.html +//https://iook1.cc/label/new/page/1.html +"分类名称": "国产视频&亚洲情色&无码专区&韩国视频&欧美视频&偷拍自拍&中文字幕&三级伦理&卡通动漫&丝袜美腿&制服师生&强奸乱伦&人妻熟女&潮吹喷射&男同女同&变态另类&美女写真&人妖系列&巨乳肥臀&自淫系列&群交系列&口交颜射&东京热&一本道&加勒比&JAV高清&SM捆绑&VR性爱", +"分类名称替换词": "/vodtype/23&/vodtype/21&/vodtype/22&/vodtype/24&/vodtype/25&/vodtype/26&/vodtype/27&/vodtype/28&/vodtype/29&/vodtype/30&/vodtype/31&/vodtype/32&/vodtype/33&/vodtype/34&/vodtype/35&/vodtype/36&/vodtype/37&/vodtype/38&/vodtype/39&/vodtype/40&/vodtype/41&/vodtype/42&/vodtype/43&/vodtype/44&/vodtype/48&/vodtype/45&/vodtype/46&/vodtype/47", +"分类截取模式": "1", +"分类列表数组规则": "#app&&.col-style", +"分类片单是否Jsoup写法": "1", +"分类片单标题": ".title&&Text", +"分类片单链接": "a&&href", +"分类片单图片": "img&&src", +"分类片单副标题": "'🔥'+.views&&Text+'⏱️'+.likes&&Text", +"分类片单链接加前缀": "https://www.170av.cc", +"分类片单链接加后缀": "", +"搜索请求头参数": "User-Agent$手机", +"搜索链接": "https://www.170av.cc/vodsearch/{wd}----------{catePg}---.html", +"POST请求数据": "", +"搜索截取模式": "1", +"搜索列表数组规则": "#app&&.col-style", +"搜索片单是否Jsoup写法": "1", +"搜索片单图片": "img&&src", +"搜索片单标题": ".title&&Text", +"搜索片单链接": "a&&href", +"搜索片单副标题": "'⏱️'+.likes&&Text+'🔥'+.views&&Text", +"搜索片单链接加前缀": "https://www.170av.cc", +"搜索片单链接加后缀": "", +"链接是否直接播放": "1", +"直接播放链接加前缀": "", +"直接播放链接加后缀": "", +"直接播放直链视频请求头": "", + + + + +//下面是选集规则,直接播放的不用下面 +"线路列表数组规则":"", +"线路列表":"", +"线路标题":"", + +"选集标题链接是否Jsoup写法":"1", +"选集列表数组规则":"", +"播放列表数组规则":"", +"选集标题":"", +"选集链接":"", +"选集链接加前缀":"", +"选集链接加后缀":"", +"是否反转选集序列":"", + +"详情是否Jsoup写法":"1", +"类型详情":"", +"年代详情":"", +"地区详情":"", +"演员详情":"", +"简介详情":"", + + + + + + + + +"分析MacPlayer": "0", +"是否开启手动嗅探": "1", +"手动嗅探视频链接关键词": ".m3u8#.mp4", +"手动嗅探视频链接过滤词": "baidu.com" +} \ No newline at end of file diff --git a/lib/182.jar b/lib/182.jar new file mode 100644 index 0000000..2eec2fe Binary files /dev/null and b/lib/182.jar differ diff --git a/lib/1827140.jar b/lib/1827140.jar new file mode 100644 index 0000000..2eec2fe Binary files /dev/null and b/lib/1827140.jar differ diff --git a/lib/18XXX.json b/lib/18XXX.json new file mode 100644 index 0000000..3aeefad --- /dev/null +++ b/lib/18XXX.json @@ -0,0 +1,16 @@ +{ + "作者": "Aries", + "站名": "https://www.18xxx6.hair/cn/home/web/", + "请求头": "User-Agent$MOBILE_UA", + "编码": "UTF-8", + "主页url": "https://www.18xxx6.hair/cn/home/web/", + "首页": "120", + "起始页": "1", + "分类url": "https://www.18xxx6.hair/cn/home/web/index.php/vod/show/id/{cateId}/page/{catePg}.html;;z", + "分类": "绝美少女$20#激情口交$21#同性专区$22#人妖激情$23#重咸口味$24#国产专区$25#日韩专区$26#欧美专区$27#卡通动漫$28#三级伦理$29", + "数组": "", + "标题": "title=\"&&\"", + "图片": "data-original=\"&&\"", + "副标题": "✨+多看少撸管+✨", + "链接": "href=\"&&\"" +} diff --git a/lib/18av.json b/lib/18av.json new file mode 100644 index 0000000..433e5bc --- /dev/null +++ b/lib/18av.json @@ -0,0 +1,69 @@ +{ +//发布页https://mm18vc.com/ +//https://18av.mm-cg.com/ +//https://18av.mm-cg.com +"规则名": "18AV-XYQHiker", +"规则作者": "飞鱼", +"请求头参数": "PC_UA", +"网页编码格式": "UTF-8", +"图片是否需要代理": "0", +"是否开启获取首页数据": "1", +"首页推荐链接": "https://18av.mm-cg.com/zh/content_news/all/1.html", +"首页列表数组规则": ".posts", +"首页片单列表数组规则": ".post", +"首页片单是否Jsoup写法": "1", +"首页片单标题": "h3&&Text", +"首页片单链接": "a&&href", +"首页片单图片": "img&&src", +"首页片单副标题": ".meta&&Text", +"首页片单链接加前缀": "", +"首页片单链接加后缀": "", +"分类起始页码": "1", +//"分类链接": "https://XXXXX.com/vodtype/{cateId}-{catePg}/", + //{cateId}分类id + //{area}地区 + //{by}排序 + //{class}剧情 + //{lang}语言 + //{catePg}翻页序列号 + //{year}日期 +"分类链接": "https://18av.mm-cg.com/zh/{cateId}/all/{catePg}.html", +"分类名称": "中文字幕&无码&动漫&自拍&", +"分类名称替换词": "chinese_list&uncensored_list&animation_list&dt_list&", +"分类截取模式": "1", +"分类列表数组规则": ".posts&&.post", +"分类片单是否Jsoup写法": "1", +"分类片单标题": "h3&&Text", +"分类片单链接": "a&&href", +"分类片单图片": "img&&src", +"分类片单副标题": ".meta&&Text", +"分类片单链接加前缀": "", +"分类片单链接加后缀": "", +"搜索请求头参数": "User-Agent$PC_UA", +"搜索链接": "https://18av.mm-cg.com/zh/searchform_search/all/index.html?search_keyword={wd}&search_type=fc&op=search", +"POST请求数据": "", +"搜索截取模式": "1", +"搜索列表数组规则": ".posts&&.post", +"搜索片单是否Jsoup写法": "1", +"搜索片单图片": "img&&src", +"搜索片单标题": "h3&&Text", +"搜索片单链接": "a&&href", +"搜索片单副标题": ".meta&&Text", +"搜索片单链接加前缀": "", +"搜索片单链接加后缀": "", +"链接是否直接播放": "1", +"直接播放链接加前缀": "", +"直接播放链接加后缀": "", +"直接播放直链视频请求头": "", + + + +"分析MacPlayer": "0", +"是否开启手动嗅探": "1", +"手动嗅探视频链接关键词": ".m3u8", +"手动嗅探视频链接过滤词": "baidu.com", + + +"筛选数据":{} + +} \ No newline at end of file diff --git a/lib/18j.json b/lib/18j.json new file mode 100644 index 0000000..cefe11b --- /dev/null +++ b/lib/18j.json @@ -0,0 +1,19 @@ +{ + "作者": "Aries", + "站名": "", + "请求头": "User-Agent$MOBILE_UA", + "编码": "UTF-8", + "主页url": "https://18jtv.com/", + "首页": "120", + "起始页": "1", + "分类url": "https://18jtv.com/t/{cateId}-{catePg}/;;z", + "分类": "国产$1#日韩$2#欧美$3#伦理$4动漫$16", + "二次截取": "", + "数组": "class=\"&&", + "标题": "title=\"&&\"", + "图片": "data-original=\"&&\"", + "副标题": "🌹+alt=\"&&\"", + "链接": "href=\"&&\"", + "线路二次截取": "play-title\"&&/div>", + "跳转播放链接": "var player_*\"url\":\"&&\"" +} diff --git a/lib/18jav.json b/lib/18jav.json new file mode 100644 index 0000000..c406b2a --- /dev/null +++ b/lib/18jav.json @@ -0,0 +1,153 @@ +{ + //永久地址发布页https://gyn.xxkk7.com/323/ + "规则名": "18jav-XYQHiker", + "规则作者": "飞鱼", + "请求头参数":"手机", + "网页编码格式":"UTF-8", + "图片是否需要代理":"0", + "是否开启获取首页数据":"1", + //首页推荐数据获取链接 + "首页推荐链接": "https://18jav.tv/label/new/", + //首页推荐列表数组截取。 + "首页列表数组规则": "body", + //首页推荐片单列表数组定位。 + "首页片单列表数组规则": ".gap-5&&.group", + //首页推荐片单信息jsoup与正则截取写法切换,只作用于html网页,1为jsoup写法(默认),0为正则截取写法 + "首页片单是否Jsoup写法":"1", + //下面这六个首页数据如果不填将调用分类那截取的配置(片单写法需一致且取值也得一致)。 + //首页片单标题 + "首页片单标题": ".text-nord4&&Text", + //首页推荐片单链接 + "首页片单链接": "a&&href", + //首页推荐片单图片,支持自定义图片链接 + "首页片单图片": "img&&data-src", + //首页推荐片单副标题 + "首页片单副标题":".absolute,1&&Text+.absolute,0&&Text", + //首页推荐片单链接补前缀 + "首页片单链接加前缀": "https://18jav.tv", + //首页推荐片单链接补后缀 + "首页片单链接加后缀": "", + "分类起始页码": "1", + //"分类链接": "https://www.l0l.tv/index.php/vod/show/id/{cateId}/page/{catePg}.html", + "分类链接": "https://18jav.tv/{cateId}&function=get_block&from={catePg}", + "分类名称": "最新&热门&主题分类", + "分类名称替换词": "latest-updates?sort_by=release_at&hot?sort_by=views&categories/chinese-subtitle?sort_by=release_at&", + //"筛选数据":{}, + "分类截取模式": "1", + "分类列表数组规则": "#list_videos_common_videos_list&&.col-6.col-sm-4.col-lg-3", + "分类片单是否Jsoup写法":"1", + "分类片单标题": ".title&&Text", + "分类片单链接": "a&&href",//替换规则 + "分类片单图片": "img&&data-src", + "分类片单副标题":".label&&Text", + "分类片单链接加前缀": "https://18jav.tv", + "分类片单链接加后缀": "", + "搜索请求头参数":"User-Agent$PC_UA", + + "搜索链接": "https://18jav.tv/search/{wd}/", + "POST请求数据":"0", + "搜索截取模式": "1", + "搜索列表数组规则": "#list_videos_videos_list_search_result&&.col-6.col-sm-4.col-lg-3", + "搜索片单是否Jsoup写法":"1", + "搜索片单图片": "img&&data-src", + "搜索片单标题": ".title&&Text", + "搜索片单链接": "a&&href", + "搜索片单副标题":".label&&Text", + "搜索片单链接加前缀": "", + "搜索片单链接加后缀": "", + //-------- + "链接是否直接播放": "1", +"直接播放链接加前缀": "", +"直接播放链接加后缀": "", +"直接播放直链视频请求头": "", +//------- + "详情是否Jsoup写法":"0", + "类型详情": ".text-muted&&a&&Text", + "年代详情": "", + "地区详情": "", + "演员详情": ":&&

", + "简介详情": "概要:&&

", + "线路列表数组规则": ".stui-pannel__head&&h3", + "线路标题": ".title&&Text", + "播放列表数组规则": ".stui-content__playlist", + "选集列表数组规则": "li", + "选集标题链接是否Jsoup写法":"1", + "选集标题": "a&&Text", + "选集链接": "a&&href", + "是否反转选集序列": "0", + "选集链接加前缀": "https://gbyool.yjyh5.makeup", + "选集链接加后缀": "", + "分析MacPlayer":"0", + "是否开启手动嗅探":"1", + "手动嗅探视频链接关键词":".m3u8#.mp4", + "手动嗅探视频链接过滤词":".html#=http", + + "筛选数据":{ +"categories/chinese-subtitle?sort_by=release_at":[ + {"key":"cateId","name":"分类","value":[ +{"v":"categories/chinese-subtitle?sort_by=release_at","n":"中文字幕"}, +{"v":"categories/roleplay?sort_by=release_at","n":"角色劇情"}, +{"v":"categories/uncensored?sort_by=release_at","n":"無碼解放"}, +{"v":"categories/taiwan-av?sort_by=release_at","n":"台灣AV"}, +{"v":"categories/uniform?sort_by=release_at","n":"制服誘惑"}, +{"v":"categories/sex-only?sort_by=release_at","n":"直接開啪"}, +{"v":"categories/pantyhose?sort_by=release_at","n":"絲襪"}, +{"v":"categories/groupsex?sort_by=release_at","n":"多P群交"}, +{"v":"categories/bdsm?sort_by=release_at","n":"主奴調教"}, +{"v":"categories/rape?sort_by=release_at","n":"強姦"}, +{"v":"categories/pov?sort_by=release_at","n":"男友視角"}, +{"v":"categories/hidden-cam?sort_by=release_at","n":"偷拍"}, +{"v":"categories/lesbian?sort_by=release_at","n":"女同歡愉"} + ]}], +"categories/chinese-subtitle":[ +{"key":"by","name":"最近更新","value":[ +{"v":"release_at","n":"最近更新"}, +{"v":"stars","n":"最近佳作"}, +{"v":"views","n":"最多观看"}]} + +], +"21":[ + {"key":"cateId","name":"分类","value":[ +{"v":"21","n":"全部"}, +{"v":"31","n":"人妻"}, +{"v":"44","n":"素人"}, +{"v":"46","n":"口爆颜射"}, +{"v":"47","n":"萝莉少女"}, +{"v":"48","n":"美乳巨乳"}, +{"v":"52","n":"制服诱惑"}, +{"v":"57","n":"调教"}, +{"v":"58","n":"出轨"}, +{"v":"101","n":"有码精品"} +]}], +"22":[ + {"key":"cateId","name":"分类","value":[ +{"v":"22","n":"全部"}, +{"v":"102","n":"无码精品"} +]}], +"23":[ + {"key":"cateId","name":"分类","value":[ +{"v":"23","n":"全部"}, +{"v":"104","n":"欧美精品"} +]}], +"24":[ + {"key":"cateId","name":"分类","value":[ +{"v":"24","n":"全部"}, +{"v":"103","n":"动漫精品"} +]}] +, +"25":[ + {"key":"cateId","name":"分类","value":[ +{"v":"views","n":"全部"}, +{"v":"39","n":"综合三级"} + +]}], +"hot":[ + {"key":"cateId","name":"分类","value":[ +{"v":"views","n":"全部"}, +{"v":"51","n":"日本中字"} + + +]}] + +} +} \ No newline at end of file diff --git a/lib/18jtv.json b/lib/18jtv.json new file mode 100644 index 0000000..373710a --- /dev/null +++ b/lib/18jtv.json @@ -0,0 +1,144 @@ +{ +//最新地址发布页https://18fby.com/?18j +//永久地址18j.tv +"规则名": "18jtv-XYQHiker", +"规则作者": "飞鱼", +"请求头参数": "手机", +"网页编码格式": "UTF-8", +"图片是否需要代理": "0", +"是否开启获取首页数据": "1", +"首页推荐链接": "https://18kb.life/label/hot/by/time/nid/1/page/1/sid/1/", +"首页列表数组规则": ".main_list", + //"首页列表数组规则": ".main&&.main_list", +"首页片单列表数组规则": "li", +"首页片单是否Jsoup写法": "1", +"首页片单标题": ".title&&Text", +"首页片单链接": "a&&href", +"首页片单图片": "img&&data-original", +//"首页片单副标题": "'📆'+span&&Text", +"首页片单链接加前缀": "https://18je.life", +"首页片单链接加后缀": "", +"分类起始页码": "1", +//{cateId}分类id +//{area}地区 +//{by}排序 +//{class}剧情 +//{lang}语言 +//{catePg}翻页序列号 +//{year}日期 +"分类链接": "https://18kb.life/show/{cateId}/by/{by}/nid/1/page/{catePg}/sid/1/", +"分类名称": "国产&日韩&欧美&伦理&动漫&", +"分类名称替换词": "1&2&3&4&16&", +"分类截取模式": "1", +"分类列表数组规则": ".main_list&&li", +"分类片单是否Jsoup写法": "1", +"分类片单标题": ".title&&Text", +"分类片单链接": "a&&href", +"分类片单图片": ".vodlist_img&&img&&data-original", +//"分类片单副标题": "'📆'+span&&Text", +"分类片单链接加前缀": "https://18kb.life", +"分类片单链接加后缀": "", +"搜索请求头参数": "User-Agent$手机", +"搜索链接": "https://18kb.life/index.php/ajax/suggest?mid=1&wd={wd}", +"POST请求数据": "", +"搜索截取模式": "0", +"搜索列表数组规则": "list", +"搜索片单是否Jsoup写法": "1", +"搜索片单图片": "pic", +"搜索片单标题": "name", +"搜索片单链接": "id", +"搜索片单副标题": "", +"搜索片单链接加前缀": "https://18kb.life/v/", +"搜索片单链接加后缀": "/", +"链接是否直接播放": "1", +"直接播放链接加前缀": "", +"直接播放链接加后缀": "", +"直接播放直链视频请求头": "", + + + +"分析MacPlayer": "0", +"是否开启手动嗅探": "1", +"手动嗅探视频链接关键词": ".m3u8", +"手动嗅探视频链接过滤词": "baidu.com", + + "筛选数据":{ +"1":[ + {"key":"cateId","name":"分类","value":[ +{"n":"全部","v":"1"}, +{"n":"国产自拍","v":"5"}, +{"n":"主播诱惑","v":"6"}, +{"n":"探花约炮","v":"7"}, +{"n":"偷拍偷窥","v":"8"}, +{"n":"乱伦侵犯","v":"9"}, +{"n":"网爆吃瓜","v":"10"}, +{"n":"短视频","v":"11"}, +{"n":"传媒剧情","v":"12"} +] +}, + + {"key":"by","name":"排序","value":[ + {"n":"最新","v":"time"}, + {"n":"日榜","v":"hits_day"}, + {"n":"周榜","v":"hits_week"}, + {"n":"总榜","v":"hits_month"}]}], +"2":[ + {"key":"cateId","name":"分类","value":[ +{"n":"全部","v":"2"}, +{"n":"日韩自拍","v":"13"}, +{"n":"日韩无码","v":"14"}, +{"n":"中文字幕","v":"15"}, +{"n":"av解说","v":"17"}, +{"n":"换脸明星","v":"18"}, +{"n":"无码字幕","v":"19"}, +{"n":"有码字幕","v":"20"} +] +}, + {"key":"by","name":"排序","value":[ + {"n":"最新","v":"time"}, + {"n":"日榜","v":"hits_day"}, + {"n":"周榜","v":"hits_week"}, + {"n":"总榜","v":"hits_month"}]}], +"3":[ +{"key":"cateId","name":"分类","value":[ +{"n":"全部","v":"3"}, +{"n":"欧美自拍","v":"21"}, +{"n":"欧美字幕","v":"22"}, +{"n":"重口味","v":"23"} +] +}, + {"key":"by","name":"排序","value":[ + {"n":"最新","v":"time"}, + {"n":"日榜","v":"hits_day"}, + {"n":"周榜","v":"hits_week"}, + {"n":"总榜","v":"hits_month"}]}], +"4":[ +{"key":"cateId","name":"分类","value":[ +{"n":"全部","v":"4"}, +{"n":"港台伦理","v":"29"}, +{"n":"日韩伦理","v":"30"}, +{"n":"欧美伦理","v":"31"} +] +}, + {"key":"by","name":"排序","value":[ + {"n":"最新","v":"time"}, + {"n":"日榜","v":"hits_day"}, + {"n":"周榜","v":"hits_week"}, + {"n":"总榜","v":"hits_month"}]}], +"16":[ + +{"key":"cateId","name":"分类","value":[ +{"n":"全部","v":"16"}, +{"n":"剧集动漫","v":"26"}, +{"n":"3D动漫","v":"27"}, +{"n":"次元动漫","v":"28"} +] +}, + {"key":"by","name":"排序","value":[ + {"n":"最新","v":"time"}, + {"n":"日榜","v":"hits_day"}, + {"n":"周榜","v":"hits_week"}, + {"n":"总榜","v":"hits_month"}]}]} + + +} diff --git a/lib/300分类.json b/lib/300分类.json new file mode 100644 index 0000000..c9df8ac --- /dev/null +++ b/lib/300分类.json @@ -0,0 +1,73 @@ +{ +"规则名": "PPT", +"请求头参数":"PC_UA", +"网页编码格式":"UTF-8", +"图片是否需要代理":"0", +"是否开启获取首页数据":"1", +"首页推荐链接": "https://www.pornlulu.com/zh-hans", +//https://www.ptt.sex +"首页列表数组规则": "#videos", +"首页片单列表数组规则": ".card", +"首页片单是否Jsoup写法": "1", +"首页片单标题": "img&&alt", +"首页片单链接": "a&&href", +"首页片单图片": "img&&src", +"首页片单副标题": "{更新}+span,0&&Text", +"首页片单链接加前缀": "https://www.pornlulu.com", +"首页片单链接加后缀": "", +"分类起始页码": "1", +"分类链接": "https://www.pornlulu.com/zh-hans/cat/{cateId}?page={catePg}", + +"分类名称": "国产自拍&中文字幕&国产情色&日本无码&日本有码&国产精品&强姦乱伦&欧美精品&制服诱惑&成人动漫&亚洲有码&萝莉少女&美女主播&国产视频&巨乳美乳&国产主播&欧美极品&骑兵有码&自拍偷拍&抖阴视频&无码专区&亚洲情色&动漫精品&日韩无码&亚洲无码&女同性恋&欧美情色&AV明星&国产传媒&熟女人妻&三级伦理&日本伦理&网红主播&国产伦理&国产偷拍&名优中字&91探花&精品推荐&卡通动漫&主播直播&美乳巨乳&制服丝袜&映画传媒&人妻熟女&其他亚洲&韩国伦理&步兵无码&欧美性爱&日韩精品&制服师生&国产乱伦&动漫卡通&女优明星&女神学生&童颜巨乳&邻家人妻&主播大秀&调教中文&麻豆传媒&巨乳中文&乱伦中文&绝美少女&娇妻素人&人妻中文&多人群交&国模私拍&空姐模特&自慰群交&国产名人&口交颜射&美熟少妇&网曝门事&女同性爱&国产裸聊&制服中文&国产情侣&大秀视频&金髮幼齿&职场同事&AV解说&欧美专区&出轨中文&精品短视&角色扮演&国产探花&独家DM&激情口交&欧美伦理&激情动漫&巨乳系列&SWAG&长腿丝袜&口交视频&欧美激情&无码中文&网红头条&福利姬视&SM调教&探花系列&抖阴短片&日本素人&伦理三级&HEY诱&人妻系列&三级字幕&高潮喷吹&国产盗摄&Cosp&韩国极品&日本精品&人妖系列&高清无码&网曝黑料&欧美系列&HEYZ&野合车震&国产色情&丝袜美腿&AI换脸&口爆颜射&韩国明星&欧美无码&VR视角&明星换脸&群交淫乱&素人自拍&网爆黑料&网红黑料&强姦中文&韩国精品&麻豆视频&日本片商&传媒出品&传媒剧情&探花约炮&偷拍偷窥&偷拍自拍&网红流出&SM重味&主播秀色&韩国主播&女僕系列&传媒原创&剧情介绍&网曝吃瓜&高清名优&日本女优&主播诱惑&AV明星&女优系列&恋腿狂魔&换脸明星&黑丝诱惑&欺辱凌辱&丝袜OL&网曝视频&香港伦理&SM重口&三级片视&性感人妻&岛国群交&绿帽淫妻&极骚萝莉&其他片商&欧美高清&精品动漫&东南亚A&自慰系列&美颜巨乳&三级自慰&精品素人&瑜伽裤视&海外明星&口交潮吹&3P合辑&剧情动漫&虚拟VR&台湾辣妹&唯美港姐&天美传媒&素人搭讪&韩国唯美&野外露出&91系列&教师学生&多P 3&闷骚护士&韩国御姐&可爱学生&童真萝莉&恋腿癖视&凌辱束缚&蜜桃传媒&传媒机构&糖心Vl&首次亮相&风情旗袍&极品少妇&兽耳系列&无码破解&古装扮演&日本乱伦&多人多P&mini&东南亚情&抖音视频&颜射系列&乌鸦传媒&女优合集&同性同志&主播自拍&贫乳小奶&翘臀美尻&韩美眉主&欧美视频&星空传媒&91製片&重咸口味&精东影业&台湾sw&韩国自拍&国产女奴&骚货护士&学生系列&性感港姐&网曝热门&野外系列&同性女优&台湾色情&学生中出&人兽性交&岛国素人&日韩主播&性感旗袍&大象传媒&伦理影片&高丽棒子&名优写真&兽耳作品&乱伦背德&及膝袜视&萝莉社视&开心鬼传&重口激情&TS人妖&滴滴探花&兔子先生&非亚洲视&SPA视&VR有码&性视界视&名优综艺&网红少女&国产女王&高清欧美&皇家华人&UP精品&明星淫梦&抖音短视&极品媚黑&成人头条&杏吧原创&P站原创&国漫3D&探花寻花&SM捆绑&人妖视频&日韩伦理&AI合成&视频伦理&日本中字&精选独家&精选视频&热门头条&VR无码&女同人妖&水果派原&性世界视&高清伦理&91大神&精选口爆&杏吧传媒&少女破处&果冻传媒&星空无限&JVID&颜射瞬间&三级剧情&香港三级&SA国际&性知识视&小鸟酱专&乐播传媒&扣扣传媒&中文音声", +"分类名称替换词": "263&48&119&270&269&249&13&260&92&274&105&103&264&304&93&268&266&261&98&25&254&22&86&259&64&115&265&401&390&267&84&45&88&285&277&37&455&140&130&303&111&248&395&23&287&44&288&52&275&272&252&149&438&250&125&273&253&16&416&292&290&109&15&289&129&31&5&33&251&374&8&58&132&521&291&66&89&262&6&392&531&19&36&221&482&97&134&286&453&99&452&138&110&328&293&437&27&375&433&514&393&367&123&101&442&96&522&418&57&467&477&280&483&131&124&24&460&169&357&369&54&246&451&69&520&419&440&476&30&55&490&403&474&512&511&515&278&457&106&417&158&402&370&415&513&394&432&510&439&471&468&516&454&466&424&547&61&243&548&425&391&524&142&536&527&534&472&100&378&143&532&410&358&215&126&517&523&461&464&501&450&56&456&429&128&423&469&459&465&408&422&421&494&556&503&135&458&478&463&70&462&530&470&500&426&441&136&498&525&152&208&436&434&59&232&497&493&144&504&528&159&71&420&479&413&526&407&398&412&414&141&372&317&406&496&120&443&40&427&399&409&508&506&518&545&553&505&50&563&18&509&60&559&72&567&492&564&163&561&519&499&507&62&558&384&81&147&150&400&148&562&435&551&549&34&428&560&537&565&314&151&541&557&535&533&540&67&276&529&538&566&74&495&539&568", + +"筛选数据":{}, +"分类截取模式": "1", +"分类列表数组规则": "#videos&&.card", +"分类片单是否Jsoup写法":"1", +"分类片单标题": "img&&alt", +"分类片单链接": "a&&href", +"分类片单图片": "img&&src", +"分类片单副标题":"span,0&&Text", +"分类片单链接加前缀": "https://www.pornlulu.com", +"分类片单链接加后缀": "", +"搜索请求头参数":"User-Agent$PC_UA", +"搜索链接": "https://www.pornlulu.com/zh-hans?q={wd}", +"搜索截取模式": "1", +"搜索列表数组规则": "#videos&&.card", +"搜索片单是否Jsoup写法":"1", +"搜索片单图片": "img&&data-src", +"搜索片单标题": "img&&alt", +"搜索片单链接": "a&&href", +"搜索片单副标题":"", +"搜索片单链接加前缀": "https://www.pornlulu.com", +"搜索片单链接加后缀": "", +"链接是否直接播放": "1", +"直接播放链接加前缀": "", +"直接播放链接加后缀": "", +"直接播放直链视频请求头": "", +//"详情是否Jsoup写法":"1", +//"类型详情": "", +//"年代详情": "", +//"地区详情": "", +//"演员详情": "#w4&&.breadcrumb-item,1&&Text", +//"简介详情": "meta,7&&content", + +//"线路列表数组规则": "head&&meta,9&&[property]", +//"线路标题": "meta&&content", + +//"播放列表数组规则": "head", +//"选集列表数组规则": "meta,10&&[property]", +//"选集标题链接是否Jsoup写法":"1", +//"选集标题": "meta&&property", +//"选集链接": "meta&&content", +//"是否反转选集序列": "0", +//"选集链接加前缀": "https://www.pornlulu.com/zh-hans", +//"选集链接加后缀": "", + +"分析MacPlayer":"0", + +"是否开启手动嗅探":"1", +"手动嗅探视频链接关键词":".m3u8", +"手动嗅探视频链接过滤词":".mp4" +} \ No newline at end of file diff --git a/lib/3Q.json b/lib/3Q.json new file mode 100644 index 0000000..e0c7341 --- /dev/null +++ b/lib/3Q.json @@ -0,0 +1,29 @@ +{ + "请求头": "User-Agent$MOBILE_UA", + "编码": "UTF-8", + "图片代理": "0", + "主页url": "https://qqqys.com", + "首页": "120", + "起始页": "1", + "分类url": "https://qqqys.com/vodshow/{cateId}/{catePg}.html;;mrcd0", + "分类": "电影&剧集&综艺&动漫&短剧", + "分类值": "1&2&4&3&5", + "数组": "/vd&&", + "标题": "title=\"&&\"", + "图片": "data-original=\"&&\"", + "副标题": "truncate text*>&&&&", + "状态": "上映:&&", + "导演": "导演:&&", + "主演": "主演:&&", + "简介": "【友情提醒:请不要相信视频中的广告,以免上当受骗!】✨乐哥为您介绍剧情👉+

&&

", + "跳转数组": "vodId:&&,", + "跳转链接": "https://qqqys.com/api.php/internal/search_aggregate?vod_id=+\"&&\"", + "线路数组": "", + "线路标题": "✨乐哥推荐✨线路", + "播放数组": "vod_play_url\":&&,[替换:\">>接表题#$>>题接#\\#>>接表表题]", + "播放列表": "表&&表", + "播放标题": "题&&题", + "播放链接": "接&&接" +} \ No newline at end of file diff --git a/lib/404xav.json b/lib/404xav.json new file mode 100644 index 0000000..20c9b23 --- /dev/null +++ b/lib/404xav.json @@ -0,0 +1,45 @@ +{ + "作者": "黑哥传媒", + "站名": "", + "请求头": "User-Agent@Mozilla/5.0 (Linux;; Android 12;; RMX3370 Build/RKQ1.211103.002;; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/136.0.7103.60 Mobile Safari/537.36&&Cookie@tcpvsd=1756552262454;; 404_lang=zh;; HstCfa4688805=1756550997675;; HstCmu4688805=1756550997675;; HstCnv4688805=1;; HstCns4688805=1;; c_ref_4688805=https%3A%2F%2F2506_ningmeng.xav301.top%2Furl%2F;; Hm_tf_k848bd84m4b=1756550998;; Hm_lvt_k848bd84m4b=1756550998;; index=2025%2F8%2F30;; 0_type=2025%2F8%2F30;; sskd__uuid_=237ba8cd21cd4b2e8a74ac2fcd66b985;; __uid=a867e333d7734dbb86034d0676678065;; 0_video=2025%2F8%2F30;; 0_search=2025%2F8%2F30;; sskd_f-ss-237ba8cd21cd4b2e8a74ac2fcd66b985=15;; __dtsu=4C301750358809B70FF3DC3A2633DF62;; HstCla4688805=1756552262252;; HstPn4688805=29;; HstPt4688805=29;; Hm_lpvt_k848bd84m4b=1756552262;; sskd_t-ss-237ba8cd21cd4b2e8a74ac2fcd66b985=1;; sskd_v-ss-237ba8cd21cd4b2e8a74ac2fcd66b985=2;; fkpp2-a867e333d7734dbb86034d0676678065=2&&Accept@text/html,application/xhtml+xml,application/xml;;q=0.9,image/avif,image/webp,image/apng,*/*;;q=0.8,application/signed-exchange;;v=b3;;q=0.7&&Accept-Language@zh-CN,zh;;q=0.9", + "编码": "UTF-8", + "图片代理": "0", + "主页url": "https://xn--08303-404xavcom-2h61a0814fire.4042516.icu", + "首页": "120", + "起始页": "1", + "分类url": "https://xn--08303-404xavcom-2h61a0814fire.4042516.icu/type/{cateId}/0/{catePg}.html;;mrcd0", + "分类": "xvideos&xnxx&91资源&91资源cn&原创资源&仓库资源&杏吧资源&桃花资源&细胞资源&百万资源&番号资源&色P资源&GAY资源&155资源&玉兔资源&jkun资源&奥斯卡资源&黄瓜资源&草榴资源&森林资源&奶香香资源&丝袜资源&大地资源&乐播资源&辣椒资源&色猫资源&滴滴资源&美少女资源&淫水机资源&香奶儿资源&白嫖资源&小湿妹资源&黄AV资源&鲨鱼资源&老色逼资源&精品X资源", + "分类值": "*", + "二次截取": "web_grid_box\">&&class=\"page-active[替换:pages>>cell_box]", + "数组": "v_thumb\">&&cell_box\">", + "标题": "v_title\">&&&&<", + "链接": "href=\"&&\"", + "简介": "👶黑哥传媒推荐:+web_detail_title\">&&", + "线路二次截取": "", + "线路数组": "module-tab-item tab-item&&/small>", + "线路标题": "👶+>&&+【共+&&<+集】", + "播放二次截取": "", + "播放数组": "module-play-list\">&&", + "播放列表": "", + "播放标题": ">&&<", + "播放链接": "href=\"&&\"", + "解析": "", + "直接播放": "1", + "播放请求头": "", + "嗅探词": ".mp4#.m3u8", + "过滤词": "", + "跳转播放链接": "var play_data =\"&&\"", + "跳转解析": "", + "搜索请求头": "User-Agent$MOBILE_UA", + "搜索url": "https://xn--08303-404xavcom-2h61a0814fire.4042516.icu/search/{wd}.html", + "搜索模式": "1", + "搜索后缀": "", + "搜索二次截取": "", + "筛选": "1", + "类型": "", + "剧情": "", + "剧情值": "*", + "地区": "" +} diff --git a/lib/444咖啡.json b/lib/444咖啡.json new file mode 100644 index 0000000..02cb56d --- /dev/null +++ b/lib/444咖啡.json @@ -0,0 +1,175 @@ +{ +// +//回家地址 → https://www.444.coffee/数字改 +//https://www.444.coffee/ +"规则名": "444咖啡-XYQHiker", +"规则作者": "飞鱼", +"请求头参数": "手机", +"网页编码格式": "UTF-8", +"图片是否需要代理": "0", +"是否开启获取首页数据": "0", +"首页推荐链接": "https://www.444.coffee", +"首页列表数组规则": ".list-videos", +"首页片单列表数组规则": ".item", +"首页片单是否Jsoup写法": "1", +"首页片单标题": ".title&&Text", +"首页片单链接": "a&&href", +"首页片单图片": "img&&data-original", +"首页片单副标题": "'📅'+.added&&Text+'👁️'+.views&&Text", +"首页片单链接加前缀": "", +"首页片单链接加后缀": "", +"分类起始页码": "1", +"分类链接": "https://www.444.coffee/page/{catePg}?order={cateId}", +"分类名称": "最新&最多人看&评分", +"分类名称替换词": "newest&views&rate", +"分类截取模式": "1", +"分类列表数组规则": ".Thumbnail_List&&li:has(img)", +"分类片单是否Jsoup写法": "1", +"分类片单标题": ".title&&Text", +"分类片单链接": "a&&href", +"分类片单图片": "img&&src", +"分类片单副标题": "'更新于'+.added&&Text!ago+'前'+'👁️'+.post-views&&Text!Views+.post-category&&Text", + +"分类片单链接加前缀": "", +"分类片单链接加后缀": "", +"搜索请求头参数": "User-Agent$手机", +"搜索链接": "https://www.444.coffee/?post_type=post&s={wd}", +"POST请求数据": "", +"搜索截取模式": "1", +"搜索列表数组规则": ".Thumbnail_List&&li:has(img)", +"搜索片单是否Jsoup写法": "1", +"搜索片单图片": "img&&src", +"搜索片单标题": ".title&&Text", +"搜索片单链接": "a&&href", +"搜索片单副标题": "'📅'+.added&&Text+'👁️'+.post-views&&Text+.post-category&&Text", +"搜索片单链接加前缀": "", +"搜索片单链接加后缀": "", +"链接是否直接播放": "1", +"直接播放链接加前缀": "", +"直接播放链接加后缀": "", +"直接播放直链视频请求头": "", + "详情是否Jsoup写法":"0", + "类型详情": "

類型:&&

", + "年代详情": "

更新:&&

", + "地区详情": "", + "演员详情": "", + "简介详情": "", + "线路列表数组规则": ".play-btn-group&&.line", + "线路标题": "'📽️'+a&&Text+'📺'", + "播放列表数组规则": ".line", + "选集列表数组规则": "a", + "选集标题链接是否Jsoup写法":"1", + "选集标题": "a&&Text", + "选集链接": "a&&href", + "是否反转选集序列": "0", + "选集链接加前缀": "https://www.444.coffee", + "选集链接加后缀": "", + +"筛选数据":{ +"/vodshow/1":[ + {"key":"cateId", + "name":"分类", + "value":[ +{"v":"/vodshow/1","n":"全部"}, +{"v":"/vodshow/6","n":"国产自拍"}, +{"v":"/vodshow/7","n":"主播大秀"}, +{"v":"/vodshow/8","n":"探花约啪"}, +{"v":"/vodshow/9","n":"国产番号"}, +{"v":"/vodshow/10","n":"网红少女"}, +{"v":"/vodshow/11","n":"偷窥偷拍"}]}, +{"key":"by", + "name":"排序", + "value":[ + {"v":"","n":"最新"}, + {"v":"hits","n":"热门"}, + {"v":"up","n":"点赞"}, + {"v":"score","n":"评分"} +]} +], +"/vodshow/2":[ + {"key":"cateId", + "name":"分类", + "value":[ +{"v":"/vodshow/2","n":"全部"}, +{"v":"/vodshow/13","n":"日本无码"}, +{"v":"/vodshow/14","n":"中文字幕"}, +{"v":"/vodshow/15","n":"日韩有码"}, +{"v":"/vodshow/16","n":"AV解说"}]}, +{"key":"by", + "name":"排序", + "value":[ + {"v":"","n":"最新"}, + {"v":"hits","n":"热门"}, + {"v":"up","n":"点赞"}, + {"v":"score","n":"评分"} +]} +], +"/vodshow/21":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"","n":"最新"}, + {"v":"hits","n":"热门"}, + {"v":"up","n":"点赞"}, + {"v":"score","n":"评分"} +]} +], +"/vodshow/3":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"","n":"最新"}, + {"v":"hits","n":"热门"}, + {"v":"up","n":"点赞"}, + {"v":"score","n":"评分"} +]} +], +"/vodshow/4":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"","n":"最新"}, + {"v":"hits","n":"热门"}, + {"v":"up","n":"点赞"}, + {"v":"score","n":"评分"} +]} +], +"/vodshow/5":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"","n":"最新"}, + {"v":"hits","n":"热门"}, + {"v":"up","n":"点赞"}, + {"v":"score","n":"评分"} +]} +], +"/vodshow/20":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"","n":"最新"}, + {"v":"hits","n":"热门"}, + {"v":"up","n":"点赞"}, + {"v":"score","n":"评分"} +]} +], +"/vodshow/22":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"","n":"最新"}, + {"v":"hits","n":"热门"}, + {"v":"up","n":"点赞"}, + {"v":"score","n":"评分"} +]} +] + + +}, + +"分析MacPlayer": "0", +"是否开启手动嗅探": "1", +"手动嗅探视频链接关键词": ".m3u8#.mp4", +"手动嗅探视频链接过滤词": "baidu.com" +} \ No newline at end of file diff --git a/lib/51短剧.json b/lib/51短剧.json new file mode 100644 index 0000000..6dbfc9d --- /dev/null +++ b/lib/51短剧.json @@ -0,0 +1,20 @@ +{ + "作者": "Aries", + "站名": "51吃瓜短剧", + "编码": "UTF-8", + "请求头": "User-Agent$MOBILE_UA", + "主页url": "https://51cg1.com/category/cbdj/", + "首页": "200", + "起始页": "0", + "分类url": "https://51cg1.com/category/{cateId}/{catePg}/[https://51cg1.com/category/{cateId}/];;mrcRAz", + "分类": "✨短剧✨$cbdj#", + "数组": "url *\"&&&&<", + "链接": "

&&

", + "标题": "title*>&&<", + "图片": "lazy fadein*src=\"&&\"", + "副标题": "✨+多看少撸管+✨", + "链接": "href=\"&&\"" +} \ No newline at end of file diff --git a/lib/69超级影院.json b/lib/69超级影院.json new file mode 100644 index 0000000..757028f --- /dev/null +++ b/lib/69超级影院.json @@ -0,0 +1,31 @@ +{ + "作者": "黑哥传媒", + "站名": "", + "请求头": "User-Agent@Mozilla/5.0 (Linux;; Android 12;; RMX3370 Build/RKQ1.211103.002;; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/136.0.7103.60 Mobile Safari/537.36&&Cookie@zone-cap-3959997=1;; zone-cap-3954650=1;; zone-cap-3614151=1;; zone-cap-3614329=1;; xv_nbview=-1;; wpn-popupunder=1;; autojumpNum10604=1;; autojumpPV10604=1;; autojumpStats10604=1;; zone-cap-3959997=1;; zone-cap-3954650=1;; zone-cap-3614151=1;; zone-cap-3614329=1;; xv_nbview=-1;; wpn-popupunder=1;; autojumpNum10604=1;; autojumpPV10604=1;; autojumpStats10604=1;; static_cdn=c7;; zone-cap-3959997=1;; zone-cap-3954650=1;; zone-cap-3614151=1;; zone-cap-3614329=1;; xv_nbview=-1;; wpn-popupunder=1;; autojumpNum10604=1;; autojumpPV10604=1;; autojumpStats10604=1;; showdomain=1;; tackStats10604=1;; HstCfa4579560=1758499369351;; HstCmu4579560=1758499369351;; HstCnv4579560=1;; c_ref_4579560=https%3A%2F%2Fwww.69bag.buzz%2F;; __dtsu=4C301750358809B70FF3DC3A2633DF62;; UBGLAI63GV=bsftm.1758499417;; pending_thumb=%7B%22t%22%3A%5B%5D%2C%22s%22%3A%5B%5D%2C%22p%22%3A%5B%5D%2C%22r%22%3A%5B%5D%7D;; HstCns4579560=2;; __ty_cpvx_t_4899_cpv_plan_ids=%7C54%7C;; __ty_cpvx_t_4899_cpv_plan_uids=%7C3607%7C;; __ty_cpvx_b_4900_cpv_plan_ids=%7C16%7C%7C19%7C%7C11%7C%7C54%7C%7C31%7C%7C2%7C%7C29%7C;; __ty_cpvx_b_4900_cpv_plan_uids=%7C10%7C%7C11%7C%7C9%7C%7C3607%7C%7C2297%7C%7C6%7C%7C1536%7C;; HstCla4579560=1758501440842;; HstPn4579560=28;; HstPt4579560=28&&Accept@text/html,application/xhtml+xml,application/xml;;q=0.9,image/avif,image/webp,image/apng,*/*;;q=0.8,application/signed-exchange;;v=b3;;q=0.7&&Accept-Language@zh-CN,zh;;q=0.9", + "编码": "UTF-8", + "图片代理": "0", + "主页url": "https://www.69bag25.com", + "首页": "120", + "起始页": "1", + "分类url": "https://www.69bag25.com/search/{cateId}/{catePg};;mrcd0", + "分类二次截取": "locale_flag\":\"&&more_links\"", + "分类数组": "{\"&&\"cat_id", + "分类标题": "黑哥传媒+label\":\"&&\"", + "分类ID": "url\":\"&&\"", + "分类": "", + "分类值": "", + "二次截取": "", + "数组": "thumb-inside\">&&", + "标题": "title=\"&&\"", + "图片": "data-src=\"&&\"", + "副标题": "✨+right\">&&<", + "链接": "href=\"&&\"", + "解析": "", + "直接播放": "1", + "播放请求头": "", + "嗅探词": ".mp4#.m3u8", + "过滤词": "", + "跳转播放链接": "", + "跳转解析": "", + "搜索请求头": "User-Agent$MOBILE_UA" +} diff --git a/lib/83视频.json b/lib/83视频.json new file mode 100644 index 0000000..bc70956 --- /dev/null +++ b/lib/83视频.json @@ -0,0 +1,18 @@ +{ + "作者": "Aries", + "站名": "", + "请求头": "User-Agent$MOBILE_UA", + "编码": "UTF-8", + "主页url": "https://rep.83sp3.work/cn/home/web/", + "首页": "120", + "起始页": "1", + "分类url": "https://rep.83sp3.work/cn/home/web/index.php/vod/type/id/{cateId}/page/{catePg}.html;;z", + "分类": "自拍偷拍$20#强奸乱伦$22#人妻熟女$23#制服丝袜$24#花季少女$25#无码露毛$26#群P多人$27#人兽人妖$28#男同女同$29#韩日专区$30#欧美色情$31#成人动漫$32#三级剧情$33", + "二次截取": "", + "数组": "/vod/play/&&

", + "标题": "/vod/play/*>&&<", + "图片": "src=\"&&\"", + "副标题": "✨+多看少撸管+✨", + "链接": "href=\"&&\"", + "跳转播放链接": "var player_*\"url\":\"&&\"" +} diff --git a/lib/91porn_asia.json b/lib/91porn_asia.json new file mode 100644 index 0000000..46a666e --- /dev/null +++ b/lib/91porn_asia.json @@ -0,0 +1,697 @@ +{ +// +//回家地址 → https://91porn.asia/ +//https://91porn.asia/ +"规则名": "91porn_asia-XYQHiker", +"规则作者": "飞鱼", +"请求头参数": "手机", +"网页编码格式": "UTF-8", +"图片是否需要代理": "0", +"是否开启获取首页数据": "1", +"首页推荐链接": "https://91porn.asia/zh", +"首页列表数组规则": "#main", +"首页片单列表数组规则": "article", +"首页片单是否Jsoup写法": "1", +"首页片单标题": "a&&title", +"首页片单链接": "a&&href", +"首页片单图片": "img&&data-src", +"首页片单副标题": "'👁️'+.views&&Text+'\n⏱️'+.duration&&Text", +"首页片单链接加前缀": "", +"首页片单链接加后缀": "", +"分类起始页码": "1", +"分类链接": "https://91porn.asia{cateId}page/{catePg}/?filter={by}", +"分类名称": "最新&Onlyfans&中出&中国&人妻&制服诱惑&国产AV&多P&女友&巨乳&无码&日本 JAV&未分类&欧美&素人&标签分类🏷️", +"分类名称替换词": "/&/category/onlyfans-zh/&/category/中出/&/category/中国-zh/&/category/人妻/&/category/制服诱惑/&/category/国产/&/category/多p/&/category/女友/&/category/巨乳/&/category/无码/&/category/jav-zh/&/category/未分类/&/category/欧美/&/category/素人/&/tag/3p/", +"分类截取模式": "1", +"分类列表数组规则": "#main&&article", +"分类片单是否Jsoup写法": "1", +"分类片单标题": "a&&title", +"分类片单链接": "a&&href", +"分类片单图片": "img&&data-src", +"分类片单副标题": "'👁️'+.views&&Text+'\n⏱️'+.duration&&Text", + +"分类片单链接加前缀": "", +"分类片单链接加后缀": "", +"搜索请求头参数": "User-Agent$手机", +"搜索链接": "https://91porn.asia/zh/?s={wd}", +"POST请求数据": "", +"搜索截取模式": "1", +"搜索列表数组规则": "#main&&article", +"搜索片单是否Jsoup写法": "1", +"搜索片单图片": "img&&data-src", +"搜索片单标题": "a&&title", +"搜索片单链接": "a&&href", +"搜索片单副标题": "'👁️'+.views&&Text+'\n⏱️'+.duration&&Text", +"搜索片单链接加前缀": "", +"搜索片单链接加后缀": "", +"链接是否直接播放": "1", +"直接播放链接加前缀": "", +"直接播放链接加后缀": "", +"直接播放直链视频请求头": "", + "详情是否Jsoup写法":"0", + "类型详情": "

類型:&&

", + "年代详情": "

更新:&&

", + "地区详情": "", + "演员详情": "", + "简介详情": "", + "线路列表数组规则": ".play-btn-group&&.line", + "线路标题": "'📽️'+a&&Text+'📺'", + "播放列表数组规则": ".line", + "选集列表数组规则": "a", + "选集标题链接是否Jsoup写法":"1", + "选集标题": "a&&Text", + "选集链接": "a&&href", + "是否反转选集序列": "0", + "选集链接加前缀": "https://91porn.asia", + "选集链接加后缀": "", + +"筛选数据":{ +"/tag/3p/":[ + {"key":"cateId", + "name":"分类", + "value":[ +{"v":"/tag/3p/","n":"3P"}, +{"v":"/tag/3p%ef%bc%8c%e5%a7%90%e5%a6%b9%ef%bc%8c%e5%a4%a7%e8%b1%a1%ef%bc%8c%e5%86%85%e8%89%b2%ef%bc%8c%e4%b8%ad%e5%9b%bd%ef%bc%8c%e5%a4%a7%e9%99%86-zh/","n":"3P,姐妹,大象,内色,中国,大陆"}, +{"v":"/tag/4k-zh/","n":"4K"}, +{"v":"/tag/4p-zh/","n":"4P"}, +{"v":"/tag/6p-zh/","n":"6P"}, +{"v":"/tag/18%e5%b2%81%e7%9a%84%e5%8f%af%e7%88%b1%e5%a5%b3%e5%ad%a9-zh/","n":"18岁的可爱女孩"}, +{"v":"/tag/69-zh/","n":"69"}, +{"v":"/tag/91porn-zh/","n":"91porn"}, +{"v":"/tag/after-shower-zh/","n":"after shower"}, +{"v":"/tag/amateur-zh/","n":"amateur"}, +{"v":"/tag/anal-zh/","n":"anal"}, +{"v":"/tag/asian-zh/","n":"asian"}, +{"v":"/tag/asian-porn-zh/","n":"Asian Porn"}, +{"v":"/tag/a%e7%89%87/","n":"A片"}, +{"v":"/tag/babe-zh/","n":"babe"}, +{"v":"/tag/bdsm-zh/","n":"bdsm"}, +{"v":"/tag/big-ass-zh/","n":"big ass"}, +{"v":"/tag/big-butt-zh/","n":"big butt"}, +{"v":"/tag/big-tits-zh/","n":"big tits"}, +{"v":"/tag/blonde-zh/","n":"blonde"}, +{"v":"/tag/brunette-zh/","n":"brunette"}, +{"v":"/tag/bunni-zh/","n":"bunni"}, +{"v":"/tag/busty-zh/","n":"busty"}, +{"v":"/tag/china-zh/","n":"china"}, +{"v":"/tag/chinese-porn-zh/","n":"Chinese Porn"}, +{"v":"/tag/condom-break-zh/","n":"condom break"}, +{"v":"/tag/cosplay-zh/","n":"cosplay"}, +{"v":"/tag/creampie-zh/","n":"creampie"}, +{"v":"/tag/cum-inside-zh/","n":"cum inside"}, +{"v":"/tag/cute-zh/","n":"cute"}, +{"v":"/tag/cuteshaved/","n":"cuteshaved"}, +{"v":"/tag/deepthroat-zh/","n":"deepthroat"}, +{"v":"/tag/doggy-zh/","n":"doggy"}, +{"v":"/tag/fingering-zh/","n":"fingering"}, +{"v":"/tag/flixko/","n":"FLIXKO"}, +{"v":"/tag/handjob-zh/","n":"handjob"}, +{"v":"/tag/hd-zh/","n":"HD"}, +{"v":"/tag/hentai-zh/","n":"hentai"}, +{"v":"/tag/homemade-zh/","n":"homemade"}, +{"v":"/tag/hot-zh/","n":"hot"}, +{"v":"/tag/japan-zh/","n":"japan"}, +{"v":"/tag/japanese18/","n":"japanese18"}, +{"v":"/tag/japanese-porn-zh/","n":"Japanese porn"}, +{"v":"/tag/jav-zh/","n":"JAV"}, +{"v":"/tag/kiki-zh/","n":"kiki"}, +{"v":"/tag/korean-porn-zh/","n":"Korean porn"}, +{"v":"/tag/ntr-zh/","n":"Ntr"}, +{"v":"/tag/ol-zh/","n":"Ol"}, +{"v":"/tag/porn-zh/","n":"porn"}, +{"v":"/tag/pov-zh/","n":"pov"}, +{"v":"/tag/pussy-zh/","n":"pussy"}, +{"v":"/tag/rona/","n":"RONA"}, +{"v":"/tag/sex-zh/","n":"sex"}, +{"v":"/tag/sexy-zh/","n":"sexy"}, +{"v":"/tag/sucking-zh/","n":"sucking"}, +{"v":"/tag/teen-zh/","n":"teen"}, +{"v":"/tag/teen-porn-etc-zh/","n":"teen porn etc"}, +{"v":"/tag/thai-porn-zh/","n":"Thai porn"}, +{"v":"/tag/vlog-zh/","n":"vlog"}, +{"v":"/tag/xjx0062/","n":"xjx0062"}, +{"v":"/tag/%e4%b8%87%e9%9d%99%e9%9b%aa/","n":"万静雪"}, +{"v":"/tag/%e4%b8%8a%e5%8d%b7/","n":"上卷"}, +{"v":"/tag/%e4%b8%8a%e9%97%a8/","n":"上门"}, +{"v":"/tag/%e4%b8%8a%e9%97%a8%e6%9c%8d%e5%8a%a1/","n":"上门服务"}, +{"v":"/tag/%e4%b8%8b%e5%b1%9e%e6%88%96%e5%90%8c%e4%ba%8b/","n":"下属或同事"}, +{"v":"/tag/%e4%b8%8d%e5%80%ab/","n":"不倫"}, +{"v":"/tag/%e4%b8%9a%e4%bd%99/","n":"业余"}, +{"v":"/tag/%e4%b8%9a%e4%bd%99%e6%80%a7%e7%88%b1/","n":"业余性爱"}, +{"v":"/tag/%e4%b8%9d%e8%a2%9c-zh/","n":"丝袜"}, +{"v":"/tag/%e4%b8%ad%e5%87%ba-zh/","n":"中出"}, +{"v":"/tag/%e4%b8%ad%e5%9b%bd-zh/","n":"中国"}, +{"v":"/tag/%e4%b8%ad%e5%9b%bd-av/","n":"中国 AV"}, +{"v":"/tag/%e4%b8%ad%e5%9b%bd%e7%be%8e%e5%a5%b3/","n":"中国美女"}, +{"v":"/tag/%e4%b8%ad%e5%9b%bd%ef%bc%8c%e5%a4%a7%e9%99%86/","n":"中国,大陆"}, +{"v":"/tag/%e4%b8%ad%e6%97%a5%e5%a4%a7%e5%af%b9%e6%8a%97ep1/","n":"中日大对抗EP1"}, +{"v":"/tag/%e4%b9%90%e5%a5%88%e5%ad%90/","n":"乐奈子"}, +{"v":"/tag/%e4%b9%90%e6%92%ad%e4%bc%a0%e5%aa%92/","n":"乐播传媒"}, +{"v":"/tag/%e4%b9%b1%e4%bc%a6/","n":"乱伦"}, +{"v":"/tag/%e4%b9%b3%e4%ba%a4/","n":"乳交"}, +{"v":"/tag/%e4%ba%82%e5%80%ab/","n":"亂倫"}, +{"v":"/tag/%e4%ba%8c%e8%88%85/","n":"二舅"}, +{"v":"/tag/%e4%ba%9a%e6%b4%b2/","n":"亚洲"}, +{"v":"/tag/%e4%ba%9a%e6%b4%b2%e6%80%a7%e7%88%b1/","n":"亚洲性爱"}, +{"v":"/tag/%e4%ba%ba%e5%a6%bb-zh/","n":"人妻"}, +{"v":"/tag/%e4%ba%ba%e5%a6%bb%ef%bc%8c%e5%87%ba%e8%bb%8c%ef%bc%8c%e5%b7%a8%e4%b9%b3%ef%bc%8c%e7%84%a6%e9%bb%9e%e5%82%b3%e5%aa%92%ef%bc%8c%e7%97%b4%e5%a5%b3%ef%bc%8c%e8%82%89%e7%b5%b2%ef%bc%8c%e8%bf%b7%e4%bd%a0/","n":"人妻,出軌,巨乳,焦點傳媒,痴女,肉絲,迷你裙,香蕉视频"}, +{"v":"/tag/%e4%bb%8b%e7%bb%8d/","n":"介绍"}, +{"v":"/tag/%e4%bc%81%e5%88%92/","n":"企划"}, +{"v":"/tag/%e4%bc%98%e5%a8%9c/","n":"优娜"}, +{"v":"/tag/%e4%bc%a0%e5%aa%92/","n":"传媒"}, +{"v":"/tag/%e4%bf%9d%e5%ae%89/","n":"保安"}, +{"v":"/tag/%e5%81%9a%e7%88%b1/","n":"做爱"}, +{"v":"/tag/%e5%81%b7%e6%83%85/","n":"偷情"}, +{"v":"/tag/%e5%82%b3%e6%95%99%e5%a3%ab/","n":"傳教士"}, +{"v":"/tag/%e5%84%aa%e9%85%92/","n":"優酒"}, +{"v":"/tag/%e5%84%bf%e5%aa%b3/","n":"儿媳"}, +{"v":"/tag/%e5%85%84%e5%a6%b9/","n":"兄妹"}, +{"v":"/tag/%e5%85%84%e5%bc%9f/","n":"兄弟"}, +{"v":"/tag/%e5%85%8d%e8%b2%bba%e7%89%87/","n":"免費A片"}, +{"v":"/tag/%e5%85%94%e5%ad%90%e5%85%88%e7%94%9f/","n":"兔子先生"}, +{"v":"/tag/%e5%85%94%e5%ad%90%e5%85%88%e7%94%9f%ef%bc%8c%e6%97%a5%e6%9c%ac%ef%bc%8c%e7%be%8e%e4%ba%ba%ef%bc%8c%e5%86%85%e5%b0%84%ef%bc%8c%e4%b8%ad%e5%9b%bd%ef%bc%8c%e5%a4%a7%e9%99%86/","n":"兔子先生,日本,美人,内射,中国,大陆"}, +{"v":"/tag/%e5%85%94%e5%ad%90%e5%85%88%e7%94%9f%ef%bc%8c%e7%be%8e%e5%a5%b3%ef%bc%8c%e4%b8%ad%e5%9b%bd%ef%bc%8c%e5%a4%a7%e9%99%86/","n":"兔子先生,美女,中国,大陆"}, +{"v":"/tag/%e5%85%ad%e7%82%b9/","n":"六点"}, +{"v":"/tag/%e5%86%85%e5%b0%84-zh/","n":"内射"}, +{"v":"/tag/%e5%86%85%e8%a3%a4-zh/","n":"内裤"}, +{"v":"/tag/%e5%86%99%e7%9c%9f/","n":"写真"}, +{"v":"/tag/%e5%87%8c%e8%be%b1/","n":"凌辱"}, +{"v":"/tag/%e5%87%ba%e8%bb%8c/","n":"出軌"}, +{"v":"/tag/%e5%87%ba%e9%81%93%e4%bd%9c/","n":"出道作"}, +{"v":"/tag/%e5%88%9b%e6%84%8f/","n":"创意"}, +{"v":"/tag/%e5%88%b6%e6%9c%8d-zh/","n":"制服"}, +{"v":"/tag/%e5%88%ba%e6%bf%80/","n":"刺激"}, +{"v":"/tag/%e5%8a%87%e6%83%85/","n":"劇情"}, +{"v":"/tag/%e5%8a%a8%e6%bc%ab/","n":"动漫"}, +{"v":"/tag/%e5%8c%bb%e7%94%9f/","n":"医生"}, +{"v":"/tag/%e5%8d%95%e4%bd%93%e4%bd%9c%e5%93%81/","n":"单体作品"}, +{"v":"/tag/%e5%8f%8c%e9%a3%9e/","n":"双飞"}, +{"v":"/tag/%e5%8f%8c%e9%a9%ac%e5%b0%be/","n":"双马尾"}, +{"v":"/tag/%e5%8f%8d%e5%b7%ae/","n":"反差"}, +{"v":"/tag/%e5%8f%8d%e5%b7%ae%e5%a9%8a/","n":"反差婊"}, +{"v":"/tag/%e5%8f%98%e6%80%81/","n":"变态"}, +{"v":"/tag/blowjob-zh/","n":"口交"}, +{"v":"/tag/%e5%8f%a3%e4%ba%a4-zh/","n":"口交"}, +{"v":"/tag/%e5%8f%a3%e7%88%86/","n":"口爆"}, +{"v":"/tag/%e5%8f%a3%e7%bd%a9%ef%bc%8c-%e9%98%b4%e9%81%93-%ef%bc%8c%e6%9a%b4%e5%8a%9b-%ef%bc%8c%e9%a6%99%e8%95%89%e4%bc%a0%e5%aa%92/","n":"口罩, 阴道 ,暴力 ,香蕉传媒"}, +{"v":"/tag/%e5%8f%a4%e8%a3%85/","n":"古装"}, +{"v":"/tag/%e5%8f%af%e7%88%b1/","n":"可爱"}, +{"v":"/tag/%e5%90%8c%e5%ad%a6%e4%bc%9a/","n":"同学会"}, +{"v":"/tag/%e5%90%8e%e5%85%a5-zh/","n":"后入"}, +{"v":"/tag/%e5%90%b4%e6%a2%a6%e6%a2%a6/","n":"吴梦梦"}, +{"v":"/tag/%e5%90%b4%e8%8a%b3%e5%ae%9c/","n":"吴芳宜"}, +{"v":"/tag/%e5%90%b8%e7%b2%be/","n":"吸精"}, +{"v":"/tag/%e5%90%b9%e7%ae%ab/","n":"吹箫"}, +{"v":"/tag/%e5%91%98%e5%b7%a5/","n":"员工"}, +{"v":"/tag/%e5%91%bb%e5%90%9f/","n":"呻吟"}, +{"v":"/tag/%e5%94%90%e9%9b%a8%e8%8f%b2/","n":"唐雨菲"}, +{"v":"/tag/%e5%96%ae%e9%ab%94%e4%bd%9c%e5%93%81/","n":"單體作品"}, +{"v":"/tag/%e5%96%b7%e6%b0%b4/","n":"喷水"}, +{"v":"/tag/%e5%98%89%e4%bb%aa/","n":"嘉仪"}, +{"v":"/tag/%e5%98%bf%e5%b0%bc/","n":"嘿尼"}, +{"v":"/tag/%e5%9b%bd%e4%ba%a7-zh/","n":"国产"}, +{"v":"/tag/%e5%9b%bd-%e4%ba%a7%e5%89%a7%e6%83%85/","n":"国 产剧情"}, +{"v":"/tag/%e5%9b%bd%e9%a3%8e/","n":"国风"}, +{"v":"/tag/%e5%9c%8b%e7%94%a2av/","n":"國產AV"}, +{"v":"/tag/%e5%9c%8b%e7%94%a2%e5%8e%9f%e5%89%b5/","n":"國產原創"}, +{"v":"/tag/%e5%9c%a3%e8%af%9e%e8%80%81%e4%ba%ba%ef%bc%8c%e6%b5%aa%e5%a5%b3%ef%bc%8c%e5%8b%be%e5%bc%95%ef%bc%8c%e5%8f%91%e6%83%85%ef%bc%8c%e5%a4%a7%e8%b1%a1%e4%bc%a0%e5%aa%92/","n":"圣诞老人,浪女,勾引,发情,大象传媒"}, +{"v":"/tag/%e5%a3%b0%e4%b9%90/","n":"声乐"}, +{"v":"/tag/%e5%a4%8f%e6%99%b4%e5%ad%90/","n":"夏晴子"}, +{"v":"/tag/%e5%a4%96%e5%8d%96/","n":"外卖"}, +{"v":"/tag/%e5%a4%96%e9%81%87/","n":"外遇"}, +{"v":"/tag/%e5%a4%9ap/","n":"多P"}, +{"v":"/tag/%e5%a4%a7%e5%b1%81%e8%82%a1/","n":"大屁股"}, +{"v":"/tag/%e5%a4%a7%e6%88%98/","n":"大战"}, +{"v":"/tag/%e5%a4%a7%e8%b1%a1%e4%bc%a0%e5%aa%92/","n":"大象传媒"}, +{"v":"/tag/%e5%a4%a7%e8%b1%a1%e4%bc%a0%e5%aa%92%ef%bc%8cda23-zh/","n":"大象传媒,DA23"}, +{"v":"/tag/%e5%a4%a7%e8%b1%a1%e5%82%b3%e5%aa%92/","n":"大象傳媒"}, +{"v":"/tag/%e5%a4%a9%e4%b8%8b%e5%b8%83%e9%ad%94/","n":"天下布魔"}, +{"v":"/tag/%e5%a4%a9%e7%be%8e%e4%bc%a0%e5%aa%92/","n":"天美传媒"}, +{"v":"/tag/%e5%a5%b3%e4%bb%86/","n":"女仆"}, +{"v":"/tag/%e5%a5%b3%e4%bc%98/","n":"女优"}, +{"v":"/tag/%e5%a5%b3%e4%bc%98%ef%bc%8c%e7%88%b1%e8%b1%86/","n":"女优,爱豆"}, +{"v":"/tag/%e5%a5%b3%e5%84%aa-zh/","n":"女優"}, +{"v":"/tag/%e5%a5%b3%e5%8f%8b/","n":"女友"}, +{"v":"/tag/%e5%a5%b3%e5%a4%a7%e5%ad%a6%e7%94%9f/","n":"女大学生"}, +{"v":"/tag/%e5%a5%b3%e5%ad%a6%e7%94%9f/","n":"女学生"}, +{"v":"/tag/%e5%a5%b3%e6%95%99%e5%b8%88/","n":"女教师"}, +{"v":"/tag/%e5%a5%b3%e7%89%9b%e4%bb%94-zh/","n":"女牛仔"}, +{"v":"/tag/%e5%a5%b3%e7%a5%9e-zh/","n":"女神"}, +{"v":"/tag/%e5%a5%b3%e7%a7%98%e4%b9%a6/","n":"女秘书"}, +{"v":"/tag/%e5%a5%b3%e9%94%80%e5%94%ae/","n":"女销售"}, +{"v":"/tag/%e5%a5%b6%e5%a6%b9/","n":"奶妹"}, +{"v":"/tag/%e5%a5%b6%e7%89%9b%e5%a5%b3%e5%ad%a9/","n":"奶牛女孩"}, +{"v":"/tag/%e5%a6%bb%e7%99%bd%e8%99%8e/","n":"妻白虎"}, +{"v":"/tag/%e5%a7%90%e5%a7%90/","n":"姐姐"}, +{"v":"/tag/%e5%a7%90%e5%bc%9f/","n":"姐弟"}, +{"v":"/tag/%e5%a7%9a%e5%ae%9b%e5%84%bf/","n":"姚宛儿"}, +{"v":"/tag/%e5%a8%83%e5%a8%83/","n":"娃娃"}, +{"v":"/tag/%e5%aa%9a%e8%8d%af/","n":"媚药"}, +{"v":"/tag/%e5%aa%9a%e8%97%a5/","n":"媚藥"}, +{"v":"/tag/%e5%ab%82%e5%ad%90/","n":"嫂子"}, +{"v":"/tag/%e5%ab%a9%e7%a9%b4/","n":"嫩穴"}, +{"v":"/tag/%e5%ad%a6%e6%a0%a1/","n":"学校"}, +{"v":"/tag/%e5%ad%a6%e7%94%9f%e5%a6%b9/","n":"学生妹"}, +{"v":"/tag/%e5%ae%8b%e5%8d%97%e4%bc%8a/","n":"宋南伊"}, +{"v":"/tag/%e5%ae%8b%e9%9b%a8%e5%b7%9d/","n":"宋雨川"}, +{"v":"/tag/%e5%ae%a4%e5%8f%8b-zh/","n":"室友"}, +{"v":"/tag/%e5%ae%b6%e6%95%99/","n":"家教"}, +{"v":"/tag/%e5%af%b9%e7%99%bd/","n":"对白"}, +{"v":"/tag/%e5%af%bc%e6%bc%94%e7%b3%bb%e5%88%97/","n":"导演系列"}, +{"v":"/tag/%e5%b0%84%e7%b2%be-zh/","n":"射精"}, +{"v":"/tag/%e5%b0%8f%e5%96%b5%e5%92%aa/","n":"小喵咪"}, +{"v":"/tag/%e5%b0%8f%e5%a7%a8/","n":"小姨"}, +{"v":"/tag/%e5%b0%8f%e5%a7%a8%ef%bc%8c%e7%88%b1%e8%b1%86%e4%bc%a0%e5%aa%92/","n":"小姨,爱豆传媒"}, +{"v":"/tag/%e5%b0%8f%e6%b0%b4%e6%b0%b4/","n":"小水水"}, +{"v":"/tag/%e5%b0%8f%e6%b2%90/","n":"小沐"}, +{"v":"/tag/%e5%b0%8f%e7%8c%ab%e5%92%aa/","n":"小猫咪"}, +{"v":"/tag/%e5%b0%8f%e9%9b%a8/","n":"小雨"}, +{"v":"/tag/%e5%b0%8f%e9%b9%bf/","n":"小鹿"}, +{"v":"/tag/%e5%b0%91%e5%a5%b3-zh/","n":"少女"}, +{"v":"/tag/%e5%b0%91%e5%a6%87-zh/","n":"少妇"}, +{"v":"/tag/%e5%b0%91%e5%a9%a6/","n":"少婦"}, +{"v":"/tag/%e5%b0%a4%e7%89%a9/","n":"尤物"}, +{"v":"/tag/%e5%b7%a8%e4%b9%b3-zh/","n":"巨乳"}, +{"v":"/tag/%e5%b7%a8%e4%b9%b3%ef%bc%8c%e4%b8%ad%e5%87%ba%ef%bc%8c%e5%b0%91%e5%a5%b3/","n":"巨乳,中出,少女"}, +{"v":"/tag/%e5%b7%a8%e4%b9%b3%ef%bc%8c%e8%ae%a1%e8%b0%8b%ef%bc%8c%e5%a4%a7%e8%b1%a1%e4%bc%a0%e5%aa%92/","n":"巨乳,计谋,大象传媒"}, +{"v":"/tag/%e5%b9%b3%e9%9d%a2/","n":"平面"}, +{"v":"/tag/%e5%bb%81%e6%89%80/","n":"廁所"}, +{"v":"/tag/%e5%bc%80%e5%8f%91/","n":"开发"}, +{"v":"/tag/%e5%bc%80%e5%bf%83%e9%ac%bc%e4%bc%a0%e5%aa%92/","n":"开心鬼传媒"}, +{"v":"/tag/%e5%bc%b7%e5%88%b6%e5%8f%a3%e4%ba%a4/","n":"強制口交"}, +{"v":"/tag/%e5%bc%ba%e4%b8%8a/","n":"强上"}, +{"v":"/tag/%e5%bc%ba%e5%a5%b8/","n":"强奸"}, +{"v":"/tag/%e5%bd%b1%e5%83%8f/","n":"影像"}, +{"v":"/tag/%e5%be%90%e5%8f%af%e5%ae%a3/","n":"徐可宣"}, +{"v":"/tag/%e5%be%a1%e5%a7%90-zh/","n":"御姐"}, +{"v":"/tag/%e5%be%ae%e4%b9%b3/","n":"微乳"}, +{"v":"/tag/%e5%bf%83%e8%90%b1/","n":"心萱"}, +{"v":"/tag/%e6%80%80%e5%ad%95/","n":"怀孕"}, +{"v":"/tag/%e6%80%a7%e4%b8%ad%e5%9b%bd/","n":"性中国"}, +{"v":"/tag/%e6%80%a7%e6%84%9f/","n":"性感"}, +{"v":"/tag/%e6%80%a7%e7%88%b1%ef%bc%8c%e9%a6%99%e8%95%89%ef%bc%8c%e7%be%8e%e5%a5%b3%ef%bc%8c%e5%8f%a3%e4%ba%a4%e3%80%82%e4%b8%ad%e5%9b%bd%ef%bc%8c%e5%a4%a7%e9%99%86/","n":"性爱,香蕉,美女,口交。中国,大陆"}, +{"v":"/tag/%e6%81%8b%e4%ba%ba/","n":"恋人"}, +{"v":"/tag/%e6%83%85%e4%ba%ba%e8%8a%82/","n":"情人节"}, +{"v":"/tag/%e6%83%85%e6%ac%b2/","n":"情欲"}, +{"v":"/tag/%e6%84%8f%e5%a4%96/","n":"意外"}, +{"v":"/tag/%e6%84%9b%e8%b1%86/","n":"愛豆"}, +{"v":"/tag/%e6%88%9a%e5%b0%8f%e6%80%9c/","n":"戚小怜"}, +{"v":"/tag/%e6%88%b4%e6%8b%89%e6%8b%89/","n":"戴拉拉"}, +{"v":"/tag/%e6%8a%96%e9%9f%b3/","n":"抖音"}, +{"v":"/tag/%e6%8a%a4%e5%a3%ab/","n":"护士"}, +{"v":"/tag/%e6%8c%89%e6%91%a9/","n":"按摩"}, +{"v":"/tag/%e6%8c%89%e6%91%a9%e6%a3%92/","n":"按摩棒"}, +{"v":"/tag/%e6%8d%a2/","n":"换"}, +{"v":"/tag/%e6%8e%a8%e7%89%b9%e7%bd%91%e7%ba%a2/","n":"推特网红"}, +{"v":"/tag/%e6%8e%a8%e9%94%80%e5%91%98/","n":"推销员"}, +{"v":"/tag/%e6%91%84%e5%bd%b1%e5%b8%88/","n":"摄影师"}, +{"v":"/tag/%e6%91%a7%e6%af%81/","n":"摧毁"}, +{"v":"/tag/%e6%92%9e%e8%a6%8b/","n":"撞見"}, +{"v":"/tag/%e6%93%8d%e5%93%ad/","n":"操哭"}, +{"v":"/tag/%e6%94%b9%e7%bc%96/","n":"改编"}, +{"v":"/tag/%e6%96%91%e6%96%91/","n":"斑斑"}, +{"v":"/tag/%e6%96%b0%e5%b9%b4/","n":"新年"}, +{"v":"/tag/%e6%97%85%e6%b8%b8/","n":"旅游"}, +{"v":"/tag/%e6%97%a0%e5%a5%97-zh/","n":"无套"}, +{"v":"/tag/%e6%97%a0%e7%a0%81%e6%b5%81%e5%87%ba/","n":"无码流出"}, +{"v":"/tag/%e6%97%a5%e6%9c%ac/","n":"日本"}, +{"v":"/tag/%e6%97%a5%e6%9c%ac%e4%b8%9a%e4%bd%99/","n":"日本业余"}, +{"v":"/tag/%e6%97%a5%e6%9c%ac%e4%ba%ba-zh/","n":"日本人"}, +{"v":"/tag/%e6%97%a5%e6%9c%ac%e5%a4%a7%e4%b9%b3%e6%88%bf/","n":"日本大乳房"}, +{"v":"/tag/%e6%97%a5%e6%9c%ac%e5%a5%b3%e5%ad%a9/","n":"日本女孩"}, +{"v":"/tag/%e6%97%b6%e9%97%b4%e9%9d%99%e6%ad%a2/","n":"时间静止"}, +{"v":"/tag/%e6%97%b7%e8%af%be%ef%bc%8c%e8%80%81%e5%b8%88%ef%bc%8c%e7%9a%87%e5%ae%b6%e5%8d%8e%e4%ba%ba/","n":"旷课,老师,皇家华人"}, +{"v":"/tag/%e6%98%9f%e7%a9%ba/","n":"星空"}, +{"v":"/tag/%e6%98%9f%e7%a9%ba%e4%bc%a0%e5%aa%92/","n":"星空传媒"}, +{"v":"/tag/%e6%98%a5%e8%8a%82/","n":"春节"}, +{"v":"/tag/%e6%99%a8%e6%9b%a6/","n":"晨曦"}, +{"v":"/tag/%e6%9c%8d%e5%8a%a1/","n":"服务"}, +{"v":"/tag/%e6%9c%a6%e6%9c%a6/","n":"朦朦"}, +{"v":"/tag/%e6%9d%8e%e4%be%9d%e4%be%9d/","n":"李依依"}, +{"v":"/tag/%e6%9d%8e%e5%80%a9/","n":"李倩"}, +{"v":"/tag/%e6%9d%8e%e5%85%81%e7%86%99/","n":"李允熙"}, +{"v":"/tag/%e6%9d%8e%e5%a6%8d%e5%b8%8c/","n":"李妍希"}, +{"v":"/tag/%e6%9d%8e%e5%a8%9c%e5%a8%9c/","n":"李娜娜"}, +{"v":"/tag/%e6%9d%8e%e6%9b%bc%e5%a6%ae/","n":"李曼妮"}, +{"v":"/tag/%e6%9d%8e%e8%93%89%e8%93%89/","n":"李蓉蓉"}, +{"v":"/tag/%e6%9d%8f%e5%90%a7/","n":"杏吧"}, +{"v":"/tag/%e6%9e%81%e5%93%81/","n":"极品"}, +{"v":"/tag/%e6%9e%97%e5%ab%a3/","n":"林嫣"}, +{"v":"/tag/%e6%9e%97%e6%80%9d%e5%a6%a4/","n":"林思妤"}, +{"v":"/tag/%e6%9e%97%e8%a5%bf%e8%90%8c/","n":"林西萌"}, +{"v":"/tag/%e6%9e%9c%e5%86%bb%e4%bc%a0%e5%aa%92/","n":"果冻传媒"}, +{"v":"/tag/%e6%9e%9c%e5%86%bb%e4%bc%a0%e5%aa%92%ef%bc%8c%e5%b0%8f%e5%a5%b3%e5%ad%a9%ef%bc%8c%e5%ad%a6%e7%94%9f%ef%bc%8c%e7%be%8e%e5%a5%b3%ef%bc%8c%e4%b8%ad%e5%9b%bd%ef%bc%8c%e5%a4%a7%e9%99%86/","n":"果冻传媒,小女孩,学生,美女,中国,大陆"}, +{"v":"/tag/%e6%a0%a1%e6%9c%8d/","n":"校服"}, +{"v":"/tag/%e6%a2%81%e4%bd%b3%e8%8a%af/","n":"梁佳芯"}, +{"v":"/tag/%e6%a2%a6%e6%83%b3/","n":"梦想"}, +{"v":"/tag/%e6%a8%a1%e7%89%b9-zh/","n":"模特"}, +{"v":"/tag/%e6%a8%aa%e5%bc%80%e6%99%ba%e7%be%8e/","n":"横开智美"}, +{"v":"/tag/%e6%af%8d%e5%a5%b3/","n":"母女"}, +{"v":"/tag/%e6%af%8d%e5%ad%90/","n":"母子"}, +{"v":"/tag/%e6%af%92%e9%be%99/","n":"毒龙"}, +{"v":"/tag/%e6%b0%b4%e6%b5%92/","n":"水浒"}, +{"v":"/tag/%e6%b1%bd%e8%bb%8a/","n":"汽車"}, +{"v":"/tag/%e6%b2%99%e7%be%8e%e8%be%b0/","n":"沙美辰"}, +{"v":"/tag/%e6%b2%b9%e5%8e%8b/","n":"油压"}, +{"v":"/tag/%e6%b2%bb%e6%84%88-%e7%88%b1%e8%b1%86%e4%bc%a0%e5%aa%92/","n":"治愈 爱豆传媒"}, +{"v":"/tag/%e6%b7%98%e6%b0%94/","n":"淘气"}, +{"v":"/tag/%e6%b7%ab%e4%b9%b1/","n":"淫乱"}, +{"v":"/tag/%e6%b7%ab%e4%ba%82/","n":"淫亂"}, +{"v":"/tag/%e6%b7%ab%e5%a6%bb/","n":"淫妻"}, +{"v":"/tag/%e6%b7%ab%e8%8d%a1/","n":"淫荡"}, +{"v":"/tag/%e6%b7%b1%e5%85%a5/","n":"深入"}, +{"v":"/tag/%e6%b8%85%e7%ba%af-zh/","n":"清纯"}, +{"v":"/tag/%e6%b8%a9%e8%8a%ae%e6%ac%a3/","n":"温芮欣"}, +{"v":"/tag/%e6%ba%ab%e6%b3%89/","n":"溫泉"}, +{"v":"/tag/%e6%bc%82%e4%ba%ae%e7%9a%84%e5%a5%b3%e5%ad%a9/","n":"漂亮的女孩"}, +{"v":"/tag/%e6%bc%82%e4%ba%ae%e7%9a%84%e8%84%b8%e8%9b%8b/","n":"漂亮的脸蛋"}, +{"v":"/tag/%e6%bd%ae%e5%90%b9-zh/","n":"潮吹"}, +{"v":"/tag/%e6%bf%80%e6%83%85/","n":"激情"}, +{"v":"/tag/%e7%84%a1%e5%a5%97/","n":"無套"}, +{"v":"/tag/%e7%84%a6%e9%bb%9e%e5%82%b3%e5%aa%92/","n":"焦點傳媒"}, +{"v":"/tag/%e7%86%9f%e5%a5%b3-zh/","n":"熟女"}, +{"v":"/tag/%e7%88%86%e4%b9%b3/","n":"爆乳"}, +{"v":"/tag/%e7%88%86%e6%93%8d/","n":"爆操"}, +{"v":"/tag/%e7%88%b1%e8%b1%86/","n":"爱豆"}, +{"v":"/tag/%e7%88%b1%e8%b1%86%e4%bc%a0%e5%aa%92/","n":"爱豆传媒"}, +{"v":"/tag/%e7%88%b1%e8%b1%86%e4%bc%a0%e5%aa%92%ef%bc%8c%e8%85%b3%e4%ba%a4%ef%bc%8c%e9%bb%91%e7%b5%b2/","n":"爱豆传媒,腳交,黑絲"}, +{"v":"/tag/%e7%88%b6%e5%a5%b3/","n":"父女"}, +{"v":"/tag/%e7%88%b8%e5%8f%a3%e4%ba%a4/","n":"爸口交"}, +{"v":"/tag/%e7%88%b8%e7%88%b8/","n":"爸爸"}, +{"v":"/tag/%e7%89%b9%e5%86%99/","n":"特写"}, +{"v":"/tag/%e7%8b%97%e4%bb%94%e5%bc%8f/","n":"狗仔式"}, +{"v":"/tag/%e7%8b%ac%e5%ae%b6/","n":"独家"}, +{"v":"/tag/%e7%8b%ac%e6%b4%bb/","n":"独活"}, +{"v":"/tag/%e7%8c%ab%e7%88%aa%e5%bd%b1%e5%83%8f/","n":"猫爪影像"}, +{"v":"/tag/%e7%8c%ab%e7%88%aa%e5%bd%b1%e5%83%8f-%e7%9a%87%e5%ae%b6%e5%8d%8e%e4%ba%ba/","n":"猫爪影像 皇家华人"}, +{"v":"/tag/%e7%8c%ae%e8%ba%ab/","n":"献身"}, +{"v":"/tag/%e7%8d%a8%e5%ae%b6/","n":"獨家"}, +{"v":"/tag/%e7%90%aa%e7%90%aa/","n":"琪琪"}, +{"v":"/tag/%e7%91%9c%e4%bc%bd/","n":"瑜伽"}, +{"v":"/tag/%e7%94%9c%e7%94%9c/","n":"甜甜"}, +{"v":"/tag/%e7%95%87%e5%b8%8c/","n":"畇希"}, +{"v":"/tag/%e7%95%99%e6%a0%a1/","n":"留校"}, +{"v":"/tag/%e7%97%89%e6%8c%9b/","n":"痉挛"}, +{"v":"/tag/%e7%97%b4%e5%a5%b3/","n":"痴女"}, +{"v":"/tag/%e7%99%bd%e4%b8%9d-zh/","n":"白丝"}, +{"v":"/tag/%e7%99%bd%e5%85%81%e5%84%bf/","n":"白允儿"}, +{"v":"/tag/%e7%99%bd%e5%ab%a9/","n":"白嫩"}, +{"v":"/tag/%e7%99%bd%e8%99%8e-zh/","n":"白虎"}, +{"v":"/tag/%e7%99%bd%e8%99%8e%ef%bc%8c%e4%b8%ad%e6%96%87%e5%ad%97%e5%b9%95%ef%bc%8c%e7%9a%87%e5%ae%b6%e5%8d%8e%e4%ba%ba%ef%bc%8c%e5%a6%88%e5%a6%88%ef%bc%8c%e5%90%8c%e5%ad%a6/","n":"白虎,中文字幕,皇家华人,妈妈,同学"}, +{"v":"/tag/%e7%99%bd%e9%9c%b2/","n":"白露"}, +{"v":"/tag/%e7%99%bd%e9%b9%bf/","n":"白鹿"}, +{"v":"/tag/%e7%9a%87%e5%ae%b6%e5%8d%8e%e4%ba%ba/","n":"皇家华人"}, +{"v":"/tag/%e7%9a%87%e5%ae%b6%e5%8d%8e%e4%ba%ba%e4%bc%a0%e5%aa%92/","n":"皇家华人传媒"}, +{"v":"/tag/%e7%9b%b4%e6%92%ad/","n":"直播"}, +{"v":"/tag/%e7%9c%8b%e8%ad%b7/","n":"看護"}, +{"v":"/tag/%e7%9c%bc%e9%8f%a1%e5%a8%98/","n":"眼鏡娘"}, +{"v":"/tag/%e7%9f%ad%e9%ab%ae/","n":"短髮"}, +{"v":"/tag/%e7%a7%81%e6%88%bf/","n":"私房"}, +{"v":"/tag/%e7%a7%98%e4%b9%a6/","n":"秘书"}, +{"v":"/tag/%e7%b1%b3%e6%ac%a7/","n":"米欧"}, +{"v":"/tag/%e7%b2%89%e5%ab%a9/","n":"粉嫩"}, +{"v":"/tag/%e7%b2%be%e4%b8%9c%e5%bd%b1%e4%b8%9a/","n":"精东影业"}, +{"v":"/tag/%e7%b4%a0%e4%ba%ba-zh/","n":"素人"}, +{"v":"/tag/%e7%b5%95%e5%b0%8d%e9%a0%98%e5%9f%9f%e5%82%b3%e5%aa%92/","n":"絕對領域傳媒"}, +{"v":"/tag/%e7%b5%b2%e8%a5%aa/","n":"絲襪"}, +{"v":"/tag/%e7%b5%b2%e8%a5%aa%e6%83%85%e8%b6%a3/","n":"絲襪情趣"}, +{"v":"/tag/%e7%ba%a6%e7%82%ae-zh/","n":"约炮"}, +{"v":"/tag/%e7%ba%aa%e5%bd%95%e7%89%87/","n":"纪录片"}, +{"v":"/tag/%e7%bb%9d%e9%a1%b6/","n":"绝顶"}, +{"v":"/tag/%e7%bb%a7%e5%a6%b9-zh/","n":"继妹"}, +{"v":"/tag/%e7%bb%a7%e5%a7%90/","n":"继姐"}, +{"v":"/tag/%e7%bb%a7%e5%a7%90creampie-zh/","n":"继姐creampie"}, +{"v":"/tag/%e7%bb%a7%e6%af%8d/","n":"继母"}, +{"v":"/tag/%e7%bd%91%e7%ba%a2-zh/","n":"网红"}, +{"v":"/tag/%e7%be%8e%e4%b8%bd%e7%9a%84%e5%a5%b3%e5%ad%a9/","n":"美丽的女孩"}, +{"v":"/tag/%e7%be%8e%e4%b9%b3/","n":"美乳"}, +{"v":"/tag/%e7%be%8e%e5%a5%b3-zh/","n":"美女"}, +{"v":"/tag/%e7%be%8e%e5%b0%91%e5%a5%b3/","n":"美少女"}, +{"v":"/tag/%e7%be%8e%e5%b0%bb/","n":"美尻"}, +{"v":"/tag/%e7%be%8e%e7%a9%b4-zh/","n":"美穴"}, +{"v":"/tag/%e7%be%8e%e8%84%9a-zh/","n":"美脚"}, +{"v":"/tag/%e7%be%8e%e8%85%bf/","n":"美腿"}, +{"v":"/tag/%e7%be%8e%e8%87%80/","n":"美臀"}, +{"v":"/tag/%e7%be%a4%e4%ba%a4%e7%9b%9b%e5%ae%b4/","n":"群交盛宴"}, +{"v":"/tag/%e7%be%bd%e6%bf%91%e7%ba%b1%e7%bb%87/","n":"羽濑纱织"}, +{"v":"/tag/%e8%80%81%e5%85%ac/","n":"老公"}, +{"v":"/tag/%e8%82%89%e4%b8%9d/","n":"肉丝"}, +{"v":"/tag/%e8%83%8c%e5%be%8c%e4%bd%8d/","n":"背後位"}, +{"v":"/tag/%e8%85%b3%e4%ba%a4/","n":"腳交"}, +{"v":"/tag/%e8%87%aa%e5%88%b6-zh/","n":"自制"}, +{"v":"/tag/%e8%87%aa%e5%ae%85%ef%bc%8c%e8%af%b1%e6%83%91%ef%bc%8c%e6%8e%88%e8%af%be%ef%bc%8c%e6%95%99%e5%b8%88%ef%bc%8c%e5%a4%a7%e8%b1%a1%e4%bc%a0%e5%aa%92/","n":"自宅,诱惑,授课,教师,大象传媒"}, +{"v":"/tag/%e8%87%aa%e6%85%b0-zh/","n":"自慰"}, +{"v":"/tag/%e8%88%94%e5%a5%b6%e5%a4%b4/","n":"舔奶头"}, +{"v":"/tag/%e8%88%9e%e8%b9%88/","n":"舞蹈"}, +{"v":"/tag/%e8%89%b2%e6%8e%a7/","n":"色控"}, +{"v":"/tag/%e8%89%be%e5%b8%8c/","n":"艾希"}, +{"v":"/tag/%e8%89%be%e6%82%a0/","n":"艾悠"}, +{"v":"/tag/%e8%89%be%e7%86%99/","n":"艾熙"}, +{"v":"/tag/%e8%89%be%e7%8e%9b/","n":"艾玛"}, +{"v":"/tag/%e8%89%be%e9%b2%a4/","n":"艾鲤"}, +{"v":"/tag/%e8%8a%8a%e8%8a%8a/","n":"芊芊"}, +{"v":"/tag/%e8%8a%b1%e8%8a%b1/","n":"花花"}, +{"v":"/tag/%e8%8b%8f%e6%97%8b/","n":"苏旋"}, +{"v":"/tag/%e8%8b%8f%e7%92%87/","n":"苏璇"}, +{"v":"/tag/%e8%8b%8f%e7%95%85/","n":"苏畅"}, +{"v":"/tag/%e8%8b%8f%e8%89%be%e6%96%87/","n":"苏艾文"}, +{"v":"/tag/%e8%8b%8f%e8%af%ad%e6%a3%a0/","n":"苏语棠"}, +{"v":"/tag/%e8%8b%97%e6%a2%9d/","n":"苗條"}, +{"v":"/tag/%e8%8b%97%e8%8b%97/","n":"苗苗"}, +{"v":"/tag/%e8%8c%b6%e7%90%86/","n":"茶理"}, +{"v":"/tag/%e8%8e%89%e5%a8%9c/","n":"莉娜"}, +{"v":"/tag/%e8%8e%8e%e8%8e%8e/","n":"莎莎"}, +{"v":"/tag/%e8%90%8c%e5%a6%b9/","n":"萌妹"}, +{"v":"/tag/%e8%90%9d%e8%8e%89/","n":"萝莉"}, +{"v":"/tag/%e8%9c%9c%e6%a1%83/","n":"蜜桃"}, +{"v":"/tag/%e8%9c%9c%e6%a1%83%e4%bc%a0%e5%aa%92/","n":"蜜桃传媒"}, +{"v":"/tag/%e8%9c%9c%e6%a1%83%e4%bc%a0%e5%aa%92-%e8%9c%9c%e6%a1%83%e5%bd%b1%e5%83%8f/","n":"蜜桃传媒 蜜桃影像"}, +{"v":"/tag/%e8%9c%9c%e6%a1%83%e5%bd%b1%e5%83%8f/","n":"蜜桃影像"}, +{"v":"/tag/%e8%9c%9c%e6%a1%83%e5%bd%b1%e5%83%8f%e4%bc%a0%e5%aa%92/","n":"蜜桃影像传媒"}, +{"v":"/tag/%e8%9c%9c%e6%a1%83%e7%9a%84%e8%aa%98%e6%83%91/","n":"蜜桃的誘惑"}, +{"v":"/tag/%e8%9d%99%e8%9d%a0/","n":"蝙蝠"}, +{"v":"/tag/%e8%a5%bf%e8%88%94%e5%8f%96%e7%b2%be%e4%b9%8b%e5%a5%b3%e5%84%bf%e5%9b%bd/","n":"西舔取精之女儿国"}, +{"v":"/tag/%e8%a7%92%e8%89%b2%e6%89%ae%e6%bc%94-en-zh/","n":"角色扮演"}, +{"v":"/tag/%e8%a7%a3%e9%94%81/","n":"解锁"}, +{"v":"/tag/%e8%aa%bf%e6%95%99%e7%b3%bb%e5%88%97/","n":"調教系列"}, +{"v":"/tag/%e8%af%88%e9%aa%97%e6%8a%a5%e5%a4%8d/","n":"诈骗报复"}, +{"v":"/tag/%e8%af%95%e8%bd%a6/","n":"试车"}, +{"v":"/tag/%e8%af%b1%e6%83%91/","n":"诱惑"}, +{"v":"/tag/%e8%b0%83%e6%95%99/","n":"调教"}, +{"v":"/tag/%e8%b4%ab%e4%b9%b3/","n":"贫乳"}, +{"v":"/tag/%e8%b6%b3%e4%ba%a4/","n":"足交"}, +{"v":"/tag/%e8%b6%b3%e6%8e%a7-zh/","n":"足控"}, +{"v":"/tag/%e8%ba%ab%e4%bd%93/","n":"身体"}, +{"v":"/tag/%e8%bd%ae%e5%a5%b8/","n":"轮奸"}, +{"v":"/tag/%e8%bf%90%e5%8a%a8%e5%91%98/","n":"运动员"}, +{"v":"/tag/%e8%bf%91%e4%ba%b2/","n":"近亲"}, +{"v":"/tag/%e8%bf%b7%e4%bd%a0%e8%a3%99/","n":"迷你裙"}, +{"v":"/tag/%e9%81%8e%e8%86%9d%e8%a5%aa/","n":"過膝襪"}, +{"v":"/tag/%e9%87%87%e7%b2%be/","n":"采精"}, +{"v":"/tag/%e9%87%8e%e9%9d%99/","n":"野静"}, +{"v":"/tag/%e9%92%9f%e5%ae%9b%e5%86%b0/","n":"钟宛冰"}, +{"v":"/tag/%e9%94%80%e5%94%ae/","n":"销售"}, +{"v":"/tag/%e9%95%b7%e8%ba%ab/","n":"長身"}, +{"v":"/tag/%e9%96%a8%e5%af%86/","n":"閨密"}, +{"v":"/tag/%e9%97%ba%e8%9c%9c/","n":"闺蜜"}, +{"v":"/tag/%e9%98%b2%e6%b6%b2%e5%b0%88%e5%8d%80/","n":"防液專區"}, +{"v":"/tag/%e9%98%bf%e5%85%ac/","n":"阿公"}, +{"v":"/tag/%e9%99%88%e5%8f%af%e5%bf%83/","n":"陈可心"}, +{"v":"/tag/%e9%9b%a8%e8%92%99/","n":"雨蒙"}, +{"v":"/tag/%e9%9c%b2%e8%84%b8-zh/","n":"露脸"}, +{"v":"/tag/%e9%9f%a9%e5%9b%bd/","n":"韩国"}, +{"v":"/tag/%e9%a6%99%e6%b8%af-zh/","n":"香港"}, +{"v":"/tag/%e9%a6%99%e8%8f%b1/","n":"香菱"}, +{"v":"/tag/%e9%a6%99%e8%95%89/","n":"香蕉"}, +{"v":"/tag/%e9%a6%99%e8%95%89%e4%bc%a0%e5%aa%92/","n":"香蕉传媒"}, +{"v":"/tag/%e9%a6%99%e8%95%89%e5%82%b3%e5%aa%92/","n":"香蕉傳媒"}, +{"v":"/tag/%e9%a6%99%e8%95%89%e8%a7%86%e9%a2%91/","n":"香蕉视频"}, +{"v":"/tag/%e9%a8%8e%e4%b9%98%e4%bd%8d/","n":"騎乘位"}, +{"v":"/tag/%e9%a9%ac%e8%99%8e%e5%8f%a3%e4%ba%a4/","n":"马虎口交"}, +{"v":"/tag/%e9%aa%91%e4%b9%98/","n":"骑乘"}, +{"v":"/tag/%e9%aa%91%e4%b9%98%e4%bd%8d-zh/","n":"骑乘位"}, +{"v":"/tag/%e9%aa%9a%e8%b4%a7/","n":"骚货"}, +{"v":"/tag/%e9%ab%98%e4%b8%ad%e7%94%9f/","n":"高中生"}, +{"v":"/tag/%e9%ab%98%e6%b8%85/","n":"高清"}, +{"v":"/tag/%e9%ab%98%e6%bd%ae-zh/","n":"高潮"}, +{"v":"/tag/%e9%ab%98%e7%ab%af%e5%a4%96%e5%9b%b4/","n":"高端外围"}, +{"v":"/tag/%e9%ac%bc%e7%88%b6/","n":"鬼父"}, +{"v":"/tag/%e9%ba%bb%e8%b1%86-zh/","n":"麻豆"}, +{"v":"/tag/%e9%ba%bb%e8%b1%86%e4%bc%a0%e5%aa%92/","n":"麻豆传媒"}, +{"v":"/tag/%e9%ba%bb%e8%b1%86%e4%bc%a0%e5%aa%92%e6%98%a0%e7%94%bb/","n":"麻豆传媒映画"}, +{"v":"/tag/%e9%ba%bb%e8%b1%86%e4%bc%a0%e5%aa%92%e6%98%a0%e7%94%bb%ef%bc%8c%e5%a4%96%e5%9b%b4/","n":"麻豆传媒映画,外围"}, +{"v":"/tag/%e9%ba%bb%e8%b1%86%e4%bc%a0%e5%aa%92%e6%98%a0%e7%94%bb%ef%bc%8c%e6%80%a7%e6%84%9f%ef%bc%8c%e4%ba%ba%e5%a6%bb%ef%bc%8c%e7%be%8e%e4%b9%b3/","n":"麻豆传媒映画,性感,人妻,美乳"}, +{"v":"/tag/%e9%ba%bb%e8%b1%86%e5%82%b3%e5%aa%92/","n":"麻豆傳媒"}, +{"v":"/tag/%e9%bb%91%e4%b8%9d-zh/","n":"黑丝"}, +{"v":"/tag/%e9%bb%91%e4%b8%9d%e5%a4%a7/","n":"黑丝大"}, +{"v":"/tag/%e9%bb%91%e7%b5%b2/","n":"黑絲"} + +]}, +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/onlyfans-zh/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/中出/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/中国-zh/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/人妻/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/制服诱惑/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/国产/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/多p/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/女友/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/巨乳/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/无码/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/jav-zh/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/未分类/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/欧美/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +], +"/category/素人/":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"latest","n":"最新"}, + {"v":"most-viewed","n":"最受欢迎"}, + {"v":"longest","n":"最长"}, + {"v":"random","n":"随机的"} +]} +] + + +}, + +"分析MacPlayer": "0", +"是否开启手动嗅探": "1", +"手动嗅探视频链接关键词": ".m3u8#.mp4", +"手动嗅探视频链接过滤词": "baidu.com" +} \ No newline at end of file diff --git a/lib/91视频.json b/lib/91视频.json new file mode 100644 index 0000000..e6b4d36 --- /dev/null +++ b/lib/91视频.json @@ -0,0 +1,15 @@ +{ + "主页url": "https://yi.yirensp.fun/", + "二次截取": "&&&&", + "图片": "data-src=\"&&\"", + "标题": "title=\"&&\"", + "副标题": "🔥", + "链接": "href=\"&&\"", + "简介": "description\" content=\"&&\"", + "分类url": "https://yi.yirensp.fun/type/{cateId}-{catePg}.html;;z", + "分类": "奶香香资源$1#日韩无码$2#中文字幕$3#AV解说$4#换脸明星$5#国产大制作$6#嫖妓全过程$7#黑料不打烊$8#国产自拍$9#主播诱惑$10#探花约炮$11#偷拍偷窥$12#网曝吃瓜$13#抖阴短片$14#传媒剧情$15#日韩主播$16#强奸乱伦$20#女优明星$21#欧美激情$22#重口激情$23#三级伦理$24#探探资源$29#精品推荐$30#国产视频$31#主播直播$32#日本无码$33#日本有码$34#中文字幕$35#巨乳美乳$36#熟女人妻$37#强奸乱伦$38#欧美精品$39#少女萝莉$40#三级伦理$41#成人动漫$42#制服丝袜$43#角色扮演$44#口交颜射$45#自拍偷拍$46#大地资源$47#日韩无码$48#强奸乱伦$49#欧美精品$50#国产精品$51#人妻系列$52#中文字幕$53#动漫精品$54#伦理片$55#日韩精品$56#制服诱惑$57#自拍偷拍$58#AV明星$59#3P合$60#巨乳系列$61#颜射系列$62#口交视频$63#自慰系列$64#SM重口$65#教师学生$66#大秀视频$67#色猫资源$68#国产自拍$69#日本无码$70#日本有码$71#中文字幕$72#欧美精品$73#成人动漫$74#日本素人$75#高清名优$76#三级伦理$77#网红主播$78#映画传媒$79#人妻熟女$80#口爆颜射$81#萝莉少女$82#SM调教$83#美乳巨乳$84#短视频$85#制服诱惑$86#女同制服$87#AI换脸$88#老色B资源$96#亚洲有码$97#亚洲无码$98#制服诱惑$99#强奸乱伦$100#巨乳美乳$101#AI换脸$102#中文字幕$103#角色扮演$104#日本女优$105#成人动漫$106#欧美激情$107#三级片$108#网曝视频$109#AV解说$110#国产传媒$111#主播直播$112#国产精品$113#国产探花$114#鲨鱼资源$115#国产情色$116#日本无码$117#AV明星$118#中文字幕$119#网红主播$120#成人动漫$121#欧美情色$122#国模私拍$123#长腿丝袜$124#邻家人妻$125#韩国伦理$126#香港伦理$127#精品推荐$128#乐播资源$129#亚洲情色$130#国产主播$131#国产自拍$132#无码专区$133#欧美性爱$134#熟女人妻$135#强奸乱伦$136#巨乳美乳$137#中文字幕$138#制服诱惑$139#女同性恋$140#卡通动画$141#视频伦理$142#少女萝莉$143#重口色情$144#人兽性交$145#福利姬$201#黄瓜资源$146#国产精品$147#绿帽淫妻$148#国产探花$149#国产乱伦$150#美女主播$151#明星淫梦$152#TS人妖$153#香港三级$154#麻豆传媒$155#杏吧传媒$156#兔子先生$157#天美传媒$158#SA国际传媒$159#性世界$160#扣扣传媒$161#果冻传媒$162#星空无限$163#精东影业$164#葫芦影业$165#蜜桃传媒$166#小说专区$181#学生校园$182#玄幻仙侠$183#明星偶像$184#生活都市$185#不伦恋情$186#经验故事$187#科学幻想$188#暴力虐待$189#", + "分类二次截取": "div class=\"menu clearfix\">&&", + "分类数组": "", + "分类标题": ">&&&&", + "图片": "data-src=\"&&\"", + "标题": "title=\"&&\"", + "链接": "href=\"&&\"[替换:detail>>play#.html>>/sid/1/nid/1.html]", + "分类url": "https://wwww.cqifei.my/index.php/vod/type/id/{cateId}/page/{catePg}.html;;z", + "分类二次截取": "menu clearfix&&wrap pre", + "分类数组": "", + "分类标题": ">&&", + "标题": "title=\"&&\"", + "图片": "data-original=\"&&\"", + "副标题": "

&&", + "导演": "黑哥传媒", + "主演": "", + "简介": "👶黑哥传媒介绍:+片名:&&", + "线路二次截取": "", + "线路数组": "", + "线路标题": "👶+", + "播放二次截取": "", + "播放数组": "detail-play-list&&", + "播放列表": "", + "播放标题": ">&&<", + "播放链接": "href=\"&&\"", + "解析": "", + "直接播放": "0", + "播放请求头": "", + "嗅探词": ".mp4#.m3u8", + "过滤词": "", + "跳转播放链接": "var player_*url\":\"&&\"", + "跳转解析": "", + "搜索请求头": "User-Agent$MOBILE_UA", + "搜索url": "https://admin.941cad.cc/bin/index.php/vod/search/page/{pg}/wd/{wd}.html", + "搜索模式": "1", + "搜索后缀": "", + "搜索二次截取": "", + "搜索数组": "thumbnail\"&&", + "搜索标题": "title=\"&&\"", + "搜索图片": "data-original=\"&&\"", + "搜索副标题": "

&&&&", + "直接播放": "1", + "图片": "data-original=\"&&\"", + "标题": "title=\"&&\"", + "副标题": "text-bg-r\">&&", + "链接": "https://www.avdg.xyz/vodplay/+href=\"/voddetail/&&.html\"+-1-1.html", + "简介": "description\" content=\"&&\"", + "搜索模式": "1", + "搜索url": "https://www.avdg.xyz/vodsearch/{wd}----------{pg}---.html", + "分类url": "https://www.avdg.xyz/vodtype/{cateId}-{catePg}.html", + "分类": "视频一区$43#视频二区$62#视频三区$1#视频四区$93#视频五区$102", + "类型": "明星换脸$9#国产传媒$47#国产主播$48#网曝黑料$49#口交颜射$50#可爱学生$54#野外露出$57||日本无码$31#VR视角$38#91探花$63#兽耳系列$64#多人多P$65#主播直播$66#古装扮演$69#风情旗袍$70||国产视频$6#素人自拍$7#国产主播$8#极品媚黑$11#网曝黑料$12#网红头条$13#巨乳美乳$46#Cosplay$85||精品推荐$94#国产色情$95#瑜伽裤$96#过膝袜$97#网红流出$98#R星传媒$99#女同性恋$100#台湾辣妹$101||唯美港姐$103#SM调教$104#萝莉少女$105#日本动漫$106#强奸乱伦$107#欧美无码$108#女优明星$109#人妖系列$110" +} \ No newline at end of file diff --git a/lib/Aoki.jar b/lib/Aoki.jar new file mode 100644 index 0000000..9b764ac Binary files /dev/null and b/lib/Aoki.jar differ diff --git a/lib/Aress.json b/lib/Aress.json new file mode 100644 index 0000000..6aaf928 --- /dev/null +++ b/lib/Aress.json @@ -0,0 +1,18 @@ +{ + "作者": "Aries", + "站名": "", + "请求头": "User-Agent$MOBILE_UA", + "编码": "UTF-8", + "图片代理": "0", + "主页url": "https://av01.club/zh/", + "首页": "120", + "起始页": "1", + "分类url": "https://av01.club/zh/{cateId}?page={catePg};;z", + "分类": "有码$censored#无码$uncensored#欧美$western#FC2$fc2#动漫$hanime#国产$chinese", + "二次截取": "", + "数组": "class=\"card-img-top embed-responsive-item lazyload\"&&div class=\"video-list-item-tag-wrapper\"", + "标题": "title=\"&&\"", + "图片": "data-src=\"&&\"", + "副标题": "title=\"&&\"", + "链接": "href=\"&&\"" +} diff --git a/lib/Aries.json b/lib/Aries.json new file mode 100644 index 0000000..1095a82 --- /dev/null +++ b/lib/Aries.json @@ -0,0 +1,16 @@ +{ + "作者": "Aries", + "站名": "https://www.fullhd.xxx/zh/", + "请求头": "User-Agent$MOBILE_UA", + "编码": "UTF-8", + "主页url": "https://www.fullhd.xxx/zh/", + "首页": "120", + "起始页": "1", + "分类url": "https://www.fullhd.xxx/zh/networks/{cateId}/{catePg}.html;;z", + "分类": "Brazzers$brazzers-com#MYLF$mylf-com#BLACKED$blacked#Team Skeet$teamskeet-com#Bangbros$bangbros#Nubiles Porn$nubiles-porn-com#Adult Time$adult-time#TUSHY$tushy-com#Private$private#Woodman Casting$woodman-casting#Naughty America$naughtyamerica-com#Mom Lover$mom-lover#Reality Kings$rk-com#MOFOS$mofos-com", + "数组": "class=\"item\"&&

", + "标题": "title=\"&&\"", + "图片": "src=\"&&\"", + "副标题": "🌹+>&&<", + "链接": "href=\"&&\"" +} diff --git a/lib/Free.json b/lib/Free.json new file mode 100644 index 0000000..8553110 --- /dev/null +++ b/lib/Free.json @@ -0,0 +1,25 @@ +{ + "作者": "", + "站名": "", + "请求头": "User-Agent$MOBILE_UA", + "编码": "UTF-8", + "图片代理": "0", + "主页url": "https://www.camversity.com", + "首页": "120", + "起始页": "1", + "分类url": "https://www.camversity.com/{cateId}?p={catePg};;mrcd0", + "分类": "couples$couples#trans$trans#girls$girls#men$Guys", + "二次截取": "star&&previous page", + "数组": "", + "标题": "alt=\"&&\"", + "图片": "src=\"&&\"", + "副标题": "module__withEye--b3m0y\">&&<", + "链接": "href=\"&&\"", + "线路二次截取": "", + "直接播放": "1", + "播放请求头": "", + "嗅探词": "", + "过滤词": "", + "跳转播放链接": "", + "跳转解析": "" +} \ No newline at end of file diff --git a/lib/GDD视频.json b/lib/GDD视频.json new file mode 100644 index 0000000..8499587 --- /dev/null +++ b/lib/GDD视频.json @@ -0,0 +1,16 @@ +{ + "作者": "Aries", + "站名": "https://www.gdd5.quest/cn/home/web/", + "请求头": "User-Agent$MOBILE_UA", + "编码": "UTF-8", + "主页url": "https://www.gdd5.quest/cn/home/web/", + "首页": "120", + "起始页": "1", + "分类url": "https://www.gdd5.quest/cn/home/web/index.php/vod/type/id/{cateId}/page/{catePg}.html;;z", + "分类": "女神学生$21#美女直播$22#人妻系列$23#强奸乱伦$24#自拍偷拍$25#制服诱惑$26#巨乳系列$27#自慰系列$28#国产视频$29#无码视频$30#有码视频$31#中文字幕$32#日韩精品$33#欧美精品$34#动漫精品$35#三级伦理$36", + "数组": "video\"&&", + "标题": "title=\"&&\"", + "图片": "src=\"&&\"", + "副标题": "✨+多看少撸管+✨", + "链接": "href=\"&&\"" +} diff --git a/lib/JAVSB.json b/lib/JAVSB.json new file mode 100644 index 0000000..cce4533 --- /dev/null +++ b/lib/JAVSB.json @@ -0,0 +1,10 @@ +{ + "主页url": "https://jav.sb/", + "直接播放": "1", + "数组": "class=\"relative aspect-w-16 aspect-h-9 rounded overflow-hidden shadow-lg\"&&", + "图片": "data-src=\"&&\"", + "标题": "alt=\"&&\"", + "链接": "href=\"&&\"", + "分类url": "https://jav.sb/javtype/{cateId}-{catePg}.html", + "分类": "日本有碼$Censored#日本無碼$Uncensored#FC2-PPV$FC2-PPV#無碼破解$Mosaic_Removed#中文字幕$CHN_SUB#MGS動画$MGS#寫真$Adult_IDOL#國產$Asian_Amateur" + } \ No newline at end of file diff --git a/lib/airav.json b/lib/airav.json new file mode 100644 index 0000000..51dcddb --- /dev/null +++ b/lib/airav.json @@ -0,0 +1,188 @@ +{ +// +//回家地址 → https://airav.io/数字改 +//https://airav.io/ +"规则名": "airAV-XYQHiker", +"规则作者": "飞鱼", +"请求头参数": "手机", +"网页编码格式": "UTF-8", +"图片是否需要代理": "0", +"是否开启获取首页数据": "1", +"首页推荐链接": "https://airav.io", +"首页列表数组规则": ".row-cols-2", + //"首页列表数组规则": "body", +"首页片单列表数组规则": ".col oneVideo", + //"首页片单列表数组规则": ".m_vedio", +"首页片单是否Jsoup写法": "1", +"首页片单标题": "a&&alt", +"首页片单链接": "a&&href", +"首页片单图片": "img[src*=storage]&&src", +"首页片单副标题": "'👁️'+.click_count&&Text", +"首页片单链接加前缀": "https://airav.io", +"首页片单链接加后缀": "", +"分类起始页码": "1", +//"分类链接": "https://hscangku.com/vodshow/{cateId}-{catePg}/", +"分类链接": "https://airav.io/list?idx={catePg}&sort={cateId}", +"分类名称": "最作上市&发行日&今日热门&本周热门&本月热门&总排行", +"分类名称替换词": "1&2&3&4&5&6", +"分类截取模式": "1", +"分类列表数组规则": "body&&.oneVideo:has(img)", +"分类片单是否Jsoup写法": "1", +"分类片单标题": "h5&&Text", +"分类片单链接": "a&&href", +"分类片单图片": "img[src*=storage]&&src", +"分类片单副标题": "'👁️'+p,0&&Text+'❤️'+p,1&&Text", + +"分类片单链接加前缀": "https://airav.io", +"分类片单链接加后缀": "", +"搜索请求头参数": "User-Agent$手机", +"搜索链接": "https://airav.io/index.aspx?search_type=1&kw={wd}", +"POST请求数据": "", +"搜索截取模式": "1", +"搜索列表数组规则": "body&&.m_vedio", +"搜索片单是否Jsoup写法": "1", +"搜索片单图片": "img[src*=storage]&&src", +"搜索片单标题": "h3&&a&&Text", +"搜索片单链接": "a&&href", +"搜索片单副标题": "'👁️'+.click_count&&Text", +"搜索片单链接加前缀": "", +"搜索片单链接加后缀": "", +"链接是否直接播放": "1", +"直接播放链接加前缀": "", +"直接播放链接加后缀": "", +"直接播放直链视频请求头": "", + "详情是否Jsoup写法":"0", + "类型详情": "

類型:&&

", + "年代详情": "

更新:&&

", + "地区详情": "", + "演员详情": "", + "简介详情": "", + "线路列表数组规则": ".play-btn-group&&.line", + "线路标题": "'📽️'+a&&Text+'📺'", + "播放列表数组规则": ".line", + "选集列表数组规则": "a", + "选集标题链接是否Jsoup写法":"1", + "选集标题": "a&&Text", + "选集链接": "a&&href", + "是否反转选集序列": "0", + "选集链接加前缀": "https://airav.io", + "选集链接加后缀": "", + +"筛选数据":{ +"":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"status=1":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"status=2":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"status=3":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"status=4":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"status=1003":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"status=6":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"status=7":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"status=8":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"status=9":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"Search=無碼":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +], +"Search=偷拍":[ +{"key":"by", + "name":"排序", + "value":[ + {"v":"dateproduce","n":"最新"}, + {"v":"Playon","n":"热门"}, + {"v":"dateupload","n":"更新"} +]} +] + + +}, + +"分析MacPlayer": "0", +"是否开启手动嗅探": "1", +"手动嗅探视频链接关键词": ".m3u8#.mp4", +"手动嗅探视频链接过滤词": "baidu.com" +} diff --git a/lib/apiv1125好色™ Tv.py b/lib/apiv1125好色™ Tv.py new file mode 100644 index 0000000..56c6087 --- /dev/null +++ b/lib/apiv1125好色™ Tv.py @@ -0,0 +1,533 @@ +import re +import sys +import urllib.parse +import threading +import time +import requests +from pyquery import PyQuery as pq + +sys.path.append('..') +from base.spider import Spider + +class Spider(Spider): + def __init__(self): + # 基础配置 + self.name = '好色TV(优)' + self.host = 'https://hsex.icu/' + self.candidate_hosts = [ + "https://hsex.icu/", + "https://hsex1.icu/", + "https://hsex.tv/" + ] + self.headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Referer': self.host + } + self.timeout = 5000 + + # 分类映射(关键修复:视频分类url_suffix设为空,适配list-{pg}.htm格式) + self.class_map = { + '视频': {'type_id': 'list', 'url_suffix': ''}, # 修复点1:视频分类后缀为空 + '周榜': {'type_id': 'top7', 'url_suffix': 'top7'}, + '月榜': {'type_id': 'top', 'url_suffix': 'top'}, + '5分钟+': {'type_id': '5min', 'url_suffix': '5min'}, + '10分钟+': {'type_id': 'long', 'url_suffix': 'long'} + } + + def getName(self): + return self.name + + def init(self, extend=""): + # 尝试获取最快可用域名 + self.host = self.get_fastest_host() + self.headers['Referer'] = self.host + + def isVideoFormat(self, url): + if not url: + return False + return any(fmt in url.lower() for fmt in ['.mp4', '.m3u8', '.flv', '.avi']) + + def manualVideoCheck(self): + def check(url): + if not self.isVideoFormat(url): + return False + try: + resp = self.fetch(url, headers=self.headers, method='HEAD', timeout=3) + return resp.status_code in (200, 302) and 'video' in resp.headers.get('Content-Type', '') + except: + return False + return check + + def get_fastest_host(self): + """测试候选域名,返回最快可用的""" + results = {} + threads = [] + + def test_host(url): + try: + start_time = time.time() + resp = requests.head(url, headers=self.headers, timeout=2, allow_redirects=False) + if resp.status_code in (200, 301, 302): + delay = (time.time() - start_time) * 1000 + results[url] = delay + else: + results[url] = float('inf') + except: + results[url] = float('inf') + + for host in self.candidate_hosts: + t = threading.Thread(target=test_host, args=(host,)) + threads.append(t) + t.start() + for t in threads: + t.join() + + valid_hosts = [(h, d) for h, d in results.items() if d != float('inf')] + return valid_hosts[0][0] if valid_hosts else self.candidate_hosts[0] + + def homeContent(self, filter): + result = {} + # 构造分类列表 + classes = [] + for name, info in self.class_map.items(): + classes.append({ + 'type_name': name, + 'type_id': info['type_id'] + }) + result['class'] = classes + + try: + # 获取首页内容 + html = self.fetch_with_retry(self.host, retry=2, timeout=5).text + data = pq(html) + + # 提取视频列表 + vlist = [] + items = data('.row .col-xs-6.col-md-3') + for item in items.items(): + try: + title = item('h5').text().strip() + if not title: + continue + + # 提取图片URL + style = item('.image').attr('style') or '' + pic_match = re.search(r'url\(["\']?([^"\']+)["\']?\)', style) + vod_pic = pic_match.group(1) if pic_match else '' + if vod_pic and not vod_pic.startswith('http'): + vod_pic = f"{self.host.rstrip('/')}/{vod_pic.lstrip('/')}" + + # 提取时长备注 + desc = item('.duration').text().strip() or '未知' + + # 提取视频ID + href = item('a').attr('href') or '' + if not href: + continue + vod_id = href.split('/')[-1] + if not vod_id.endswith('.htm'): + vod_id += '.htm' + + vlist.append({ + 'vod_id': vod_id, + 'vod_name': title, + 'vod_pic': vod_pic, + 'vod_remarks': desc + }) + except Exception as e: + print(f"解析首页视频项失败: {e}") + continue + + result['list'] = vlist + except Exception as e: + print(f"首页解析失败: {e}") + result['list'] = [] + return result + + def homeVideoContent(self): + return [] + + def categoryContent(self, tid, pg, filter, extend): + result = {} + try: + # 匹配分类信息 + cate_info = None + for name, info in self.class_map.items(): + if info['type_id'] == tid: + cate_info = info + break + + if not cate_info: + result['list'] = [] + return result + + # 关键修复:区分视频分类与其他分类的URL格式 + if tid == 'list': # 视频分类(type_id为list) + url = f"{self.host}list-{pg}.htm" # 格式:list-1.htm、list-2.htm + else: # 其他分类(周榜/月榜等):xxx_list-{pg}.htm + url = f"{self.host}{cate_info['url_suffix']}_list-{pg}.htm" + + # 请求分类页 + html = self.fetch(url, headers=self.headers, timeout=8).text + html = html.encode('utf-8', errors='ignore').decode('utf-8') + data = pq(html) + + # 提取视频列表 + vlist = [] + items = data('.row .col-xs-6.col-md-3') + for item in items.items(): + try: + title = item('h5').text().strip() + if not title: + continue + + style = item('.image').attr('style') or '' + pic_match = re.search(r'url\(["\']?([^"\']+)["\']?\)', style) + vod_pic = pic_match.group(1) if pic_match else '' + if vod_pic and not vod_pic.startswith('http'): + vod_pic = f"{self.host.rstrip('/')}/{vod_pic.lstrip('/')}" + + desc = item('.duration').text().strip() or '未知' + + href = item('a').attr('href') or '' + if not href: + continue + vod_id = href.split('/')[-1] + if not vod_id.endswith('.htm'): + vod_id += '.htm' + + vlist.append({ + 'vod_id': vod_id, + 'vod_name': title, + 'vod_pic': vod_pic, + 'vod_remarks': desc + }) + except Exception as e: + print(f"解析分类视频项失败: {e}") + continue + + # 提取总页数 + pagecount = 1 + try: + pagination = data('.pagination1 li a') + page_nums = [] + for a in pagination.items(): + text = a.text().strip() + if text.isdigit(): + page_nums.append(int(text)) + if page_nums: + pagecount = max(page_nums) + except: + pagecount = 1 + + result['list'] = vlist + result['page'] = pg + result['pagecount'] = pagecount + result['limit'] = len(vlist) + result['total'] = 999999 + except Exception as e: + print(f"分类解析失败: {e}") + result['list'] = [] + result['page'] = pg + result['pagecount'] = 1 + result['limit'] = 0 + result['total'] = 0 + return result + + def detailContent(self, ids): + try: + if not ids or not ids[0]: + return {'list': []} + + vod_id = ids[0].strip() + if not vod_id.endswith('.htm'): + vod_id += '.htm' + url = f"{self.host}{vod_id.lstrip('/')}" + + html = self.fetch_with_retry(url, retry=2, timeout=8).text + html = html.encode('utf-8', errors='ignore').decode('utf-8') + data = pq(html) + + # 提取标题 + title = data('.panel-title, .video-title, h1').text().strip() or '未知标题' + + # 提取封面图 + vod_pic = '' + poster_style = data('.vjs-poster').attr('style') or '' + pic_match = re.search(r'url\(["\']?([^"\']+)["\']?\)', poster_style) + if pic_match: + vod_pic = pic_match.group(1) + if not vod_pic: + vod_pic = data('.video-pic img, .vjs-poster img, .thumbnail img').attr('src') or '' + if vod_pic and not vod_pic.startswith('http'): + vod_pic = f"{self.host}{vod_pic.lstrip('/')}" + + # 提取时长和观看量 + duration = '未知' + views = '未知' + info_items = data('.panel-body .col-md-3, .video-info .info-item, .info p') + for item in info_items.items(): + text = item.text().strip() + if '时长' in text or 'duration' in text.lower(): + duration = text.replace('时长:', '').replace('时长', '').strip() + elif '观看' in text or 'views' in text.lower(): + views_match = re.search(r'(\d+\.?\d*[kK]?)次观看', text) + if views_match: + views = views_match.group(1) + else: + views = text.replace('观看:', '').replace('观看', '').strip() + remarks = f"{duration} | {views}" + + # 提取播放地址 + video_url = '' + m3u8_match = re.search(r'videoUrl\s*=\s*["\']([^"\']+\.m3u8)["\']', html) + if m3u8_match: + video_url = m3u8_match.group(1) + if not video_url: + source = data('source[src*=".m3u8"], source[src*=".mp4"]') + video_url = source.attr('src') or '' + if not video_url: + js_matches = re.findall(r'(https?://[^\s"\']+\.(?:m3u8|mp4))', html) + if js_matches: + video_url = js_matches[0] + + if video_url and not video_url.startswith('http'): + video_url = f"{self.host}{video_url.lstrip('/')}" + + vod = { + 'vod_id': vod_id, + 'vod_name': title, + 'vod_pic': vod_pic, + 'vod_remarks': remarks, + 'vod_play_from': '好色TV(优)', + 'vod_play_url': f'正片${video_url}' if video_url else '正片$暂无地址' + } + return {'list': [vod]} + except Exception as e: + print(f"详情解析失败: {e}") + return {'list': []} + + def searchContent(self, key, quick, pg=1): + try: + # 关键词合法性校验 + if not key.strip(): + print("搜索关键词不能为空") + return {'list': [], 'page': int(pg), 'pagecount': 1, 'limit': 0, 'total': 0} + + # 编码关键词 + encoded_key = urllib.parse.quote(key.strip(), encoding='utf-8', errors='replace') + + # 构造搜索URL + search_url = f"{self.host}search.htm" + params = { + 'search': encoded_key, + 'page': int(pg) + } + + # 发起请求 + resp = self.fetch( + url=search_url, + headers=self.headers, + params=params, + timeout=8 + ) + if resp.status_code not in (200, 302): + print(f"搜索页面请求失败,URL:{resp.url},状态码:{resp.status_code}") + return {'list': [], 'page': int(pg), 'pagecount': 1, 'limit': 0, 'total': 0} + + # 处理页面内容 + html = resp.text.encode('utf-8', errors='ignore').decode('utf-8') + data = pq(html) + + # 检测无结果场景 + no_result_texts = ['没有找到相关视频', '无搜索结果', 'No results found', '未找到匹配内容'] + no_result = any(data(f'div:contains("{text}"), p:contains("{text}")').text() for text in no_result_texts) + if no_result: + print(f"搜索关键词「{key}」第{pg}页无结果") + return {'list': [], 'page': int(pg), 'pagecount': 1, 'limit': 0, 'total': 0} + + # 解析搜索结果 + vlist = [] + items = data('.row .col-xs-6.col-md-3') + for item in items.items(): + try: + title = item('h5').text().strip() + if not title: + continue + + style = item('.image').attr('style') or '' + pic_match = re.search(r'url\(["\']?([^"\']+)["\']?\)', style) + vod_pic = pic_match.group(1) if pic_match else '' + if vod_pic and not vod_pic.startswith(('http://', 'https://')): + vod_pic = f"{self.host.rstrip('/')}/{vod_pic.lstrip('/')}" + + desc = item('.duration').text().strip() or '未知时长' + + href = item('a').attr('href') or '' + if not href: + continue + vod_id = href.split('/')[-1] + if not vod_id.endswith('.htm'): + vod_id += '.htm' + + vlist.append({ + 'vod_id': vod_id, + 'vod_name': title, + 'vod_pic': vod_pic, + 'vod_remarks': desc + }) + except Exception as e: + print(f"解析单条搜索结果失败:{e}(跳过该条)") + continue + + # 解析总页数 + pagecount = 1 + try: + pagination = data('.pagination1 li a') + page_nums = [] + for a in pagination.items(): + text = a.text().strip() + if text.isdigit(): + page_nums.append(int(text)) + if page_nums: + pagecount = max(page_nums) + print(f"搜索关键词「{key}」分页解析完成,共{pagecount}页") + except Exception as e: + print(f"解析分页失败(默认单页):{e}") + pagecount = 1 + + # 返回结果(修复点2:补全page键的引号,修正语法错误) + total = len(vlist) * pagecount + print(f"搜索关键词「{key}」第{pg}页处理完成,结果{len(vlist)}条,总页数{pagecount}") + return { + 'list': vlist, + 'page': int(pg), # 原代码此处缺少引号,导致语法错误 + 'pagecount': pagecount, + 'limit': len(vlist), + 'total': total + } + except Exception as e: + print(f"搜索功能整体异常:{e}") + return { + 'list': [], + 'page': int(pg), 'pagecount': 1, + 'limit': 0, + 'total': 0 + } + + def playerContent(self, flag, id, vipFlags): + headers = self.headers.copy() + headers.update({ + 'Referer': self.host, + 'Origin': self.host.rstrip('/'), + 'Host': urllib.parse.urlparse(self.host).netloc, + }) + + # 根据rule中的double设置 + return { + 'parse': 1, # 根据rule中的play_parse设置 + 'url': id, + 'header': headers, + 'double': True # 根据rule中的double设置 + } + + def localProxy(self, param): + try: + url = param['url'] + if url and not url.startswith(('http://', 'https://')): + url = f"{self.host.rstrip('/')}/{url.lstrip('/')}" + + img_headers = self.headers.copy() + img_headers.update({'Accept': 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8'}) + + res = self.fetch(url, headers=img_headers, timeout=10) + content_type = res.headers.get('Content-Type', 'image/jpeg') + + return [200, content_type, res.content] + except Exception as e: + print(f"图片代理失败: {e}") + return [200, 'image/jpeg', b''] + + def fetch_with_retry(self, url, retry=2, timeout=5): + for i in range(retry + 1): + try: + resp = self.fetch(f'https://vpsdn.leuse.top/proxy?single=true&url={urllib.parse.quote(url)}',headers=self.headers, timeout=timeout) + if resp.status_code in (200, 301, 302): + return resp + print(f"请求{url}返回状态码{resp.status_code},重试中...") + except Exception as e: + print(f"第{i+1}次请求{url}失败: {e}") + if i < retry: + time.sleep(0.5) + return type('obj', (object,), {'text': '', 'status_code': 404}) + + def fetch(self, url, headers=None, timeout=5, method='GET', params=None): + headers = headers or self.headers + params = params or {} + try: + if method.upper() == 'GET': + resp = requests.get( + f'https://vpsdn.leuse.top/proxy?single=true&url={urllib.parse.quote(url)}', + headers=headers, + timeout=timeout, + allow_redirects=True, + params=params # 支持GET请求带参数,适配搜索分页 + ) + elif method.upper() == 'HEAD': + resp = requests.head( + f'https://vpsdn.leuse.top/proxy?single=true&url={urllib.parse.quote(url)}', + headers=headers, + timeout=timeout, + allow_redirects=False, + params=params + ) + else: + resp = requests.get( # 默认GET请求,兼容其他方法调用 + f'https://vpsdn.leuse.top/proxy?single=true&url={urllib.parse.quote(url)}', + headers=headers, + timeout=timeout, + allow_redirects=True, + params=params + ) + # 自动适配编码,避免中文乱码 + if 'charset' in resp.headers.get('Content-Type', '').lower(): + resp.encoding = resp.apparent_encoding + else: + resp.encoding = 'utf-8' + return resp + except Exception as e: + print(f"网络请求失败({url}): {e}") + # 返回统一格式空响应,避免后续逻辑崩溃 + return type('obj', (object,), { + 'text': '', + 'status_code': 500, + 'headers': {}, + 'url': url + }) + + +# ------------------------------ +# 可选测试代码(运行时注释或删除,用于验证功能) +# ------------------------------ +if __name__ == "__main__": + # 初始化爬虫 + spider = Spider() + spider.init() + + # 测试首页内容 + print("=== 测试首页 ===") + home_data = spider.homeContent(filter='') + print(f"首页分类数:{len(home_data['class'])}") + print(f"首页视频数:{len(home_data['list'])}") + + # 测试视频分类(修复后的数据获取) + print("\n=== 测试视频分类(第1页) ===") + cate_data = spider.categoryContent(tid='list', pg=1, filter='', extend='') + print(f"视频分类第1页视频数:{len(cate_data['list'])}") + print(f"视频分类总页数:{cate_data['pagecount']}") + + # 测试搜索功能(修复语法错误后) + print("\n=== 测试搜索(关键词:测试) ===") + search_data = spider.searchContent(key="测试", quick=False, pg=1) + print(f"搜索结果数:{len(search_data['list'])}") + print(f"搜索总页数:{search_data['pagecount']}") diff --git a/lib/apiv1265直播转点播.js b/lib/apiv1265直播转点播.js new file mode 100644 index 0000000..4b89f37 --- /dev/null +++ b/lib/apiv1265直播转点播.js @@ -0,0 +1,443 @@ +// JSON 解析错误:JSON语法结构存在错误,无法解析,以下为您输出接口原文。 + +var iil = "jsjiami.com.v6", + iil_ = ["iil"], + lIIIl1ll = [ + iil, + "\x6f\x6b\x68\x74\x74\x70\x2f\x33\x2e\x31\x35", + "\x69\x6e\x64\x65\x78\x4f\x66", + "\x24\x24\x24", + "\x73\x70\x6c\x69\x74", + "\x74\x72\x69\x6d", + "\x26\x26\x26", + "\x3a\x2f\x2f", + "\x6c\x6f\x67", + "\x70\x69\x63\x55\x72\x6c\x3a\x20", + "\x72\x65\x70\x6c\x61\x63\x65", + "\x70\x75\x73\x68", + "\x2f\x66\x69\x6c\x65\x2f\x6c\x69\x76\x65\x73\x6f\x75\x72\x63\x65\x6c\x69\x73\x74", + "\x2f\x6c\x69\x76\x65\x73\x6f\x75\x72\x63\x65\x6c\x69\x73\x74", + "\x47\x45\x54", + "\x70\x61\x72\x73\x65", + "\x63\x6f\x6e\x74\x65\x6e\x74", + "\x73\x75\x62\x73\x74\x72\x69\x6e\x67", + "\x6c\x61\x73\x74\x49\x6e\x64\x65\x78\x4f\x66", + "\x6e\x61\x6d\x65", + "\x75\x72\x6c", + "\x3d\x3d\x3d\x3d\x20\x3e\x3e\x3e\x20", + "\x73\x74\x72\x69\x6e\x67\x69\x66\x79", + "\x65\x78\x65\x63", + "\x74\x65\x73\x74", + "\x6d\x61\x74\x63\x68", + "\x63\x68\x61\x6e\x6e\x65\x6c", + "\x2c\x23\x67\x65\x6e\x72\x65\x23\x0a", + "\x75\x72\x6c\x73", + "\x64\x61\x74\x61", + "\x64\x61\x74\x61\x6c\x69\x73\x74", + "\x70\x72\x6f\x76", + "\x6c\x69\x73\x74", + "\x2d\x2d\x2d", + "\x6c\x69\x6e\x65", + "\x77\x65\x62\x50\x69\x63\x55\x72\x6c\x3a\x20", + "\x23\x45\x58\x54\x4d\x33\x55", + "\x22\x63\x68\x61\x6e\x6e\x65\x6c\x22", + "\x22\x75\x72\x6c\x73\x22", + "\x22\x64\x61\x74\x61\x6c\x69\x73\x74\x22", + "\x6c\x65\x6e\x67\x74\x68", + "\x23\x67\x65\x6e\x72\x65\x23", + "\x7b\x6e\x61\x6d\x65\x7d", + "\x7b\x63\x61\x74\x65\x7d", + "\u76f4\u64ad\u5217\u8868", + "\x6e\x75\x6c\x6c", + "\x74\x79\x70\x65\x5f\x69\x64", + "\x76\x6f\x64\x5f\x70\x6c\x61\x79\x5f\x75\x72\x6c", + "\x68\x61\x73\x4f\x77\x6e\x50\x72\x6f\x70\x65\x72\x74\x79", + "\x6a\x6f\x69\x6e", + "\x76\x6f\x64\x5f\x70\x6c\x61\x79\x5f\x66\x72\x6f\x6d", + "\x6a\x43\x50\x73\x4e\x6a\x77\x69\x4a\x61\x51\x6d\x69\x2e\x63\x6f\x4e\x4f\x6d\x47\x72\x2e\x76\x56\x36\x41\x46\x67\x79\x74\x74\x3d\x3d", + ]; +function Ii1l1III(_0x3b13df, _0x346a54) { + _0x3b13df = ~~"0x"["concat"](_0x3b13df["slice"](0x0)); + var _0x4db44b = lIIIl1ll[_0x3b13df]; + return _0x4db44b; +} +(function (_0x209161, _0x5eaa4a) { + var _0x42ecdf = 0x0; + for ( + _0x5eaa4a = _0x209161["shift"](_0x42ecdf >> 0x2); + _0x5eaa4a && + _0x5eaa4a !== + (_0x209161["pop"](_0x42ecdf >> 0x3) + "")["replace"]( + /[CPNwJQNOGrVAFgytt=]/g, + "" + ); + _0x42ecdf++ + ) { + _0x42ecdf = _0x42ecdf ^ 0x127efd; + } +})(lIIIl1ll, Ii1l1III); +let headers = { "User-Agent": Ii1l1III("0") }; +let classes = []; +let cates = {}; +let picUrl = ""; +let webPaths = {}; +function init(IiIIi1i) { + let i1Ii11I1 = ""; + if (IiIIi1i[Ii1l1III("1")](Ii1l1III("2")) > 0x0) { + i1Ii11I1 = IiIIi1i[Ii1l1III("3")](Ii1l1III("2"))[0x0][Ii1l1III("4")](); + IiIIi1i = IiIIi1i[Ii1l1III("3")](Ii1l1III("2"))[0x1][Ii1l1III("4")](); + } + if (IiIIi1i[Ii1l1III("1")](Ii1l1III("5")) > 0x0) { + picUrl = IiIIi1i[Ii1l1III("3")](Ii1l1III("5"))[0x1][Ii1l1III("4")](); + if (picUrl[Ii1l1III("1")](Ii1l1III("6")) < 0x0) { + picUrl = i1Ii11I1 + picUrl; + } + IiIIi1i = IiIIi1i[Ii1l1III("3")](Ii1l1III("5"))[0x0][Ii1l1III("4")](); + } + console[Ii1l1III("7")](Ii1l1III("8") + picUrl); + let IIlIlI1I = IiIIi1i[Ii1l1III("3")]("\x23"); + for (const IlII1I1 of IIlIlI1I) { + if (IlII1I1[Ii1l1III("1")]("\x24") > 0x0) { + let illIl111 = IlII1I1; + let Ill1iIi = IlII1I1[Ii1l1III("3")]("\x24")[0x0]; + if (illIl111[Ii1l1III("1")](Ii1l1III("6")) < 0x0) { + illIl111 = illIl111[Ii1l1III("9")]("\x24", "\x24" + i1Ii11I1); + } + classes[Ii1l1III("a")]({ + type_id: illIl111, + type_name: Ill1iIi[Ii1l1III("9")]("\x21\x21", ""), + }); + } else { + let II1lIlli = IlII1I1; + if (II1lIlli[Ii1l1III("1")](Ii1l1III("6")) < 0x0) { + II1lIlli = i1Ii11I1 + II1lIlli; + } + II1lIlli = II1lIlli[Ii1l1III("9")](Ii1l1III("b"), Ii1l1III("c")); + let Illi11ll = req(II1lIlli, { + "\x6d\x65\x74\x68\x6f\x64": Ii1l1III("d"), + "\x68\x65\x61\x64\x65\x72\x73": headers, + }); + try { + let l1lIiill = JSON[Ii1l1III("e")](Illi11ll[Ii1l1III("f")]); + let lillI11l = II1lIlli[Ii1l1III("10")]( + 0x0, + II1lIlli[Ii1l1III("11")]("\x2f") + 0x1 + ); + for (const i1iilII1 of l1lIiill) { + let Iillil = i1iilII1[Ii1l1III("12")]; + let lI1iIl = i1iilII1[Ii1l1III("13")]; + let illIl111 = + Iillil + + "\x24" + + (lI1iIl[Ii1l1III("1")](Ii1l1III("6")) < 0x0 ? lillI11l : "") + + lI1iIl; + classes[Ii1l1III("a")]({ + type_id: illIl111, + type_name: Iillil[Ii1l1III("9")]("\x21\x21", ""), + }); + webPaths[illIl111] = lillI11l; + } + } catch (Ii1Ii11) { + console[Ii1l1III("7")](Ii1l1III("14") + Ii1Ii11); + } + } + } +} +function home(I1iiIiIl) { + return JSON[Ii1l1III("15")]({ class: classes, filters: null }); +} +function parseM3u(iIi1Ii1I, I1IlIIIi) { + let iI1iiIii = {}; + let iiI11111 = /(#EXTINF:.+?),([^,]+?)\s*\n(.+?)\s*\n/g; + let ii1iilil = null; + while ((ii1iilil = iiI11111[Ii1l1III("16")](iIi1Ii1I)) != null) { + let lllli1iI = ii1iilil[0x1]; + let il1Ili1I = ii1iilil[0x2]; + let liIlll1l = ii1iilil[0x3]; + if ( + il1Ili1I == null || + liIlll1l == null || + il1Ili1I == "" || + liIlll1l == "" + ) { + continue; + } + il1Ili1I = il1Ili1I[Ii1l1III("4")](); + liIlll1l = liIlll1l[Ii1l1III("4")](); + let IiI1lI1l = I1IlIIIi; + let ilIl1i1i = /group-title="(.*?)"/; + if (ilIl1i1i[Ii1l1III("17")](lllli1iI)) { + IiI1lI1l = lllli1iI[Ii1l1III("18")](ilIl1i1i)[0x1]; + } + if (!iI1iiIii[IiI1lI1l]) { + iI1iiIii[IiI1lI1l] = []; + } + iI1iiIii[IiI1lI1l][Ii1l1III("a")](il1Ili1I + "\x2c" + liIlll1l); + } + let ll11III1 = ""; + for (const li1Ili in iI1iiIii) { + ll11III1 += li1Ili + "\x0a"; + let IlIil1ll = iI1iiIii[li1Ili]; + for (const li1iI11 of IlIil1ll) { + ll11III1 += li1iI11 + "\x0a"; + } + } + return ll11III1; +} +function parseFm(IliiIl1I) { + let lliiI1i1 = ""; + let Iii1ll = JSON[Ii1l1III("e")](IliiIl1I); + for (const i1lIlli1 of Iii1ll) { + let I111Il1l = i1lIlli1[Ii1l1III("12")]; + let ilI11li = i1lIlli1[Ii1l1III("19")]; + lliiI1i1 += I111Il1l + Ii1l1III("1a"); + for (const iiilI1iI of ilI11li) { + let I11111l1 = iiilI1iI[Ii1l1III("12")]; + let IlI1l1I1 = iiilI1iI[Ii1l1III("1b")]; + for (const l1II1lll of IlI1l1I1) { + lliiI1i1 += I11111l1 + "\x2c" + l1II1lll + "\x0a"; + } + } + } + return lliiI1i1; +} +function parseLu(iIliI1lI) { + let IIlilI1i = ""; + let I11ilI1i = JSON[Ii1l1III("e")](iIliI1lI)[Ii1l1III("1c")]; + for (const i1Ii1l1 of I11ilI1i[Ii1l1III("1d")]) { + let I11111l = i1Ii1l1[Ii1l1III("1e")]; + let IiIiii1l = i1Ii1l1[Ii1l1III("1f")]; + IIlilI1i += I11111l + Ii1l1III("1a"); + for (const l1111lI of IiIiii1l) { + let lIlI1iI = l1111lI[Ii1l1III("12")]; + let ll11i1II = l1111lI[Ii1l1III("1b")]; + for (const Iliilii of ll11i1II) { + IIlilI1i += + lIlI1iI + + Ii1l1III("20") + + Iliilii[Ii1l1III("21")] + + "\x2c" + + Iliilii[Ii1l1III("13")] + + "\x0a"; + } + } + } + return IIlilI1i; +} +function getCateData(IliI1i) { + let iI1I1I1I = picUrl; + if (IliI1i[Ii1l1III("1")](Ii1l1III("5")) > 0x0) { + iI1I1I1I = IliI1i[Ii1l1III("3")](Ii1l1III("5"))[0x1][Ii1l1III("4")](); + if (iI1I1I1I[Ii1l1III("1")](Ii1l1III("6")) < 0x0 && webPaths[IliI1i]) { + iI1I1I1I = webPaths[IliI1i] + iI1I1I1I; + } + IliI1i = IliI1i[Ii1l1III("3")](Ii1l1III("5"))[0x0][Ii1l1III("4")](); + } + console[Ii1l1III("7")](Ii1l1III("22") + iI1I1I1I); + let ll1iIiiI = IliI1i[Ii1l1III("3")]("\x24")[0x1]; + let i1I1l1i = IliI1i[Ii1l1III("3")]("\x24")[0x0]; + if (!cates[IliI1i]) { + cates[IliI1i] = []; + let iIl11Iii = headers; + if (ll1iIiiI[Ii1l1III("1")]("\x7c") > 0x0) { + let ii111I1I = decodeURIComponent(ll1iIiiI[Ii1l1III("3")]("\x7c")[0x1]); + ll1iIiiI = ll1iIiiI[Ii1l1III("3")]("\x7c")[0x0]; + for (const II1Ii1l of ii111I1I[Ii1l1III("3")]("\x26")) { + if (II1Ii1l[Ii1l1III("1")]("\x3d") > 0x0) { + let lI1lliii = II1Ii1l[Ii1l1III("3")]("\x3d")[0x0]; + let I11Iii1i = II1Ii1l[Ii1l1III("3")]("\x3d")[0x1]; + iIl11Iii[lI1lliii] = I11Iii1i; + } + } + } + let I111lilI = req(ll1iIiiI, { + "\x6d\x65\x74\x68\x6f\x64": Ii1l1III("d"), + "\x68\x65\x61\x64\x65\x72\x73": iIl11Iii, + }); + I111lilI = I111lilI[Ii1l1III("f")][Ii1l1III("4")](); + if (I111lilI[Ii1l1III("1")](Ii1l1III("23")) >= 0x0) { + I111lilI = parseM3u(I111lilI, i1I1l1i); + } else if ( + I111lilI[Ii1l1III("1")](Ii1l1III("24")) > 0x0 && + I111lilI[Ii1l1III("1")](Ii1l1III("25")) > 0x0 + ) { + I111lilI = parseFm(I111lilI); + } else if ( + I111lilI[Ii1l1III("1")](Ii1l1III("26")) > 0x0 && + I111lilI[Ii1l1III("1")](Ii1l1III("25")) > 0x0 + ) { + I111lilI = parseLu(I111lilI); + } + let li1IiiII = (i1I1l1i + "\x0a" + I111lilI[Ii1l1III("9")]("\x0d", ""))[ + Ii1l1III("3") + ]("\x0a"); + let lli11iI = i1I1l1i; + let IiiIIiIi = null; + let iiiI1l = ""; + for (let i1ii1IIl = 0x0; i1ii1IIl < li1IiiII[Ii1l1III("27")]; i1ii1IIl++) { + let lIliIii = li1IiiII[i1ii1IIl][Ii1l1III("9")](/\s+/g, ""); + if ( + lIliIii != "" && + lIliIii[Ii1l1III("1")](Ii1l1III("6")) < 0x0 && + (lIliIii[Ii1l1III("1")]("\x2c") < 0x0 || + lIliIii[Ii1l1III("1")](Ii1l1III("28")) > 0x0) + ) { + if (iiiI1l != "") { + let ilIIIl = iI1I1I1I[Ii1l1III("9")]( + Ii1l1III("29"), + encodeURIComponent(lli11iI) + )[Ii1l1III("9")](Ii1l1III("2a"), encodeURIComponent(i1I1l1i)); + let ilI1ilI = ilIIIl[Ii1l1III("1")]("\x3c"); + let iili1I1i = ilIIIl[Ii1l1III("11")]("\x3e"); + if (ilI1ilI > -0x1 && iili1I1i > ilI1ilI) { + let I11Ilili = ilIIIl[Ii1l1III("10")](ilI1ilI, iili1I1i + 0x1); + let I1liliII = new RegExp(I11Ilili[Ii1l1III("9")](/<|>/g, "")); + let lii11liI = lli11iI[Ii1l1III("9")]( + I1liliII, + function (Ili1lIi1, iiliII1l) { + return iiliII1l; + } + ); + ilIIIl = ilIIIl[Ii1l1III("9")](I11Ilili, lii11liI); + console[Ii1l1III("7")](lli11iI + "\x2c\x20" + ilIIIl); + } + let IiiIIiIi = { + vod_id: IliI1i + Ii1l1III("2") + cates[IliI1i][Ii1l1III("27")], + vod_name: lli11iI, + vod_pic: ilIIIl, + vod_remarks: "", + type_name: Ii1l1III("2b"), + vod_year: "", + vod_area: "", + vod_actor: "", + vod_director: "", + vod_content: "", + vod_play_from: i1I1l1i, + vod_play_url: iiiI1l, + }; + cates[IliI1i][Ii1l1III("a")](IiiIIiIi); + } + lli11iI = lIliIii[Ii1l1III("3")]("\x2c")[0x0][Ii1l1III("4")](); + iiiI1l = ""; + } else if ( + lIliIii[Ii1l1III("1")]("\x2c") > 0x0 && + /http|rtmp|rtsp|rsp/[Ii1l1III("17")](lIliIii) + ) { + let l1iiI1ii = lIliIii[Ii1l1III("3")]("\x2c"); + if (iiiI1l != "") { + iiiI1l += "\x23"; + } + iiiI1l += + l1iiI1ii[0x0][Ii1l1III("4")]() + + "\x24" + + l1iiI1ii[0x1][Ii1l1III("4")](); + } + } + if (iiiI1l != "") { + let II1Iliil = iI1I1I1I[Ii1l1III("9")]( + Ii1l1III("29"), + encodeURIComponent(lli11iI) + )[Ii1l1III("9")](Ii1l1III("2a"), encodeURIComponent(i1I1l1i)); + let ilI1ilI = II1Iliil[Ii1l1III("1")]("\x3c"); + let iili1I1i = II1Iliil[Ii1l1III("11")]("\x3e"); + if (ilI1ilI > -0x1 && iili1I1i > ilI1ilI) { + let I11Ilili = II1Iliil[Ii1l1III("10")](ilI1ilI, iili1I1i + 0x1); + let I1liliII = new RegExp(I11Ilili[Ii1l1III("9")](/<|>/g, "")); + let lii11liI = I1liliII[Ii1l1III("17")](lli11iI) + ? lli11iI[Ii1l1III("18")](I1liliII)[0x1] + : Ii1l1III("2c"); + II1Iliil = II1Iliil[Ii1l1III("9")](I11Ilili, lii11liI); + } + let IiiIIiIi = { + vod_id: IliI1i + Ii1l1III("2") + cates[IliI1i][Ii1l1III("27")], + vod_name: lli11iI, + vod_pic: II1Iliil, + vod_remarks: "", + type_name: Ii1l1III("2b"), + vod_year: "", + vod_area: "", + vod_actor: "", + vod_director: "", + vod_content: "", + vod_play_from: i1I1l1i, + vod_play_url: iiiI1l, + }; + cates[IliI1i][Ii1l1III("a")](IiiIIiIi); + } + } + return cates[IliI1i]; +} +function homeVod(liIIlIl1) { + let iIl1IIii = getCateData(classes[0x0][Ii1l1III("2d")]); + let I1l1iil = JSON[Ii1l1III("15")]({ list: iIl1IIii }); + return I1l1iil; +} +function category(I1l1i1Ii, l1IiiIli, IIi1Illi, lilIliIl) { + let IIi1i1ll = []; + if (l1IiiIli == 0x1) { + IIi1i1ll = getCateData(I1l1i1Ii); + } + let iIiiIi1i = JSON[Ii1l1III("15")]({ list: IIi1i1ll }); + return iIiiIi1i; +} +function detail(lIl11iii) { + let I1IIIil = lIl11iii[Ii1l1III("3")](Ii1l1III("2")); + let liiiil1i = I1IIIil[0x0]; + let l1l111II = liiiil1i[Ii1l1III("3")]("\x24")[0x0]; + let Il1li11i = parseInt(I1IIIil[0x1]); + let Iill11Ii = getCateData(liiiil1i)[Il1li11i]; + console[Ii1l1III("7")](JSON[Ii1l1III("15")](Iill11Ii)); + if (l1l111II[Ii1l1III("1")]("\x21\x21") >= 0x0) { + l1l111II = l1l111II[Ii1l1III("9")]("\x21\x21", ""); + const ii1l1iil = Iill11Ii[Ii1l1III("2e")][Ii1l1III("3")]("\x23"); + console[Ii1l1III("7")](JSON[Ii1l1III("15")](ii1l1iil)); + let i1Ili1I = {}; + let IIIllli1 = {}; + for (const i1IiIlIl of ii1l1iil) { + let Ill1iii1 = i1IiIlIl[Ii1l1III("3")]("\x24")[0x0]; + let IIiIII11 = l1l111II; + if (Ill1iii1[Ii1l1III("1")](Ii1l1III("20")) > 0x0) { + IIiIII11 = Ill1iii1[Ii1l1III("3")](Ii1l1III("20"))[0x1]; + Ill1iii1 = Ill1iii1[Ii1l1III("3")](Ii1l1III("20"))[0x0]; + } + if (!i1Ili1I[Ii1l1III("2f")](Ill1iii1)) { + i1Ili1I[Ill1iii1] = 0x1; + } else { + i1Ili1I[Ill1iii1]++; + } + IIiIII11 = + l1l111II + (i1Ili1I[Ill1iii1] > 0x1 ? "\x20" + i1Ili1I[Ill1iii1] : ""); + if (!IIIllli1[Ii1l1III("2f")](IIiIII11)) { + IIIllli1[IIiIII11] = []; + } + IIIllli1[IIiIII11][Ii1l1III("a")]( + Ill1iii1 + "\x24" + i1IiIlIl[Ii1l1III("3")]("\x24")[0x1] + ); + } + let III1i1ii = []; + let iii1lIIi = []; + for (let iliI1I1i in IIIllli1) { + III1i1ii[Ii1l1III("a")](iliI1I1i); + iii1lIIi[Ii1l1III("a")](IIIllli1[iliI1I1i][Ii1l1III("30")]("\x23")); + } + Iill11Ii[Ii1l1III("31")] = III1i1ii[Ii1l1III("30")](Ii1l1III("2")); + Iill11Ii[Ii1l1III("2e")] = iii1lIIi[Ii1l1III("30")](Ii1l1III("2")); + } + return JSON[Ii1l1III("15")]({ list: [Iill11Ii] }); +} +function play(l1llIIii, illiiIII, lIIIiIiI) { + return JSON[Ii1l1III("15")]({ parse: 0x0, url: illiiIII }); +} +function search(I1lll, lI1iiIII) { + return null; +} +__JS_SPIDER__ = { + "\x69\x6e\x69\x74": init, + "\x68\x6f\x6d\x65": home, + "\x68\x6f\x6d\x65\x56\x6f\x64": homeVod, + "\x63\x61\x74\x65\x67\x6f\x72\x79": category, + "\x64\x65\x74\x61\x69\x6c": detail, + "\x70\x6c\x61\x79": play, + "\x73\x65\x61\x72\x63\x68": search, +}; +iil = "jsjiami.com.v6"; diff --git a/lib/apiv1535lavAPP.py b/lib/apiv1535lavAPP.py new file mode 100644 index 0000000..3ecc807 --- /dev/null +++ b/lib/apiv1535lavAPP.py @@ -0,0 +1,212 @@ +# -*- coding: utf-8 -*- +# by @嗷呜 +import sys +from base64 import b64encode, b64decode +from Crypto.Hash import MD5, SHA256 +sys.path.append('..') +from base.spider import Spider +from Crypto.Cipher import AES +import json +import time + + +class Spider(Spider): + + def getName(self): + return "lav" + + def init(self, extend=""): + self.id = self.ms(str(int(time.time() * 1000)))[:16] + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def action(self, action): + pass + + def destroy(self): + pass + + host = "http://sir_new.tiansexyl.tv" + t = str(int(time.time() * 1000)) + headers = {'User-Agent': 'okhttp-okgo/jeasonlzy', 'Connection': 'Keep-Alive', + 'Content-Type': 'application/x-www-form-urlencoded'} + + def homeContent(self, filter): + cateManual = {"演员": "actor", "分类": "avsearch", } + classes = [] + for k in cateManual: + classes.append({'type_name': k, 'type_id': cateManual[k]}) + j = {'code': 'homePage', 'mod': 'down', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv', + 'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn', + 'oauth_id': self.id} + + body = self.aes(j) + data = self.post(f'{self.host}/api.php?t={str(int(time.time() * 1000))}', data=body, headers=self.headers).json()['data'] + data1 = self.aes(data, False)['data'] + self.r = data1['r'] + for i, d in enumerate(data1['avTag']): + # if i == 4: + # break + classes.append({'type_name': d['name'], 'type_id': d['tag']}) + resutl = {} + resutl["class"] = classes + return resutl + + def homeVideoContent(self): + pass + + def categoryContent(self, tid, pg, filter, extend): + id = tid.split("@@") + result = {} + result["page"] = pg + result["pagecount"] = 9999 + result["limit"] = 90 + result["total"] = 999999 + if id[0] == 'avsearch': + if pg == '1': + j = {'code': 'avsearch', 'mod': 'search', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv', + 'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn', + 'oauth_id': self.id} + if len(id) > 1: + j = {'code': 'find', 'mod': 'tag', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv', + 'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn', + 'oauth_id': self.id, 'type': 'av', 'dis': 'new', 'page': str(pg), 'tag': id[1]} + elif id[0] == 'actor': + j = {'mod': 'actor', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv', 'app_type': 'rn', + 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn', 'oauth_id': self.id, + 'page': str(pg), 'filter': ''} + if len(id) > 1: + j = {'code': 'eq', 'mod': 'actor', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv', + 'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn', + 'oauth_id': self.id, 'page': str(pg), 'id': id[1], 'actor': id[2]} + else: + j = {'code': 'search', 'mod': 'av', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv', + 'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn', + 'oauth_id': self.id, 'page': str(pg), 'tag': id[0]} + + body = self.aes(j) + data = self.post(f'{self.host}/api.php?t={str(int(time.time() * 1000))}', data=body, headers=self.headers).json()['data'] + data1 = self.aes(data, False)['data'] + videos = [] + if tid == 'avsearch' and len(id) == 1: + for item in data1: + videos.append({"vod_id": id[0] + "@@" + str(item.get('tags')), 'vod_name': item.get('name'), + 'vod_pic': self.imgs(item.get('ico')), 'vod_tag': 'folder', + 'style': {"type": "rect", "ratio": 1.33}}) + elif tid == 'actor' and len(id) == 1: + for item in data1: + videos.append({"vod_id": id[0] + "@@" + str(item.get('id')) + "@@" + item.get('name'), + 'vod_name': item.get('name'), 'vod_pic': self.imgs(item.get('cover')), + 'vod_tag': 'folder', 'style': {"type": "oval"}}) + else: + for item in data1: + if item.get('_id'): + videos.append({"vod_id": str(item.get('id')), 'vod_name': item.get('title'), + 'vod_pic': self.imgs(item.get('cover_thumb') or item.get('cover_full')), + 'vod_remarks': item.get('good'), 'style': {"type": "rect", "ratio": 1.33}}) + result["list"] = videos + return result + + def detailContent(self, ids): + id = ids[0] + j = {'code': 'detail', 'mod': 'av', 'channel': 'self', 'via': 'agent', 'bundleId': 'com.tvlutv', + 'app_type': 'rn', 'os_version': '12.0.5', 'version': '3.2.3', 'oauth_type': 'android_rn', + 'oauth_id': self.id, 'id': id} + body = self.aes(j) + data = self.post(f'{self.host}/api.php?t={str(int(time.time() * 1000))}', data=body, headers=self.headers).json()['data'] + data1 = self.aes(data, False)['line'] + vod = {} + play = [] + for itt in data1: + a = itt['line'].get('s720') + if a: + b = a.split('.') + b[0] = 'https://m3u8' + a = '.'.join(b) + play.append(itt['info']['tips'] + "$" + a) + break + vod["vod_play_from"] = 'LAV' + vod["vod_play_url"] = "#".join(play) + result = {"list": [vod]} + return result + + def searchContent(self, key, quick, pg="1"): + pass + + def playerContent(self, flag, id, vipFlags): + url = self.getProxyUrl() + "&url=" + b64encode(id.encode('utf-8')).decode('utf-8') + "&type=m3u8" + self.hh = {'User-Agent': 'dd', 'Connection': 'Keep-Alive', 'Referer': self.r} + result = {} + result["parse"] = 0 + result["url"] = url + result["header"] = self.hh + return result + + def localProxy(self, param): + url = param["url"] + if param.get('type') == "m3u8": + return self.vod(b64decode(url).decode('utf-8')) + else: + return self.img(url) + + def vod(self, url): + data = self.fetch(url, headers=self.hh).text + key = bytes.fromhex("13d47399bda541b85e55830528d4e66f1791585b2d2216f23215c4c63ebace31") + iv = bytes.fromhex(data[:32]) + data = data[32:] + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + data_bytes = bytes.fromhex(data) + decrypted = cipher.decrypt(data_bytes) + encoded = decrypted.decode("utf-8").replace("\x08", "") + return [200, "application/vnd.apple.mpegur", encoded] + + def imgs(self, url): + return self.getProxyUrl() + '&url=' + url + + def img(self, url): + type = url.split('.')[-1] + data = self.fetch(url).text + key = bytes.fromhex("ba78f184208d775e1553550f2037f4af22cdcf1d263a65b4d5c74536f084a4b2") + iv = bytes.fromhex(data[:32]) + data = data[32:] + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + data_bytes = bytes.fromhex(data) + decrypted = cipher.decrypt(data_bytes) + return [200, f"image/{type}", decrypted] + + def ms(self, data, m=False): + h = MD5.new() + if m: + h = SHA256.new() + h.update(data.encode('utf-8')) + return h.hexdigest() + + def aes(self, data, operation=True): + key = bytes.fromhex("620f15cfdb5c79c34b3940537b21eda072e22f5d7151456dec3932d7a2b22c53") + t = str(int(time.time())) + ivt = self.ms(t) + if operation: + data = json.dumps(data, separators=(',', ':')) + iv = bytes.fromhex(ivt) + else: + iv = bytes.fromhex(data[:32]) + data = data[32:] + cipher = AES.new(key, AES.MODE_CFB, iv, segment_size=128) + if operation: + data_bytes = data.encode('utf-8') + encrypted = cipher.encrypt(data_bytes) + ep = f'{ivt}{encrypted.hex()}' + edata = f"data={ep}×tamp={t}0d27dfacef1338483561a46b246bf36d" + sign = self.ms(self.ms(edata, True)) + edata = f"timestamp={t}&data={ep}&sign={sign}" + return edata + else: + data_bytes = bytes.fromhex(data) + decrypted = cipher.decrypt(data_bytes) + return json.loads(decrypted.decode('utf-8')) + diff --git a/lib/apiv1561Phb.py b/lib/apiv1561Phb.py new file mode 100644 index 0000000..be5eb0f --- /dev/null +++ b/lib/apiv1561Phb.py @@ -0,0 +1,301 @@ +# -*- coding: utf-8 -*- +# by @嗷呜 +import json +import re +import sys +from base64 import b64decode, b64encode +from urllib.parse import urlparse + +import requests +from pyquery import PyQuery as pq +from requests import Session +sys.path.append('..') +from base.spider import Spider + +class Spider(Spider): + + def init(self, extend=""): + ''' + 内置代理配置:真心jar为例 + { + "key": "Phb", + "name": "Phb", + "type": 3, + "searchable": 1, + "quickSearch": 1, + "filterable": 1, + "api": "./py/Phb.py", + "ext": { + "http": "http://127.0.0.1:1072", + "https": "http://127.0.0.1:1072" + } + }, + 注:http(s)代理都是http + ''' + try:self.proxies = json.loads(extend) + except:self.proxies = {} + self.headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5410.0 Safari/537.36', + 'pragma': 'no-cache', + 'cache-control': 'no-cache', + 'sec-ch-ua-platform': '"Windows"', + 'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"', + 'dnt': '1', + 'sec-ch-ua-mobile': '?0', + 'sec-fetch-site': 'cross-site', + 'sec-fetch-mode': 'cors', + 'sec-fetch-dest': 'empty', + 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8', + 'priority': 'u=1, i', + } + self.host = self.gethost() + self.headers.update({'referer': f'{self.host}/', 'origin': self.host}) + self.session = Session() + self.session.proxies.update(self.proxies) + self.session.headers.update(self.headers) + pass + + def getName(self): + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def destroy(self): + pass + + def homeContent(self, filter): + result = {} + cateManual = { + "视频": "/video", + "片单": "/playlists", + "频道": "/channels", + "分类": "/categories", + "明星": "/pornstars" + } + classes = [] + filters = {} + for k in cateManual: + classes.append({ + 'type_name': k, + 'type_id': cateManual[k] + }) + result['class'] = classes + result['filters'] = filters + return result + + def homeVideoContent(self): + data = self.getpq('/recommended') + vhtml = data("#recommendedListings .pcVideoListItem .phimage") + return {'list': self.getlist(vhtml)} + + def categoryContent(self, tid, pg, filter, extend): + vdata = [] + result = {} + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + if tid == '/video' or '_this_video' in tid: + pagestr = f'&' if '?' in tid else f'?' + tid = tid.split('_this_video')[0] + data = self.getpq(f'{tid}{pagestr}page={pg}') + vdata = self.getlist(data('#videoCategory .pcVideoListItem')) + elif tid == '/playlists': + data = self.getpq(f'{tid}?page={pg}') + vhtml = data('#playListSection li') + vdata = [] + for i in vhtml.items(): + vdata.append({ + 'vod_id': 'playlists_click_' + i('.thumbnail-info-wrapper .display-block a').attr('href'), + 'vod_name': i('.thumbnail-info-wrapper .display-block a').attr('title'), + 'vod_pic': self.proxy(i('.largeThumb').attr('src')), + 'vod_tag': 'folder', + 'vod_remarks': i('.playlist-videos .number').text(), + 'style': {"type": "rect", "ratio": 1.33} + }) + elif tid == '/channels': + data = self.getpq(f'{tid}?o=rk&page={pg}') + vhtml = data('#filterChannelsSection li .description') + vdata = [] + for i in vhtml.items(): + vdata.append({ + 'vod_id': 'director_click_' + i('.avatar a').attr('href'), + 'vod_name': i('.avatar img').attr('alt'), + 'vod_pic': self.proxy(i('.avatar img').attr('src')), + 'vod_tag': 'folder', + 'vod_remarks': i('.descriptionContainer ul li').eq(-1).text(), + 'style': {"type": "rect", "ratio": 1.33} + }) + elif tid == '/categories' and pg == '1': + result['pagecount'] = 1 + data = self.getpq(f'{tid}') + vhtml = data('.categoriesListSection li .relativeWrapper') + vdata = [] + for i in vhtml.items(): + vdata.append({ + 'vod_id': i('a').attr('href') + '_this_video', + 'vod_name': i('a').attr('alt'), + 'vod_pic': self.proxy(i('a img').attr('src')), + 'vod_tag': 'folder', + 'style': {"type": "rect", "ratio": 1.33} + }) + elif tid == '/pornstars': + data = self.getpq(f'{tid}?o=t&page={pg}') + vhtml = data('#popularPornstars .performerCard .wrap') + vdata = [] + for i in vhtml.items(): + vdata.append({ + 'vod_id': 'pornstars_click_' + i('a').attr('href'), + 'vod_name': i('.performerCardName').text(), + 'vod_pic': self.proxy(i('a img').attr('src')), + 'vod_tag': 'folder', + 'vod_year': i('.performerVideosViewsCount span').eq(0).text(), + 'vod_remarks': i('.performerVideosViewsCount span').eq(-1).text(), + 'style': {"type": "rect", "ratio": 1.33} + }) + elif 'playlists_click' in tid: + tid = tid.split('click_')[-1] + if pg == '1': + hdata = self.getpq(tid) + self.token = hdata('#searchInput').attr('data-token') + vdata = self.getlist(hdata('#videoPlaylist .pcVideoListItem .phimage')) + else: + tid = tid.split('playlist/')[-1] + data = self.getpq(f'/playlist/viewChunked?id={tid}&token={self.token}&page={pg}') + vdata = self.getlist(data('.pcVideoListItem .phimage')) + elif 'director_click' in tid: + tid = tid.split('click_')[-1] + data = self.getpq(f'{tid}/videos?page={pg}') + vdata = self.getlist(data('#showAllChanelVideos .pcVideoListItem .phimage')) + elif 'pornstars_click' in tid: + tid = tid.split('click_')[-1] + data = self.getpq(f'{tid}/videos?page={pg}') + vdata = self.getlist(data('#mostRecentVideosSection .pcVideoListItem .phimage')) + result['list'] = vdata + return result + + def detailContent(self, ids): + url = f"{self.host}{ids[0]}" + data = self.getpq(ids[0]) + vn = data('meta[property="og:title"]').attr('content') + dtext = data('.userInfo .usernameWrap a') + pdtitle = '[a=cr:' + json.dumps( + {'id': 'director_click_' + dtext.attr('href'), 'name': dtext.text()}) + '/]' + dtext.text() + '[/a]' + vod = { + 'vod_name': vn, + 'vod_director': pdtitle, + 'vod_remarks': (data('.userInfo').text() + ' / ' + data('.ratingInfo').text()).replace('\n', ' / '), + 'vod_play_from': 'Pornhub', + 'vod_play_url': '' + } + js_content = data("#player script").eq(0).text() + plist = [f"{vn}${self.e64(f'{1}@@@@{url}')}"] + try: + pattern = r'"mediaDefinitions":\s*(\[.*?\]),\s*"isVertical"' + match = re.search(pattern, js_content, re.DOTALL) + if match: + json_str = match.group(1) + udata = json.loads(json_str) + plist = [ + f"{media['height']}${self.e64(f'{0}@@@@{url}')}" + for media in udata[:-1] + if (url := media.get('videoUrl')) + ] + except Exception as e: + print(f"提取mediaDefinitions失败: {str(e)}") + vod['vod_play_url'] = '#'.join(plist) + return {'list': [vod]} + + def searchContent(self, key, quick, pg="1"): + data = self.getpq(f'/video/search?search={key}&page={pg}') + return {'list': self.getlist(data('#videoSearchResult .pcVideoListItem .phimage'))} + + def playerContent(self, flag, id, vipFlags): + ids = self.d64(id).split('@@@@') + if '.m3u8' in ids[1]: ids[1] = self.proxy(ids[1], 'm3u8') + return {'parse': int(ids[0]), 'url': ids[1], 'header': self.headers} + + def localProxy(self, param): + url = self.d64(param.get('url')) + if param.get('type') == 'm3u8': + return self.m3Proxy(url) + else: + return self.tsProxy(url) + + def m3Proxy(self, url): + ydata = requests.get(url, headers=self.headers, proxies=self.proxies, allow_redirects=False) + data = ydata.content.decode('utf-8') + if ydata.headers.get('Location'): + url = ydata.headers['Location'] + data = requests.get(url, headers=self.headers, proxies=self.proxies).content.decode('utf-8') + lines = data.strip().split('\n') + last_r = url[:url.rfind('/')] + parsed_url = urlparse(url) + durl = parsed_url.scheme + "://" + parsed_url.netloc + for index, string in enumerate(lines): + if '#EXT' not in string: + if 'http' not in string: + domain = last_r if string.count('/') < 2 else durl + string = domain + ('' if string.startswith('/') else '/') + string + lines[index] = self.proxy(string, string.split('.')[-1].split('?')[0]) + data = '\n'.join(lines) + return [200, "application/vnd.apple.mpegur", data] + + def tsProxy(self, url): + data = requests.get(url, headers=self.headers, proxies=self.proxies, stream=True) + return [200, data.headers['Content-Type'], data.content] + + def gethost(self): + try: + response = requests.get('https://www.pornhub.com', headers=self.headers, proxies=self.proxies, + allow_redirects=False) + return response.headers['Location'][:-1] + except Exception as e: + print(f"获取主页失败: {str(e)}") + return "https://www.pornhub.com" + + def e64(self, text): + try: + text_bytes = text.encode('utf-8') + encoded_bytes = b64encode(text_bytes) + return encoded_bytes.decode('utf-8') + except Exception as e: + print(f"Base64编码错误: {str(e)}") + return "" + + def d64(self, encoded_text): + try: + encoded_bytes = encoded_text.encode('utf-8') + decoded_bytes = b64decode(encoded_bytes) + return decoded_bytes.decode('utf-8') + except Exception as e: + print(f"Base64解码错误: {str(e)}") + return "" + + def getlist(self, data): + vlist = [] + for i in data.items(): + vlist.append({ + 'vod_id': i('a').attr('href'), + 'vod_name': i('a').attr('title'), + 'vod_pic': self.proxy(i('img').attr('src')), + 'vod_remarks': i('.bgShadeEffect').text() or i('.duration').text(), + 'style': {'ratio': 1.33, 'type': 'rect'} + }) + return vlist + + def getpq(self, path): + try: + response = self.session.get(f'{self.host}{path}').text + return pq(response.encode('utf-8')) + except Exception as e: + print(f"请求失败: , {str(e)}") + return None + + def proxy(self, data, type='img'): + if data and len(self.proxies):return f"{self.getProxyUrl()}&url={self.e64(data)}&type={type}" + else:return data \ No newline at end of file diff --git a/lib/apiv1587DSYS.py b/lib/apiv1587DSYS.py new file mode 100644 index 0000000..f71349d --- /dev/null +++ b/lib/apiv1587DSYS.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +# by @嗷呜 +import time +import uuid +from base64 import b64decode, b64encode +import json +import sys +from urllib.parse import urlparse, urlunparse +from Crypto.Cipher import AES +from Crypto.Hash import MD5 +from Crypto.Util.Padding import unpad, pad +sys.path.append('..') +from base.spider import Spider + + +class Spider(Spider): + + def init(self, extend=""): + pass + + def getName(self): + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def destroy(self): + pass + + host = "https://api.230110.xyz" + + phost = "https://cdn.230110.xyz" + + headers = { + 'origin': host, + 'referer': f'{host}/', + 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.8 Mobile/15E148 Safari/604.1', + } + + def homeContent(self, filter): + data='9XSPkyFMrOOG34JSg//ZosMof45cyBo9hwZMZ5rvI6Yz/ZZlXWIf8/644OzwW+FNIOdJ61R/Lxjy1tqN+ZzokxtiVzb8LjYAkh6GFudwAUXFt9yS1ZjAxC3tDKrQsJQLk3nym0s00DBBzLBntRBDFz7nbba+OOBuQOZpL3CESGL42l4opdoViQLhO/dIizY1kIOk2NxxpDC9Z751gPl1ctHWuLWhuLG/QWgNWi/iHScjKrMHJKcC9GQHst/4Q3dgZ03eQIIVB6jvoV1XXoBCz6fjM/jM3BXpzSttT4Stglwy93gWuNWuZiKypHK2Q0lO10oM0ceRW2a0fPGId+rNYMRO3cR/C0ZueD4cmTAVOuxVr9ZZSP8/nhD0bHyAPONXtchIDJb0O/kdFHk2KTJfQ5q4fHOyzezczc4iQDV/R0S8cGZKM14MF+wytA/iljfj43H0UYqq5pM+MCUGRTdYEtuxCp0+A+DiOhNZwY/Km/TgBoGZQWGbpljJ2LAVnWhxX+ickLH7zuR/FeIwP/R8zOuR+8C8UlT9eHTqtvfNzaGdFxt316atHy8TNjRO7J5a177mqsHs3ziG0toDDzLDCbhRUjFgVA3ktahhXiWaaCo/ZGSJAA8TDO5DYqnJ0JDaX0ILPj8QB5zxrHYmRE8PboIr3RBAjz1sREbaHfjrUjoh29ePhlolLV00EvgoxP5knaqt5Ws/sq5IG57qKCAPgqXzblPLHToJGBtukKhLp8jbGJrkb6PVn4/jysks0NGE' + return {'class':self.aes(data,False)} + + def homeVideoContent(self): + pass + + def categoryContent(self, tid, pg, filter, extend): + data = {"q": "", "filter": [f"type_id = {tid}"], "offset": (int(pg)-1) * 24, "limit": 24, "sort": ["video_time:desc"],"lang": "zh-cn", "route": "/videos/search"} + result = {} + if 'skey_' in tid:return self.searchContent(tid.split('_')[-1], True, pg) + result['list'] = self.getl(self.getdata(data)) + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + return result + + def detailContent(self, ids): + data={"limit":1,"filter":[f"video_id = {ids[0]}"],"lang":"zh-cn","route":"/videos/search"} + res = self.getdata(data)[0] + purl=urlunparse(urlparse(self.phost)._replace(path=urlparse(res.get('video_url')).path)) + vod = { + 'vod_play_from': 'dsysav', + 'vod_play_url': f"{res.get('video_duration')}${purl}" + } + if res.get('video_tag'): + clist = [] + tags=res['video_tag'].split(',') + for k in tags: + clist.append('[a=cr:' + json.dumps({'id': f'skey_{k}', 'name': k}) + '/]' + k + '[/a]') + vod['vod_content'] = ' '.join(clist) + return {'list':[vod]} + + def searchContent(self, key, quick, pg="1"): + data={"q":key,"filter":[],"offset":(int(pg)-1) * 24,"limit":24,"sort":["video_time:desc"],"lang":"zh-cn","route":"/videos/search"} + return {'list':self.getl(self.getdata(data)),'page':pg} + + def playerContent(self, flag, id, vipFlags): + if id.endswith('.mpd'): + id=f"{self.getProxyUrl()}&url={self.e64(id)}&type=mpd" + return {'parse': 0, 'url': id, 'header':self.headers} + + def localProxy(self, param): + if param.get('type') and param['type']=='mpd': + url = self.d64(param.get('url')) + ids=url.split('/') + id=f"{ids[-3]}/{ids[-2]}/" + xpu = f"{self.getProxyUrl()}&path=".replace('&', '&') + data = self.fetch(url, headers=self.headers).text + data = data.replace('initialization="', f'initialization="{xpu}{id}').replace('media="',f'media="{xpu}{id}') + return [200,'application/octet-stream',data] + else: + hsign=self.md5(f"AjPuom638LmWfWyeM5YueKuJ9PuWLdRn/mpd/{param.get('path')}1767196800") + bytes_data = bytes.fromhex(hsign) + sign = b64encode(bytes_data).decode('utf-8').replace('=','').replace('+','-').replace('/','_') + url=f"{self.phost}/mpd/{param.get('path')}?sign={sign}&expire=1767196800" + return [302,'text/plain',None,{'Location':url}] + + def liveContent(self, url): + pass + + def aes(self, text, operation=True): + key = b'OPQT123412FRANME' + iv = b'MRDCQP12QPM13412' + cipher = AES.new(key, AES.MODE_CBC, iv) + if operation: + ct_bytes = cipher.encrypt(pad(json.dumps(text).encode("utf-8"), AES.block_size)) + ct = b64encode(ct_bytes).decode("utf-8") + return ct + else: + pt = unpad(cipher.decrypt(b64decode(text)), AES.block_size) + return json.loads(pt.decode("utf-8")) + + def e64(self, text): + try: + text_bytes = text.encode('utf-8') + encoded_bytes = b64encode(text_bytes) + return encoded_bytes.decode('utf-8') + except Exception as e: + print(f"Base64编码错误: {str(e)}") + return "" + + def d64(self,encoded_text): + try: + encoded_bytes = encoded_text.encode('utf-8') + decoded_bytes = b64decode(encoded_bytes) + return decoded_bytes.decode('utf-8') + except Exception as e: + print(f"Base64解码错误: {str(e)}") + return "" + + def md5(self, text): + h = MD5.new() + h.update(text.encode('utf-8')) + return h.hexdigest() + + def getl(self,data): + videos = [] + for i in data: + img = i.get('video_cover') + if img and 'http' in img:img = urlunparse(urlparse(self.phost)._replace(path=urlparse(img).path)) + videos.append({ + 'vod_id': i.get('video_id'), + 'vod_name': i.get('video_title'), + 'vod_pic': img, + 'vod_remarks': i.get('video_duration'), + 'style': {"type": "rect", "ratio": 1.33} + }) + return videos + + def getdata(self,data): + uid = str(uuid.uuid4()) + t = int(time.time()) + json_data = { + 'sign': self.md5(f"{self.e64(json.dumps(data))}{uid}{t}AjPuom638LmWfWyeM5YueKuJ9PuWLdRn"), + 'nonce': uid, + 'timestamp': t, + 'data': self.aes(data), + } + res = self.post(f"{self.host}/v1", json=json_data, headers=self.headers).json() + res = self.aes(res['data'], False) + return res diff --git a/lib/apiv161351吸瓜动态版.py b/lib/apiv161351吸瓜动态版.py new file mode 100644 index 0000000..81ba712 --- /dev/null +++ b/lib/apiv161351吸瓜动态版.py @@ -0,0 +1,404 @@ +# -*- coding: utf-8 -*- +# 🌈 Love +import json +import random +import re +import sys +import threading +import time +from base64 import b64decode, b64encode +from urllib.parse import urlparse + +import requests +from Crypto.Cipher import AES +from Crypto.Util.Padding import unpad +from pyquery import PyQuery as pq +sys.path.append('..') +from base.spider import Spider + + +class Spider(Spider): + + def init(self, extend=""): + try:self.proxies = json.loads(extend) + except:self.proxies = {} + self.headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Accept-Language': 'zh-CN,zh;q=0.9', + 'Connection': 'keep-alive', + 'Cache-Control': 'no-cache', + } + # Use working dynamic URLs directly + self.host = self.get_working_host() + self.headers.update({'Origin': self.host, 'Referer': f"{self.host}/"}) + self.log(f"使用站点: {self.host}") + print(f"使用站点: {self.host}") + pass + + def getName(self): + return "🌈 51吸瓜" + + def isVideoFormat(self, url): + # Treat direct media formats as playable without parsing + return any(ext in (url or '') for ext in ['.m3u8', '.mp4', '.ts']) + + def manualVideoCheck(self): + return False + + def destroy(self): + pass + + def homeContent(self, filter): + try: + response = requests.get(self.host, headers=self.headers, proxies=self.proxies, timeout=15) + if response.status_code != 200: + return {'class': [], 'list': []} + + data = self.getpq(response.text) + result = {} + classes = [] + + # Try to get categories from different possible locations + category_selectors = [ + '.category-list ul li', + '.nav-menu li', + '.menu li', + 'nav ul li' + ] + + for selector in category_selectors: + for k in data(selector).items(): + link = k('a') + href = (link.attr('href') or '').strip() + name = (link.text() or '').strip() + # Skip placeholder or invalid entries + if not href or href == '#' or not name: + continue + classes.append({ + 'type_name': name, + 'type_id': href + }) + if classes: + break + + # If no categories found, create some default ones + if not classes: + classes = [ + {'type_name': '首页', 'type_id': '/'}, + {'type_name': '最新', 'type_id': '/latest/'}, + {'type_name': '热门', 'type_id': '/hot/'} + ] + + result['class'] = classes + result['list'] = self.getlist(data('#index article a')) + return result + + except Exception as e: + print(f"homeContent error: {e}") + return {'class': [], 'list': []} + + def homeVideoContent(self): + try: + response = requests.get(self.host, headers=self.headers, proxies=self.proxies, timeout=15) + if response.status_code != 200: + return {'list': []} + data = self.getpq(response.text) + return {'list': self.getlist(data('#index article a, #archive article a'))} + except Exception as e: + print(f"homeVideoContent error: {e}") + return {'list': []} + + def categoryContent(self, tid, pg, filter, extend): + try: + if '@folder' in tid: + id = tid.replace('@folder', '') + videos = self.getfod(id) + else: + # Build URL properly + if tid.startswith('/'): + if pg and pg != '1': + url = f"{self.host}{tid}page/{pg}/" + else: + url = f"{self.host}{tid}" + else: + url = f"{self.host}/{tid}" + + response = requests.get(url, headers=self.headers, proxies=self.proxies, timeout=15) + if response.status_code != 200: + return {'list': [], 'page': pg, 'pagecount': 1, 'limit': 90, 'total': 0} + + data = self.getpq(response.text) + videos = self.getlist(data('#archive article a, #index article a'), tid) + + result = {} + result['list'] = videos + result['page'] = pg + result['pagecount'] = 1 if '@folder' in tid else 99999 + result['limit'] = 90 + result['total'] = 999999 + return result + + except Exception as e: + print(f"categoryContent error: {e}") + return {'list': [], 'page': pg, 'pagecount': 1, 'limit': 90, 'total': 0} + + def detailContent(self, ids): + try: + url = f"{self.host}{ids[0]}" if not ids[0].startswith('http') else ids[0] + response = requests.get(url, headers=self.headers, proxies=self.proxies, timeout=15) + + if response.status_code != 200: + return {'list': [{'vod_play_from': '51吸瓜', 'vod_play_url': f'页面加载失败${url}'}]} + + data = self.getpq(response.text) + vod = {'vod_play_from': '51吸瓜'} + + # Get content/description + try: + clist = [] + if data('.tags .keywords a'): + for k in data('.tags .keywords a').items(): + title = k.text() + href = k.attr('href') + if title and href: + clist.append('[a=cr:' + json.dumps({'id': href, 'name': title}) + '/]' + title + '[/a]') + vod['vod_content'] = ' '.join(clist) if clist else data('.post-title').text() + except: + vod['vod_content'] = data('.post-title').text() or '51吸瓜视频' + + # Get video URLs (build episode list when multiple players exist) + try: + plist = [] + used_names = set() + if data('.dplayer'): + for c, k in enumerate(data('.dplayer').items(), start=1): + config_attr = k.attr('data-config') + if config_attr: + try: + config = json.loads(config_attr) + video_url = config.get('video', {}).get('url', '') + # Determine a readable episode name from nearby headings if present + ep_name = '' + try: + parent = k.parents().eq(0) + # search up to a few ancestors for a heading text + for _ in range(3): + if not parent: break + heading = parent.find('h2, h3, h4').eq(0).text() or '' + heading = heading.strip() + if heading: + ep_name = heading + break + parent = parent.parents().eq(0) + except Exception: + ep_name = '' + base_name = ep_name if ep_name else f"视频{c}" + name = base_name + count = 2 + # Ensure the name is unique + while name in used_names: + name = f"{base_name} {count}" + count += 1 + used_names.add(name) + if video_url: + self.log(f"解析到视频: {name} -> {video_url}") + print(f"解析到视频: {name} -> {video_url}") + plist.append(f"{name}${video_url}") + except: + continue + + if plist: + self.log(f"拼装播放列表,共{len(plist)}个") + print(f"拼装播放列表,共{len(plist)}个") + vod['vod_play_url'] = '#'.join(plist) + else: + vod['vod_play_url'] = f"未找到视频源${url}" + + except Exception as e: + vod['vod_play_url'] = f"视频解析失败${url}" + + return {'list': [vod]} + + except Exception as e: + print(f"detailContent error: {e}") + return {'list': [{'vod_play_from': '51吸瓜', 'vod_play_url': f'详情页加载失败${ids[0] if ids else ""}'}]} + + def searchContent(self, key, quick, pg="1"): + try: + url = f"{self.host}/search/{key}/{pg}" if pg != "1" else f"{self.host}/search/{key}/" + response = requests.get(url, headers=self.headers, proxies=self.proxies, timeout=15) + + if response.status_code != 200: + return {'list': [], 'page': pg} + + data = self.getpq(response.text) + videos = self.getlist(data('#archive article a, #index article a')) + return {'list': videos, 'page': pg} + + except Exception as e: + print(f"searchContent error: {e}") + return {'list': [], 'page': pg} + + def playerContent(self, flag, id, vipFlags): + url = id + p = 1 + if self.isVideoFormat(url): + # m3u8/mp4 direct play; when using proxy setting, wrap to proxy for m3u8 + if '.m3u8' in url: + url = self.proxy(url) + p = 0 + self.log(f"播放请求: parse={p}, url={url}") + print(f"播放请求: parse={p}, url={url}") + return {'parse': p, 'url': url, 'header': self.headers} + + def localProxy(self, param): + if param.get('type') == 'img': + res=requests.get(param['url'], headers=self.headers, proxies=self.proxies, timeout=10) + return [200,res.headers.get('Content-Type'),self.aesimg(res.content)] + elif param.get('type') == 'm3u8':return self.m3Proxy(param['url']) + else:return self.tsProxy(param['url']) + + def proxy(self, data, type='m3u8'): + if data and len(self.proxies):return f"{self.getProxyUrl()}&url={self.e64(data)}&type={type}" + else:return data + + def m3Proxy(self, url): + url=self.d64(url) + ydata = requests.get(url, headers=self.headers, proxies=self.proxies, allow_redirects=False) + data = ydata.content.decode('utf-8') + if ydata.headers.get('Location'): + url = ydata.headers['Location'] + data = requests.get(url, headers=self.headers, proxies=self.proxies).content.decode('utf-8') + lines = data.strip().split('\n') + last_r = url[:url.rfind('/')] + parsed_url = urlparse(url) + durl = parsed_url.scheme + "://" + parsed_url.netloc + iskey=True + for index, string in enumerate(lines): + if iskey and 'URI' in string: + pattern = r'URI="([^"]*)"' + match = re.search(pattern, string) + if match: + lines[index] = re.sub(pattern, f'URI="{self.proxy(match.group(1), "mkey")}"', string) + iskey=False + continue + if '#EXT' not in string: + if 'http' not in string: + domain = last_r if string.count('/') < 2 else durl + string = domain + ('' if string.startswith('/') else '/') + string + lines[index] = self.proxy(string, string.split('.')[-1].split('?')[0]) + data = '\n'.join(lines) + return [200, "application/vnd.apple.mpegur", data] + + def tsProxy(self, url): + url = self.d64(url) + data = requests.get(url, headers=self.headers, proxies=self.proxies, stream=True) + return [200, data.headers['Content-Type'], data.content] + + def e64(self, text): + try: + text_bytes = text.encode('utf-8') + encoded_bytes = b64encode(text_bytes) + return encoded_bytes.decode('utf-8') + except Exception as e: + print(f"Base64编码错误: {str(e)}") + return "" + + def d64(self, encoded_text): + try: + encoded_bytes = encoded_text.encode('utf-8') + decoded_bytes = b64decode(encoded_bytes) + return decoded_bytes.decode('utf-8') + except Exception as e: + print(f"Base64解码错误: {str(e)}") + return "" + + def get_working_host(self): + """Get working host from known dynamic URLs""" + # Known working URLs from the dynamic gateway + dynamic_urls = [ + 'https://artist.vgwtswi.xyz', + 'https://ability.vgwtswi.xyz', + 'https://am.vgwtswi.xyz' + ] + + # Test each URL to find a working one + for url in dynamic_urls: + try: + response = requests.get(url, headers=self.headers, proxies=self.proxies, timeout=10) + if response.status_code == 200: + # Verify it has the expected content structure + data = self.getpq(response.text) + articles = data('#index article a') + if len(articles) > 0: + self.log(f"选用可用站点: {url}") + print(f"选用可用站点: {url}") + return url + except Exception as e: + continue + + # Fallback to first URL if none work (better than crashing) + self.log(f"未检测到可用站点,回退: {dynamic_urls[0]}") + print(f"未检测到可用站点,回退: {dynamic_urls[0]}") + return dynamic_urls[0] + + + def getlist(self, data, tid=''): + videos = [] + l = '/mrdg' in tid + for k in data.items(): + a = k.attr('href') + b = k('h2').text() + # Some pages might not include datePublished; use a fallback + c = k('span[itemprop="datePublished"]').text() or k('.post-meta, .entry-meta, time').text() + if a and b: + videos.append({ + 'vod_id': f"{a}{'@folder' if l else ''}", + 'vod_name': b.replace('\n', ' '), + 'vod_pic': self.getimg(k('script').text()), + 'vod_remarks': c or '', + 'vod_tag': 'folder' if l else '', + 'style': {"type": "rect", "ratio": 1.33} + }) + return videos + + def getfod(self, id): + url = f"{self.host}{id}" + data = self.getpq(requests.get(url, headers=self.headers, proxies=self.proxies).text) + vdata=data('.post-content[itemprop="articleBody"]') + r=['.txt-apps','.line','blockquote','.tags','.content-tabs'] + for i in r:vdata.remove(i) + p=vdata('p') + videos=[] + for i,x in enumerate(vdata('h2').items()): + c=i*2 + videos.append({ + 'vod_id': p.eq(c)('a').attr('href'), + 'vod_name': p.eq(c).text(), + 'vod_pic': f"{self.getProxyUrl()}&url={p.eq(c+1)('img').attr('data-xkrkllgl')}&type=img", + 'vod_remarks':x.text() + }) + return videos + + def getimg(self, text): + match = re.search(r"loadBannerDirect\('([^']+)'", text) + if match: + url = match.group(1) + return f"{self.getProxyUrl()}&url={url}&type=img" + else: + return '' + + def aesimg(self, word): + key = b'f5d965df75336270' + iv = b'97b60394abc2fbe1' + cipher = AES.new(key, AES.MODE_CBC, iv) + decrypted = unpad(cipher.decrypt(word), AES.block_size) + return decrypted + + def getpq(self, data): + try: + return pq(data) + except Exception as e: + print(f"{str(e)}") + return pq(data.encode('utf-8')) diff --git a/lib/apiv1665Xvideos.py b/lib/apiv1665Xvideos.py new file mode 100644 index 0000000..91dcd73 --- /dev/null +++ b/lib/apiv1665Xvideos.py @@ -0,0 +1,260 @@ +# -*- coding: utf-8 -*- +# by @嗷呜 +import json +import re +import sys +from pyquery import PyQuery as pq +from base64 import b64decode, b64encode +from requests import Session +sys.path.append('..') +from base.spider import Spider + + +class Spider(Spider): + def init(self, extend=""): + self.headers['referer']=f'{self.host}/' + self.session = Session() + self.session.headers.update(self.headers) + pass + + def getName(self): + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def destroy(self): + pass + + host = "https://www.xvideos.com" + + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"', + 'sec-ch-ua-mobile': '?0', + 'sec-ch-ua-full-version': '"133.0.6943.98"', + 'sec-ch-ua-arch': '"x86"', + 'sec-ch-ua-platform': '"Windows"', + 'sec-ch-ua-platform-version': '"19.0.0"', + 'sec-ch-ua-model': '""', + 'sec-ch-ua-full-version-list': '"Not(A:Brand";v="99.0.0.0", "Google Chrome";v="133.0.6943.98", "Chromium";v="133.0.6943.98"', + 'dnt': '1', + 'upgrade-insecure-requests': '1', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8', + 'priority': 'u=0, i' + } + + def homeContent(self, filter): + result = {} + cateManual = { + "最新": "/new", + "最佳": "/best", + "频道": "/channels-index", + "标签": "/tags", + "明星": "/pornstars-index" + } + classes = [] + for k in cateManual: + classes.append({ + 'type_name': k, + 'type_id': cateManual[k] + }) + result['class'] = classes + return result + + def homeVideoContent(self): + data = self.getpq() + return {'list':self.getlist(data(".mozaique .frame-block"))} + + def categoryContent(self, tid, pg, filter, extend): + vdata = [] + result = {} + page = f"/{int(pg) - 1}" if pg != '1' else '' + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + if tid=='/new' or 'tags_click' in tid: + if 'tags_click' in tid:tid=tid.split('click_')[-1] + data=self.getpq(f'{tid}/{pg}') + vdata=self.getlist(data(".mozaique .frame-block")) + elif tid=='/best': + if pg=='1': + self.path=self.session.get(f'{self.host}{tid}',headers=self.headers,allow_redirects=False).headers['Location'] + data=self.getpq(f'{self.path}{page}') + vdata=self.getlist(data(".mozaique .frame-block")) + elif tid=='/channels-index' or tid=='/pornstars-index': + data = self.getpq(f'{tid}{page}') + vhtml=data(".mozaique .thumb-block") + for i in vhtml.items(): + a = i('.thumb-inside .thumb a') + match = re.search(r'src="([^"]+)"', a('script').text()) + img='' + if match: + img = match.group(1).strip() + vdata.append({ + 'vod_id': f"channels_click_{'/channels'if tid=='/channels-index' else ''}"+a.attr('href'), + 'vod_name': a('.profile-name').text() or i('.profile-name').text().replace('\xa0','/'), + 'vod_pic': img, + 'vod_tag': 'folder', + 'vod_remarks': i('.thumb-under .profile-counts').text(), + 'style': {'ratio': 1.33, 'type': 'rect'} + }) + elif tid=='/tags': + result['pagecount'] = pg + vhtml = self.getpq(tid) + vhtml = vhtml('.tags-list') + for d in vhtml.items(): + for i in d('li a').items(): + vdata.append({ + 'vod_id': "tags_click_"+i.attr('href'), + 'vod_name': i.attr('title') or i('b').text(), + 'vod_pic': '', + 'vod_tag': 'folder', + 'vod_remarks': i('.navbadge').text(), + 'style': {'ratio': 1.33, 'type': 'rect'} + }) + elif 'channels_click' in tid: + tid=tid.split('click_')[-1] + headers=self.session.headers.copy() + headers.update({'Accept': 'application/json, text/javascript, */*; q=0.01'}) + vhtml=self.post(f'{self.host}{tid}/videos/best/{int(pg)-1}',headers=headers).json() + for i in vhtml['videos']: + vdata.append({ + 'vod_id': i.get('u'), + 'vod_name': i.get('tf'), + 'vod_pic': i.get('il'), + 'vod_year': i.get('n'), + 'vod_remarks': i.get('d'), + 'style': {'ratio': 1.33, 'type': 'rect'} + }) + result['list'] = vdata + return result + + def detailContent(self, ids): + url = f"{self.host}{ids[0]}" + data = self.getpq(ids[0]) + vn=data('meta[property="og:title"]').attr('content') + dtext=data('.main-uploader a') + href=dtext.attr('href') + pdtitle='' + if href and href.count('/') < 2: + href=f'/channels{href}' + pdtitle = '[a=cr:' + json.dumps({'id': 'channels_click_'+href, 'name': dtext('.name').text()}) + '/]' + dtext('.name').text() + '[/a]' + vod = { + 'vod_name': vn, + 'vod_director':pdtitle, + 'vod_remarks': data('.page-title').text().replace(vn,''), + 'vod_play_from': '老僧酿酒', + 'vod_play_url': '' + } + js_content = data("#video-player-bg script") + jstr='' + for script in js_content.items(): + content = script.text() + if 'setVideoUrlLow' in content and 'html5player' in content: + jstr = content + break + plist = [f"{vn}${self.e64(f'{1}@@@@{url}')}"] + def extract_video_urls(js_content): + try: + low = re.search(r'setVideoUrlLow\([\'"]([^\'"]+)[\'"]\)', js_content) + high = re.search(r'setVideoUrlHigh\([\'"]([^\'"]+)[\'"]\)', js_content) + hls = re.search(r'setVideoHLS\([\'"]([^\'"]+)[\'"]\)', js_content) + + return { + 'hls': hls.group(1) if hls else None, + 'high': high.group(1) if high else None, + 'low': low.group(1) if low else None + } + except Exception as e: + print(f"提取视频URL失败: {str(e)}") + return {} + if jstr: + try: + urls = extract_video_urls(jstr) + plist = [ + f"{quality}${self.e64(f'{0}@@@@{url}')}" + for quality, url in urls.items() + if url + ] + except Exception as e: + print(f"提取url失败: {str(e)}") + vod['vod_play_url'] = '#'.join(plist) + return {'list':[vod]} + + def searchContent(self, key, quick, pg="1"): + data=self.getpq(f'/?k={key}&p={int(pg)-1}') + return {'list':self.getlist(data(".mozaique .frame-block")),'page':pg} + + def playerContent(self, flag, id, vipFlags): + headers = { + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5410.0 Safari/537.36', + 'pragma': 'no-cache', + 'cache-control': 'no-cache', + 'sec-ch-ua-platform': '"Windows"', + 'sec-ch-ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"', + 'dnt': '1', + 'sec-ch-ua-mobile': '?0', + 'origin': self.host, + 'sec-fetch-site': 'cross-site', + 'sec-fetch-mode': 'cors', + 'sec-fetch-dest': 'empty', + 'referer': f'{self.host}/', + 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8', + 'priority': 'u=1, i', + } + ids=self.d64(id).split('@@@@') + return {'parse': int(ids[0]), 'url': ids[1], 'header': headers} + + def localProxy(self, param): + pass + + def e64(self, text): + try: + text_bytes = text.encode('utf-8') + encoded_bytes = b64encode(text_bytes) + return encoded_bytes.decode('utf-8') + except Exception as e: + print(f"Base64编码错误: {str(e)}") + return "" + + def d64(self,encoded_text): + try: + encoded_bytes = encoded_text.encode('utf-8') + decoded_bytes = b64decode(encoded_bytes) + return decoded_bytes.decode('utf-8') + except Exception as e: + print(f"Base64解码错误: {str(e)}") + return "" + + def getlist(self, data): + vlist=[] + for i in data.items(): + a=i('.thumb-inside .thumb a') + b=i('.thumb-under .title a') + vlist.append({ + 'vod_id': a.attr('href'), + 'vod_name': b('a').attr('title'), + 'vod_pic': a('img').attr('data-src'), + 'vod_year': a('.video-hd-mark').text(), + 'vod_remarks': b('.duration').text(), + 'style': {'ratio': 1.33, 'type': 'rect'} + }) + return vlist + + def getpq(self, path=''): + response = self.session.get(f'{self.host}{path}').text + try: + return pq(response) + except Exception as e: + print(f"{str(e)}") + return pq(response.encode('utf-8')) diff --git a/lib/apiv1743黑料.py b/lib/apiv1743黑料.py new file mode 100644 index 0000000..782c30b --- /dev/null +++ b/lib/apiv1743黑料.py @@ -0,0 +1,260 @@ +# coding=utf-8 +# !/python +import sys +import requests +from bs4 import BeautifulSoup +import re +from base.spider import Spider + +sys.path.append('..') +xurl = "https://kb11.adultporna-av1sim111.xyz" +headerx = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36' +} + + +class Spider(Spider): + global xurl + global headerx + + def getName(self): + return "首页" + + def init(self, extend): + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def homeVideoContent(self): + videos = [] + try: + res = requests.get(xurl + '/show/30/', headers=headerx) + res.encoding = "utf-8" + res = res.text + doc = BeautifulSoup(res, "html.parser") + vodss = doc.find('ul', class_='row row-space8 row-m-space8') + vods = vodss.find_all('li') + for vod in vods: + name = vod.select_one('section a')['title'] + id = vod.select_one('section a')['href'] + remarks = vod.select_one('section a span small').text + pic = vod.select_one('section a img')['src'] + video = { + "vod_id": id, + "vod_name": name, + "vod_pic": pic, + "vod_remarks": remarks + } + videos.append(video) + except: + pass + result = {'list': videos} + return result + + def homeContent(self, filter): + res = requests.get(xurl + '/zzzz', headers=headerx) + res.encoding = "utf-8" + res = res.text + doc = BeautifulSoup(res, "html.parser") + result = {} + result['class'] = [] + vodss = doc.find_all('dd') + result['class'].append({'type_id': '/t/86', 'type_name': '女优'}) + result['class'].append({'type_id': '/t/141', 'type_name': '日本番號'}) + result['class'].append({'type_id': '/t/1', 'type_name': '日本有码'}) + result['class'].append({'type_id': '/t/5', 'type_name': '日本无码'}) + result['class'].append({'type_id': '/t/32', 'type_name': '日本巨乳无码'}) + result['class'].append({'type_id': '/t/34', 'type_name': '日本人妻无码'}) + result['class'].append({'type_id': '/t/35', 'type_name': '日本制服无码'}) + result['class'].append({'type_id': '/t/223', 'type_name': '日本乱伦无码'}) + result['class'].append({'type_id': '/t/224', 'type_name': '日本强奸无码'}) + result['class'].append({'type_id': '/t/36', 'type_name': '日本丝袜美腿'}) + result['class'].append({'type_id': '/t/13', 'type_name': '日本中文字幕'}) + result['class'].append({'type_id': '/t/53', 'type_name': '日本绝美少女'}) + result['class'].append({'type_id': '/t/6', 'type_name': '日本强奸乱伦'}) + result['class'].append({'type_id': '/t/7', 'type_name': '日本巨乳'}) + result['class'].append({'type_id': '/t/9', 'type_name': '日本制服诱惑'}) + result['class'].append({'type_id': '/t/11', 'type_name': '日本调教'}) + result['class'].append({'type_id': '/t/58', 'type_name': '日本口爆'}) + result['class'].append({'type_id': '/t/30', 'type_name': '欧美'}) + result['class'].append({'type_id': '/t/164', 'type_name': '成人动漫'}) + result['class'].append({'type_id': '/t/85', 'type_name': '伦理电影'}) + result['class'].append({'type_id': '/t/2', 'type_name': '国产传媒'}) + result['class'].append({'type_id': '/t/163', 'type_name': '国产视频'}) + result['class'].append({'type_id': '/t/67', 'type_name': '国产空姐模特'}) + result['class'].append({'type_id': '/t/69', 'type_name': '国产学生'}) + result['class'].append({'type_id': '/t/70', 'type_name': '国产人妻熟女'}) + result['class'].append({'type_id': '/t/71', 'type_name': '国产乱伦'}) + result['class'].append({'type_id': '/t/72', 'type_name': '国产自慰'}) + result['class'].append({'type_id': '/t/73', 'type_name': '国产野合车震'}) + result['class'].append({'type_id': '/t/75', 'type_name': '国产名人'}) + result['class'].append({'type_id': '/t/74', 'type_name': '国产OL'}) + result['class'].append({'type_id': '/t/18', 'type_name': '国产剧情'}) + result['class'].append({'type_id': '/t/19', 'type_name': '国产偷怕'}) + result['class'].append({'type_id': '/t/76', 'type_name': '国产网曝'}) + result['class'].append({'type_id': '/t/227', 'type_name': '综合传媒'}) + result['class'].append({'type_id': '/t/38', 'type_name': '麻豆合集'}) + result['class'].append({'type_id': '/t/109', 'type_name': '葫芦影业'}) + result['class'].append({'type_id': '/t/111', 'type_name': '天美传媒'}) + result['class'].append({'type_id': '/t/112', 'type_name': '果冻传媒'}) + result['class'].append({'type_id': '/t/131', 'type_name': '91制片厂'}) + result['class'].append({'type_id': '/t/113', 'type_name': '蜜桃传媒'}) + result['class'].append({'type_id': '/t/114', 'type_name': '精东影业'}) + result['class'].append({'type_id': '/t/115', 'type_name': '皇家华人'}) + result['class'].append({'type_id': '/t/116', 'type_name': 'SWAG'}) + result['class'].append({'type_id': '/t/120', 'type_name': '兔子先生'}) + result['class'].append({'type_id': '/t/122', 'type_name': 'PsychoPornTW'}) + result['class'].append({'type_id': '/t/124', 'type_name': '微啪 & 陌丽影像传媒'}) + result['class'].append({'type_id': '/t/125', 'type_name': '大象传媒'}) + result['class'].append({'type_id': '/t/126', 'type_name': '乌鸦传媒'}) + result['class'].append({'type_id': '/t/141', 'type_name': '日本番号'}) + result['class'].append({'type_id': '/t/225', 'type_name': '综合番号'}) + result['class'].append({'type_id': '/t/142', 'type_name': '200GANA'}) + result['class'].append({'type_id': '/t/146', 'type_name': '259LUXU'}) + result['class'].append({'type_id': '/t/147', 'type_name': '261ARA'}) + result['class'].append({'type_id': '/t/148', 'type_name': '277DCV'}) + result['class'].append({'type_id': '/t/143', 'type_name': '300MIUM'}) + result['class'].append({'type_id': '/t/149', 'type_name': '300MAAN'}) + result['class'].append({'type_id': '/t/150', 'type_name': '300NTK'}) + result['class'].append({'type_id': '/t/152', 'type_name': '328HMDN'}) + result['class'].append({'type_id': '/t/154', 'type_name': '336KNB'}) + result['class'].append({'type_id': '/t/155', 'type_name': '348NTR'}) + result['class'].append({'type_id': '/t/156', 'type_name': '390JAC'}) + result['class'].append({'type_id': '/t/158', 'type_name': '428SUKE'}) + result['class'].append({'type_id': '/t/181', 'type_name': 'AARM'}) + result['class'].append({'type_id': '/t/180', 'type_name': 'ADN'}) + result['class'].append({'type_id': '/t/185', 'type_name': 'ATID'}) + result['class'].append({'type_id': '/t/192', 'type_name': 'DFDM'}) + result['class'].append({'type_id': '/t/194', 'type_name': 'DLDSS'}) + + + for vod in vodss: + id = vod.find('a')['href'].rstrip("/") + name = vod.find('a').text + if not any(d['type_name'] == name for d in result['class']): + result['class'].append({'type_id': id, 'type_name': name}) + return result + + def categoryContent(self, cid, pg, filter, ext): + result = {} + videos = [] + if pg == "" or pg == 1: + url = xurl + cid + else: + url = xurl + cid + '-' + str(pg) + + + res = requests.get(url=url, headers=headerx) + res.encoding = "utf-8" + res = res.text + + doc = BeautifulSoup(res, "html.parser") + vodss = doc.find('ul', class_='row row-space8 row-m-space8') + vods = vodss.find_all('li') + for vod in vods: + name = vod.select_one('section a')['title'] + id = vod.select_one('section a')['href'] + remarks = vod.select_one('section a span small').text + pic = vod.select_one('section a img')['src'] + video = { + "vod_id": id, + "vod_name": name, + "vod_pic": pic, + "vod_remarks": remarks + } + videos.append(video) + + result['list'] = videos + result['page'] = pg + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + return result + + def detailContent(self, ids): + did = ids[0].replace("voddetail", "v") + videos = [] + result = {} + res = requests.get(url=xurl + did, headers=headerx) + res.encoding = "utf-8" + res = res.text + source_match = re.search(r'"","url":"(.*?)"', res) + if source_match: + purl = source_match.group(1).replace("\\", "") + videos.append({ + "vod_id": did, + "vod_name": '', + "vod_pic": "", + "type_name": "", + "vod_year": "", + "vod_area": "", + "vod_remarks": "", + "vod_actor": "", + "vod_director": "", + "vod_content": "", + "vod_play_from": '直链播放', + "vod_play_url": purl + }) + + result['list'] = videos + return result + + def playerContent(self, flag, id, vipFlags): + + result = {} + result["parse"] = 0 + result["playUrl"] = '' + result["url"] = id + result["header"] = headerx + return result + + def searchContent(self, key, quick): + return self.searchContentPage(key, quick, '1') + + def searchContentPage(self, key, quick, page): + result = {} + + + header2 = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36', + 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6' + } + + res = requests.get(xurl + '/s/page/' + str(page) + '/wd/' + key, headers=header2) + res.encoding = "utf-8" + res = res.text + videos = [] + doc = BeautifulSoup(res, "html.parser") + vodss = doc.find('ul', class_='row row-space8 row-m-space8') + vods = vodss.find_all('li') + for vod in vods: + name = vod.select_one('section a')['title'] + id = vod.select_one('section a')['href'] + remarks = vod.select_one('section a span small').text + pic = vod.select_one('section a img')['src'] + video = { + "vod_id": id, + "vod_name": name, + "vod_pic": pic, + "vod_remarks": remarks + } + videos.append(video) + result['list'] = videos + result['page'] = page + result['pagecount'] = 9999 + result['limit'] = 90 + result['total'] = 999999 + return result + + def localProxy(self, params): + if params['type'] == "m3u8": + return self.proxyM3u8(params) + elif params['type'] == "media": + return self.proxyMedia(params) + elif params['type'] == "ts": + return self.proxyTs(params) + return None diff --git a/lib/apiv1769九个区.py b/lib/apiv1769九个区.py new file mode 100644 index 0000000..c25a9a1 --- /dev/null +++ b/lib/apiv1769九个区.py @@ -0,0 +1,419 @@ +# coding=utf-8 +#!/usr/bin/python +import sys +sys.path.append('..') +from base.spider import Spider +import json +import time +import urllib.parse +import re +import requests +from lxml import etree + +class Spider(Spider): + + def getName(self): + return "香蕉视频" + + def init(self, extend=""): + self.host = "https://618013.xyz" + self.api_host = "https://h5.xxoo168.org" + self.headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', + 'Accept-Encoding': 'gzip, deflate', + 'Connection': 'keep-alive', + 'Referer': self.host + } + self.log(f"香蕉视频爬虫初始化完成,主站: {self.host}") + + def html(self, content): + """将HTML内容转换为可查询的对象""" + try: + return etree.HTML(content) + except: + self.log("HTML解析失败") + return None + + def regStr(self, pattern, string, index=1): + """正则表达式提取字符串""" + try: + match = re.search(pattern, string, re.IGNORECASE) + if match and len(match.groups()) >= index: + return match.group(index) + except: + pass + return "" + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def homeContent(self, filter): + """获取首页内容和分类""" + result = {} + # 只保留指定的分类 + classes = [ + {'type_id': '618013.xyz_1', 'type_name': '全部视频'}, + {'type_id': '618013.xyz_22', 'type_name': '制服诱惑'}, + {'type_id': '618013.xyz_6', 'type_name': '国产视频'}, + {'type_id': '618013.xyz_8', 'type_name': '清纯少女'}, + {'type_id': '618013.xyz_9', 'type_name': '辣妹大奶'}, + {'type_id': '618013.xyz_10', 'type_name': '女同专属'}, + {'type_id': '618013.xyz_11', 'type_name': '素人出演'}, + {'type_id': '618013.xyz_12', 'type_name': '角色扮演'}, + {'type_id': '618013.xyz_20', 'type_name': '人妻熟女'}, + {'type_id': '618013.xyz_23', 'type_name': '日韩剧情'}, + {'type_id': '618013.xyz_21', 'type_name': '经典伦理'}, + {'type_id': '618013.xyz_7', 'type_name': '成人动漫'}, + {'type_id': '618013.xyz_14', 'type_name': '精品二区'}, + {'type_id': '618013.xyz_40', 'type_name': '精品三区'}, + {'type_id': '618013.xyz_53', 'type_name': '动漫中字'}, + {'type_id': '618013.xyz_52', 'type_name': '日本无码'}, + {'type_id': '618013.xyz_33', 'type_name': '中文字幕'}, + {'type_id': '618013.xyz_44', 'type_name': '国产传媒'}, + {'type_id': '618013.xyz_32', 'type_name': '国产自拍'} + ] + result['class'] = classes + try: + rsp = self.fetch(self.host, headers=self.headers) + doc = self.html(rsp.text) + videos = self._get_videos(doc, limit=20) + result['list'] = videos + except Exception as e: + self.log(f"首页获取出错: {str(e)}") + result['list'] = [] + return result + + def homeVideoContent(self): + """分类定义 - 兼容性方法""" + return { + 'class': [ + {'type_id': '618013.xyz_1', 'type_name': '全部视频'}, + {'type_id': '618013.xyz_13', 'type_name': '香蕉精品'}, + {'type_id': '618013.xyz_22', 'type_name': '制服诱惑'}, + {'type_id': '618013.xyz_6', 'type_name': '国产视频'}, + {'type_id': '618013.xyz_8', 'type_name': '清纯少女'}, + {'type_id': '618013.xyz_9', 'type_name': '辣妹大奶'}, + {'type_id': '618013.xyz_10', 'type_name': '女同专属'}, + {'type_id': '618013.xyz_11', 'type_name': '素人出演'}, + {'type_id': '618013.xyz_12', 'type_name': '角色扮演'}, + {'type_id': '618013.xyz_20', 'type_name': '人妻熟女'}, + {'type_id': '618013.xyz_23', 'type_name': '日韩剧情'}, + {'type_id': '618013.xyz_21', 'type_name': '经典伦理'}, + {'type_id': '618013.xyz_7', 'type_name': '成人动漫'}, + {'type_id': '618013.xyz_14', 'type_name': '精品二区'}, + {'type_id': '618013.xyz_40', 'type_name': '精品三区'}, + {'type_id': '618013.xyz_53', 'type_name': '动漫中字'}, + {'type_id': '618013.xyz_52', 'type_name': '日本无码'}, + {'type_id': '618013.xyz_33', 'type_name': '中文字幕'}, + {'type_id': '618013.xyz_44', 'type_name': '国产传媒'}, + {'type_id': '618013.xyz_32', 'type_name': '国产自拍'} + ] + } + + def categoryContent(self, tid, pg, filter, extend): + """分类内容""" + try: + domain, type_id = tid.split('_') + url = f"https://{domain}/index.php/vod/type/id/{type_id}.html" + if pg and pg != '1': + url = url.replace('.html', f'/page/{pg}.html') + self.log(f"访问分类URL: {url}") + rsp = self.fetch(url, headers=self.headers) + doc = self.html(rsp.text) + videos = self._get_videos(doc, limit=20) + + # 获取总页数 + pagecount = 1 + page_elements = doc.xpath('//div[@class="mypage"]//a') + if page_elements: + try: + last_page = page_elements[-2].xpath('./qyg0.js')[0] # 获取"尾页"前一个元素 + if last_page.isdigit(): + pagecount = int(last_page) + except: + pass + + return { + 'list': videos, + 'page': int(pg), + 'pagecount': pagecount, + 'limit': 20, + 'total': pagecount * 20 + } + except Exception as e: + self.log(f"分类内容获取出错: {str(e)}") + return {'list': []} + + def searchContent(self, key, quick, pg="1"): + """搜索功能""" + try: + search_url = f"{self.host}/index.php/vod/search.html?wd={urllib.parse.quote(key)}&page={pg}" + self.log(f"搜索URL: {search_url}") + rsp = self.fetch(search_url, headers=self.headers) + if not rsp or rsp.status_code != 200: + return {'list': []} + doc = self.html(rsp.text) + videos = self._get_videos(doc) + return {'list': videos} + except Exception as e: + self.log(f"搜索出错: {str(e)}") + return {'list': []} + + def detailContent(self, ids): + """详情页面""" + try: + vid = ids[0] + if '_' in vid: + domain, video_id = vid.split('_') + detail_url = f"https://{domain}/index.php/vod/detail/id/{video_id}.html" + else: + detail_url = f"{self.host}/index.php/vod/detail/id/{vid}.html" + self.log(f"访问详情URL: {detail_url}") + rsp = self.fetch(detail_url, headers=self.headers) + doc = self.html(rsp.text) + video_info = self._get_detail(doc, vid) + return {'list': [video_info]} if video_info else {'list': []} + except Exception as e: + self.log(f"详情获取出错: {str(e)}") + return {'list': []} + + def playerContent(self, flag, id, vipFlags): + """播放链接 - 直接使用API获取视频地址""" + try: + self.log(f"获取播放链接: flag={flag}, id={id}") + + # 提取视频ID + if '_' in id: + _, video_id = id.split('_') + else: + video_id = id + + self.log(f"视频ID: {video_id}") + + # 直接调用API获取视频地址 + api_url = f"{self.api_host}/api/v2/vod/reqplay/{video_id}" + self.log(f"请求API获取视频地址: {api_url}") + + api_headers = self.headers.copy() + api_headers.update({ + 'Referer': f"{self.host}/", + 'Origin': self.host, + 'X-Requested-With': 'XMLHttpRequest' + }) + + api_response = self.fetch(api_url, headers=api_headers) + if api_response and api_response.status_code == 200: + data = api_response.json() + self.log(f"API响应: {data}") + + if data.get('retcode') == 3: + video_url = data.get('data', {}).get('httpurl_preview', '') + else: + video_url = data.get('data', {}).get('httpurl', '') + + if video_url: + # 移除可能的参数 + video_url = video_url.replace('?300', '') + self.log(f"从API获取到视频地址: {video_url}") + return {'parse': 0, 'playUrl': '', 'url': video_url} + else: + self.log("API响应中没有找到视频地址") + else: + self.log(f"API请求失败,状态码: {api_response.status_code if api_response else '无响应'}") + + # 如果API请求失败,回退到原来的方法 + if '_' in id: + domain, play_id = id.split('_') + play_url = f"https://{domain}/html/kkyd.html?m={play_id}" + else: + play_url = f"{self.host}/html/kkyd.html?m={id}" + + self.log(f"回退到播放页面: {play_url}") + return {'parse': 1, 'playUrl': '', 'url': play_url} + + except Exception as e: + self.log(f"播放链接获取出错: {str(e)}") + # 出错时也返回播放页面URL + if '_' in id: + domain, play_id = id.split('_') + play_url = f"https://{domain}/html/kkyd.html?m={play_id}" + else: + play_url = f"{self.host}/html/kkyd.html?m={id}" + return {'parse': 1, 'playUrl': '', 'url': play_url} + + # ========== 辅助方法 ========== + + def _get_videos(self, doc, limit=None): + """获取影片列表 - 根据实际网站结构""" + try: + videos = [] + elements = doc.xpath('//a[@class="vodbox"]') + self.log(f"找到 {len(elements)} 个vodbox元素") + for elem in elements: + video = self._extract_video(elem) + if video: + videos.append(video) + return videos[:limit] if limit and videos else videos + except Exception as e: + self.log(f"获取影片列表出错: {str(e)}") + return [] + + def _extract_video(self, element): + """提取影片信息 - 修复标题乱码问题,正确读取km-script标签文本""" + try: + # 1. 提取影片链接(获取vod_id的来源) + link = element.xpath('./qyg1.js')[0] # 获取a标签的href属性 + if link.startswith('/'): + link = self.host + link # 补全相对路径为完整URL + + # 2. 提取vod_id(从URL的m参数获取,而非hash,更准确) + vod_id = self.regStr(r'm=(\d+)', link) # 匹配 ?m=123 中的数字 + if not vod_id: + vod_id = str(hash(link) % 1000000) # 兜底:hash生成唯一ID + + # 3. 提取标题(关键修复:读取

内的文本并解密) + title_elem = element.xpath('./qyg2.js') # 定位km-script标签 + if not title_elem: + # 尝试其他可能的标题选择器 + title_elem = element.xpath('.//p[contains(@class, "script")]/text()') + if not title_elem: + title_elem = element.xpath('./qyg3.js') + if not title_elem: + title_elem = element.xpath('./qyg4.js') + if not title_elem: + title_elem = element.xpath('./qyg5.js') + if not title_elem: + self.log(f"未找到标题元素,跳过该视频") + return None + + title_encrypted = title_elem[0].strip() # 获取加密的标题文本 + + # 4. 解密标题 - 使用网站的解密算法 + title = self._decrypt_title(title_encrypted) + + # 5. 提取封面图(逻辑不变,兼容data-original和src) + pic_elem = element.xpath('./qyg6.js') # 优先懒加载地址 + if not pic_elem: + pic_elem = element.xpath('./qyg7.js') # 兜底:直接src地址 + pic = pic_elem[0] if pic_elem else '' + + # 6. 补全图片URL(处理相对路径或无协议的情况) + if pic: + if pic.startswith('//'): + pic = 'https:' + pic # 补全https协议 + elif pic.startswith('/'): + pic = self.host + pic # 补全主域名 + + # 7. 返回正确的视频信息 + return { + 'vod_id': f"618013.xyz_{vod_id}", + 'vod_name': title, # 此时title已为正确文本 + 'vod_pic': pic, + 'vod_remarks': '', + 'vod_year': '' + } + except Exception as e: + self.log(f"提取影片信息出错: {str(e)}") + return None + + def _decrypt_title(self, encrypted_text): + """解密标题 - 使用网站的解密算法""" + try: + # 网站使用的解密算法:每个字符与128进行异或操作 + decrypted_chars = [] + for char in encrypted_text: + # 将字符转换为Unicode码点 + code_point = ord(char) + # 与128进行异或操作 + decrypted_code = code_point ^ 128 + # 转换回字符 + decrypted_char = chr(decrypted_code) + decrypted_chars.append(decrypted_char) + + # 拼接解密后的字符 + decrypted_text = ''.join(decrypted_chars) + return decrypted_text + except Exception as e: + self.log(f"标题解密失败: {str(e)}") + return encrypted_text # 如果解密失败,返回原文本 + + def _get_detail(self, doc, vid): + """获取详情信息 (优化版) - 修复播放源提取问题""" + try: + title = self._get_text(doc, ['//h1/text()', '//title/text()']) + pic = self._get_text(doc, ['//div[@class="dyimg"]//img/@src', '//img[@class="poster"]/@src']) + if pic and pic.startswith('/'): + pic = self.host + pic + desc = self._get_text(doc, ['//div[@class="yp_context"]/text()', '//div[@class="introduction"]//text()']) + actor = self._get_text(doc, ['//span[contains(text(),"主演")]/following-sibling::*/text()']) + director = self._get_text(doc, ['//span[contains(text(),"导演")]/following-sibling::*/text()']) + + play_from = [] + play_urls = [] + + # 尝试查找播放源 + play_links = doc.xpath('//a[contains(@href, "m=")]') + if play_links: + episodes = [] + for link in play_links: + ep_title = link.xpath('./qyg0.js') + ep_href = link.xpath('./qyg1.js')[0] + if ep_title: + ep_title = ep_title[0].strip() + play_id = self.regStr(r'm=(\d+)', ep_href) + if play_id: + episodes.append(f"{ep_title}${play_id}") + + if episodes: + play_from.append("默认播放源") + play_urls.append('#'.join(episodes)) + + if not play_from: + self.log("未找到播放源元素,无法定位播放源列表") + # 即使没有播放源,也返回基本信息 + return { + 'vod_id': vid, + 'vod_name': title, + 'vod_pic': pic, + 'type_name': '', + 'vod_year': '', + 'vod_area': '', + 'vod_remarks': '', + 'vod_actor': actor, + 'vod_director': director, + 'vod_content': desc, + 'vod_play_from': '默认播放源', + 'vod_play_url': f"第1集${vid}" + } + + return { + 'vod_id': vid, + 'vod_name': title, + 'vod_pic': pic, + 'type_name': '', + 'vod_year': '', + 'vod_area': '', + 'vod_remarks': '', + 'vod_actor': actor, + 'vod_director': director, + 'vod_content': desc, + 'vod_play_from': '$$$'.join(play_from), + 'vod_play_url': '$$$'.join(play_urls) + } + except Exception as e: + self.log(f"获取详情出错: {str(e)}") + return None + + def _get_text(self, doc, selectors): + """通用文本提取""" + for selector in selectors: + texts = doc.xpath(selector) + for text in texts: + if text and text.strip(): + return text.strip() + return '' \ No newline at end of file diff --git a/lib/apiv1795香蕉.py b/lib/apiv1795香蕉.py new file mode 100644 index 0000000..3fc11fa --- /dev/null +++ b/lib/apiv1795香蕉.py @@ -0,0 +1,669 @@ +# coding=utf-8 +#!/usr/bin/python +import sys +sys.path.append('..') +from base.spider import Spider +import json +import time +import urllib.parse +import re +import requests +from lxml import etree +from urllib.parse import urljoin + +class Spider(Spider): + + def getName(self): + return "苹果视频" + + def init(self, extend=""): + self.host = "https://618041.xyz" + self.api_host = "https://h5.xxoo168.org" + self.headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', + 'Accept-Encoding': 'gzip, deflate', + 'Connection': 'keep-alive', + 'Referer': self.host + } + # 定义特殊分区ID列表,包含所有需要特殊处理的分类 + self.special_categories = ['13', '14', '33', '53', '32', '52', '9'] + self.log(f"苹果视频爬虫初始化完成,主站: {self.host}") + + def html(self, content): + """将HTML内容转换为可查询的对象""" + try: + return etree.HTML(content) + except: + self.log("HTML解析失败") + return None + + def regStr(self, pattern, string, index=1): + """正则表达式提取字符串""" + try: + match = re.search(pattern, string, re.IGNORECASE) + if match and len(match.groups()) >= index: + return match.group(index) + except: + pass + return "" + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def homeContent(self, filter): + """获取首页内容和分类""" + result = {} + # 只保留指定的分类 + classes = [ + {'type_id': '618041.xyz_1', 'type_name': '全部视频'}, + {'type_id': '618041.xyz_13', 'type_name': '香蕉精品'}, + {'type_id': '618041.xyz_22', 'type_name': '制服诱惑'}, + {'type_id': '618041.xyz_6', 'type_name': '国产视频'}, + {'type_id': '618041.xyz_8', 'type_name': '清纯少女'}, + {'type_id': '618041.xyz_9', 'type_name': '辣妹大奶'}, + {'type_id': '618041.xyz_10', 'type_name': '女同专属'}, + {'type_id': '618041.xyz_11', 'type_name': '素人出演'}, + {'type_id': '618041.xyz_12', 'type_name': '角色扮演'}, + {'type_id': '618041.xyz_20', 'type_name': '人妻熟女'}, + {'type_id': '618041.xyz_23', 'type_name': '日韩剧情'}, + {'type_id': '618041.xyz_21', 'type_name': '经典伦理'}, + {'type_id': '618041.xyz_7', 'type_name': '成人动漫'}, + {'type_id': '618041.xyz_14', 'type_name': '精品二区'}, + {'type_id': '618041.xyz_53', 'type_name': '动漫中字'}, + {'type_id': '618041.xyz_52', 'type_name': '日本无码'}, + {'type_id': '618041.xyz_33', 'type_name': '中文字幕'}, + {'type_id': '618041.xyz_32', 'type_name': '国产自拍'} + ] + result['class'] = classes + try: + rsp = self.fetch(self.host, headers=self.headers) + doc = self.html(rsp.text) + videos = self._get_videos(doc, limit=20) + result['list'] = videos + except Exception as e: + self.log(f"首页获取出错: {str(e)}") + result['list'] = [] + return result + + def homeVideoContent(self): + """分类定义 - 兼容性方法""" + return { + 'class': [ + {'type_id': '618041.xyz_1', 'type_name': '全部视频'}, + {'type_id': '618041.xyz_13', 'type_name': '香蕉精品'}, + {'type_id': '618041.xyz_22', 'type_name': '制服诱惑'}, + {'type_id': '618041.xyz_6', 'type_name': '国产视频'}, + {'type_id': '618041.xyz_8', 'type_name': '清纯少女'}, + {'type_id': '618041.xyz_9', 'type_name': '辣妹大奶'}, + {'type_id': '618041.xyz_10', 'type_name': '女同专属'}, + {'type_id': '618041.xyz_11', 'type_name': '素人出演'}, + {'type_id': '618041.xyz_12', 'type_name': '角色扮演'}, + {'type_id': '618041.xyz_20', 'type_name': '人妻熟女'}, + {'type_id': '618041.xyz_23', 'type_name': '日韩剧情'}, + {'type_id': '618041.xyz_21', 'type_name': '经典伦理'}, + {'type_id': '618041.xyz_7', 'type_name': '成人动漫'}, + {'type_id': '618041.xyz_14', 'type_name': '精品二区'}, + {'type_id': '618041.xyz_53', 'type_name': '动漫中字'}, + {'type_id': '618041.xyz_52', 'type_name': '日本无码'}, + {'type_id': '618041.xyz_33', 'type_name': '中文字幕'}, + {'type_id': '618041.xyz_32', 'type_name': '国产自拍'} + ] + } + + def categoryContent(self, tid, pg, filter, extend): + """分类内容 - 修改为使用固定页数设置""" + try: + domain, type_id = tid.split('_') + url = f"https://{domain}/index.php/vod/type/id/{type_id}.html" + if pg and pg != '1': + url = url.replace('.html', f'/page/{pg}.html') + self.log(f"访问分类URL: {url}") + rsp = self.fetch(url, headers=self.headers) + doc = self.html(rsp.text) + # 在这里将 type_id 传递给 _get_videos 方法 + videos = self._get_videos(doc, category_id=type_id, limit=20) + + # 使用固定页数设置,而不是尝试从页面解析 + pagecount = 999 + total = 19980 + + return { + 'list': videos, + 'page': int(pg), + 'pagecount': pagecount, + 'limit': 20, + 'total': total + } + except Exception as e: + self.log(f"分类内容获取出错: {str(e)}") + return {'list': []} + + def searchContent(self, key, quick, pg="1"): + """搜索功能 - 完全修复版""" + try: + # 构造搜索URL + search_url = f"{self.host}/index.php/vod/type/id/1/wd/{urllib.parse.quote(key)}/page/{pg}.html" + self.log(f"搜索URL: {search_url}") + + # 发送请求 + rsp = self.fetch(search_url, headers=self.headers) + if not rsp or rsp.status_code != 200: + self.log("搜索请求失败") + return {'list': []} + + # 解析HTML + doc = self.html(rsp.text) + if not doc: + self.log("搜索页面解析失败") + return {'list': []} + + # 提取搜索结果 + videos = self._get_videos(doc, limit=20) + + # 尝试从页面提取分页信息 + pagecount = 5 # 默认值 + total = 100 # 默认值 + + # 尝试从分页元素中提取真实的分页信息 + page_elements = doc.xpath('//div[@class="mypage"]/a') + if page_elements and len(page_elements) > 0: + try: + # 查找尾页链接 + last_page = None + for elem in page_elements: + href = elem.xpath('./qyg10.js')[0] + if '尾页' in elem.text or 'page/' in href: + last_page = href + break + + if last_page: + # 从尾页URL中提取页码 + page_match = re.search(r'/page/(\d+)\.html', last_page) + if page_match: + pagecount = int(page_match.group(1)) + total = pagecount * 20 # 估算总数 + except: + pass + + return { + 'list': videos, + 'page': int(pg), + 'pagecount': pagecount, + 'limit': 20, + 'total': total + } + except Exception as e: + self.log(f"搜索出错: {str(e)}") + return {'list': []} + + def detailContent(self, ids): + """详情页面 - 特别处理特殊分区的链接""" + try: + vid = ids[0] + + # 检查是否是特殊分区的链接 + if vid.startswith('special_'): + # 解析特殊分区ID格式: special_{category_id}_{video_id}_{encoded_url} + parts = vid.split('_') + if len(parts) >= 4: + category_id = parts[1] + video_id = parts[2] + encoded_url = '_'.join(parts[3:]) + play_url = urllib.parse.unquote(encoded_url) + + self.log(f"特殊分区视频,直接使用链接: {play_url}") + + # 从播放链接中提取视频URL + parsed_url = urllib.parse.urlparse(play_url) + query_params = urllib.parse.parse_qs(parsed_url.query) + video_url = query_params.get('v', [''])[0] + pic_url = query_params.get('b', [''])[0] + title_encrypted = query_params.get('m', [''])[0] + + # 解码标题 + title = self._decrypt_title(title_encrypted) + + return { + 'list': [{ + 'vod_id': vid, + 'vod_name': title, + 'vod_pic': pic_url, + 'vod_remarks': '', + 'vod_year': '', + 'vod_play_from': '直接播放', + 'vod_play_url': f"第1集${play_url}" + }] + } + + # 常规处理 + if '_' in vid and len(vid.split('_')) > 2: + domain, category_id, video_id = vid.split('_') + else: + domain, video_id = vid.split('_') + + detail_url = f"https://{domain}/index.php/vod/detail/id/{video_id}.html" + + self.log(f"访问详情URL: {detail_url}") + rsp = self.fetch(detail_url, headers=self.headers) + doc = self.html(rsp.text) + video_info = self._get_detail(doc, rsp.text, vid) + return {'list': [video_info]} if video_info else {'list': []} + except Exception as e: + self.log(f"详情获取出错: {str(e)}") + return {'list': []} + + def playerContent(self, flag, id, vipFlags): + """播放链接 - 特别处理特殊分区的链接""" + try: + self.log(f"获取播放链接: flag={flag}, id={id}") + + # 检查是否是特殊分区的链接 + if id.startswith('special_'): + # 解析特殊分区ID格式: special_{category_id}_{video_id}_{encoded_url} + parts = id.split('_') + if len(parts) >= 4: + category_id = parts[1] + video_id = parts[2] + encoded_url = '_'.join(parts[3:]) + play_url = urllib.parse.unquote(encoded_url) + + self.log(f"特殊分区视频,直接使用链接: {play_url}") + + # 从播放链接中提取视频URL + parsed_url = urllib.parse.urlparse(play_url) + query_params = urllib.parse.parse_qs(parsed_url.query) + video_url = query_params.get('v', [''])[0] + + if video_url: + # 确保URL是完整的 + if video_url.startswith('//'): + video_url = 'https:' + video_url + elif not video_url.startswith('http'): + video_url = urljoin(self.host, video_url) + + self.log(f"从特殊链接中提取到视频地址: {video_url}") + return {'parse': 0, 'playUrl': '', 'url': video_url} + + # 检查传入的ID是否为完整URL,如果是则直接解析 + if id.startswith('http'): + self.log("ID 是一个完整URL,直接解析参数") + parsed_url = urllib.parse.urlparse(id) + query_params = urllib.parse.parse_qs(parsed_url.query) + + # 尝试获取视频参数 + video_url = query_params.get('v', [''])[0] + if not video_url: + # 尝试其他可能的参数名 + for key in query_params: + if key in ['url', 'src', 'file']: + video_url = query_params[key][0] + break + + if video_url: + # 解码可能的URL编码 + video_url = urllib.parse.unquote(video_url) + # 确保URL是完整的 + if video_url.startswith('//'): + video_url = 'https:' + video_url + elif not video_url.startswith('http'): + # 尝试添加基本域名 + video_url = urljoin(self.host, video_url) + + self.log(f"从 URL 参数中提取到视频地址: {video_url}") + return {'parse': 0, 'playUrl': '', 'url': video_url} + else: + self.log("URL 中没有找到视频参数,尝试从页面提取") + # 请求页面并提取视频链接 + rsp = self.fetch(id, headers=self.headers) + if rsp and rsp.status_code == 200: + video_url = self._extract_direct_video_url(rsp.text) + if video_url: + self.log(f"从页面提取到视频地址: {video_url}") + return {'parse': 0, 'playUrl': '', 'url': video_url} + + self.log("无法从页面提取视频链接,返回原始URL") + return {'parse': 1, 'playUrl': '', 'url': id} + + # 从新的 id 格式中提取视频ID和分类ID + if id.count('_') >= 2: + parts = id.split('_') + video_id = parts[-1] + category_id = parts[1] + else: + video_id = id.split('_')[-1] + category_id = '' + + self.log(f"视频ID: {video_id}, 分类ID: {category_id}") + + # 对于特殊分类,使用直接解析播放页面的方式 + if category_id in self.special_categories: + self.log("特殊分类,尝试从详情页提取直接播放链接") + # 构造播放页面URL + play_page_url = f"{self.host}/index.php/vod/play/id/{video_id}.html" + + # 请求播放页面 + rsp = self.fetch(play_page_url, headers=self.headers) + if rsp and rsp.status_code == 200: + # 从页面提取视频链接 + video_url = self._extract_direct_video_url(rsp.text) + if video_url: + self.log(f"从播放页面提取到视频地址: {video_url}") + return {'parse': 0, 'playUrl': '', 'url': video_url} + + # 如果提取失败,回退到API方式 + self.log("从播放页面提取失败,尝试API方式") + return self._get_video_by_api(id, video_id) + else: + # 其他分类使用API方式 + self.log("使用API方式获取视频地址") + return self._get_video_by_api(id, video_id) + + except Exception as e: + self.log(f"播放链接获取出错: {str(e)}") + if '_' in id: + domain, play_id = id.split('_') + play_url = f"https://{domain}/html/kkyd.html?m={play_id}" + else: + play_url = f"{self.host}/html/kkyd.html?m={id}" + return {'parse': 1, 'playUrl': '', 'url': play_url} + + def _get_video_by_api(self, id, video_id): + """通过API获取视频地址""" + try: + api_url = f"{self.api_host}/api/v2/vod/reqplay/{video_id}" + self.log(f"请求API获取视频地址: {api_url}") + + api_headers = self.headers.copy() + api_headers.update({ + 'Referer': f"{self.host}/", + 'Origin': self.host, + 'X-Requested-With': 'XMLHttpRequest' + }) + + api_response = self.fetch(api_url, headers=api_headers) + if api_response and api_response.status_code == 200: + data = api_response.json() + self.log(f"API响应: {data}") + + if data.get('retcode') == 3: + video_url = data.get('data', {}).get('httpurl_preview', '') + else: + video_url = data.get('data', {}).get('httpurl', '') + + if video_url: + video_url = video_url.replace('?300', '') + self.log(f"从API获取到视频地址: {video_url}") + return {'parse': 0, 'playUrl': '', 'url': video_url} + else: + self.log("API响应中没有找到视频地址") + else: + self.log(f"API请求失败,状态码: {api_response.status_code if api_response else '无响应'}") + + if '_' in id: + domain, play_id = id.split('_') + play_url = f"https://{domain}/html/kkyd.html?m={play_id}" + else: + play_url = f"{self.host}/html/kkyd.html?m={id}" + self.log(f"API请求失败,回退到播放页面: {play_url}") + return {'parse': 1, 'playUrl': '', 'url': play_url} + + except Exception as e: + self.log(f"API方式获取视频出错: {str(e)}") + if '_' in id: + domain, play_id = id.split('_') + play_url = f"https://{domain}/html/kkyd.html?m={play_id}" + else: + play_url = f"{self.host}/html/kkyd.html?m={id}" + return {'parse': 1, 'playUrl': '', 'url': play_url} + + def _extract_direct_video_url(self, html_content): + """从HTML内容中提取直接播放链接 (优化版)""" + try: + # 首先尝试提取明显的视频链接 + patterns = [ + r'v=([^&]+\.(?:m3u8|mp4))', + r'"url"\s*:\s*["\']([^"\']+\.(?:mp4|m3u8))["\']', + r'src\s*=\s*["\']([^"\']+\.(?:mp4|m3u8))["\']', + r'http[^\s<>"\'?]+\.(?:mp4|m3u8)' + ] + + for pattern in patterns: + matches = re.findall(pattern, html_content, re.IGNORECASE) + for match in matches: + if isinstance(match, tuple): + match = match[0] + extracted_url = match.replace('\\', '') + extracted_url = urllib.parse.unquote(extracted_url) + + if extracted_url.startswith('//'): + extracted_url = 'https:' + extracted_url + elif extracted_url.startswith('http'): + return extracted_url + + return None + except Exception as e: + self.log(f"提取直接播放URL出错: {str(e)}") + return None + + def _get_videos(self, doc, category_id=None, limit=None): + """获取影片列表 - 根据实际网站结构""" + try: + videos = [] + elements = doc.xpath('//a[@class="vodbox"]') + self.log(f"找到 {len(elements)} 个vodbox元素") + for elem in elements: + video = self._extract_video(elem, category_id) + if video: + videos.append(video) + return videos[:limit] if limit and videos else videos + except Exception as e: + self.log(f"获取影片列表出错: {str(e)}") + return [] + + def _extract_video(self, element, category_id=None): + """提取影片信息 - 特别处理特殊分区的链接""" + try: + link = element.xpath('./qyg10.js')[0] + if link.startswith('/'): + link = self.host + link + + # 检查是否是特殊分区的链接 + is_special_link = 'ar-kk.html' in link or 'ar.html' in link + + # 对于特殊分区,直接使用链接本身作为ID + if is_special_link and category_id in self.special_categories: + # 提取链接中的参数 + parsed_url = urllib.parse.urlparse(link) + query_params = urllib.parse.parse_qs(parsed_url.query) + + # 获取视频ID(从v参数中提取) + video_url = query_params.get('v', [''])[0] + if video_url: + # 从视频URL中提取ID + video_id_match = re.search(r'/([a-f0-9-]+)/video\.m3u8', video_url) + if video_id_match: + video_id = video_id_match.group(1) + else: + # 如果没有匹配到,使用哈希值 + video_id = str(hash(link) % 1000000) + else: + video_id = str(hash(link) % 1000000) + + # 对于特殊分区,保留完整的链接作为vod_id的一部分 + final_vod_id = f"special_{category_id}_{video_id}_{urllib.parse.quote(link)}" + else: + # 常规处理 + vod_id = self.regStr(r'm=(\d+)', link) + if not vod_id: + vod_id = str(hash(link) % 1000000) + + final_vod_id = f"618041.xyz_{vod_id}" + if category_id: + final_vod_id = f"618041.xyz_{category_id}_{vod_id}" + + # 提取标题 + title_elem = element.xpath('./qyg12.js') + if not title_elem: + title_elem = element.xpath('.//p[contains(@class, "script")]/text()') + if not title_elem: + title_elem = element.xpath('./qyg13.js') + if not title_elem: + title_elem = element.xpath('./qyg14.js') + if not title_elem: + title_elem = element.xpath('./qyg15.js') + if not title_elem: + self.log(f"未找到标题元素,跳过该视频") + return None + + title_encrypted = title_elem[0].strip() + title = self._decrypt_title(title_encrypted) + + # 提取图片 + pic_elem = element.xpath('./qyg16.js') + if not pic_elem: + pic_elem = element.xpath('./qyg17.js') + pic = pic_elem[0] if pic_elem else '' + + if pic: + if pic.startswith('//'): + pic = 'https:' + pic + elif pic.startswith('/'): + pic = self.host + pic + + return { + 'vod_id': final_vod_id, + 'vod_name': title, + 'vod_pic': pic, + 'vod_remarks': '', + 'vod_year': '' + } + except Exception as e: + self.log(f"提取影片信息出错: {str(e)}") + return None + + def _decrypt_title(self, encrypted_text): + """解密标题 - 使用网站的解密算法""" + try: + decrypted_chars = [] + for char in encrypted_text: + code_point = ord(char) + decrypted_code = code_point ^ 128 + decrypted_char = chr(decrypted_code) + decrypted_chars.append(decrypted_char) + + decrypted_text = ''.join(decrypted_chars) + return decrypted_text + except Exception as e: + self.log(f"标题解密失败: {str(e)}") + return encrypted_text + + def _get_detail(self, doc, html_content, vid): + """获取详情信息 (优化版) - 修复播放源提取问题""" + try: + title = self._get_text(doc, ['//h1/text()', '//title/text()']) + pic = self._get_text(doc, ['//div[contains(@class,"dyimg")]//img/@src', '//img[contains(@class,"poster")]/@src']) + if pic and pic.startswith('/'): + pic = self.host + pic + desc = self._get_text(doc, ['//div[contains(@class,"yp_context")]/text()', '//div[contains(@class,"introduction")]//text()']) + actor = self._get_text(doc, ['//span[contains(text(),"主演")]/following-sibling::*/text()']) + director = self._get_text(doc, ['//span[contains(text(),"导演")]/following-sibling::*/text()']) + + play_from = [] + play_urls = [] + + # 使用更灵活的正则匹配来查找播放链接 + player_link_patterns = [ + re.compile(r'href="(.*?ar\.html.*?)"'), + re.compile(r'href="(.*?kkyd\.html.*?)"'), + re.compile(r'href="(.*?ar-kk\.html.*?)"') + ] + + player_links = [] + for pattern in player_link_patterns: + matches = pattern.findall(html_content) + player_links.extend(matches) + + if player_links: + episodes = [] + for link in player_links: + full_url = urljoin(self.host, link) + episodes.append(f"第1集${full_url}") + + if episodes: + play_from.append("默认播放源") + play_urls.append('#'.join(episodes)) + + if not play_from: + self.log("未找到播放源元素,无法定位播放源列表") + return { + 'vod_id': vid, + 'vod_name': title, + 'vod_pic': pic, + 'type_name': '', + 'vod_year': '', + 'vod_area': '', + 'vod_remarks': '', + 'vod_actor': actor, + 'vod_director': director, + 'vod_content': desc, + 'vod_play_from': '默认播放源', + 'vod_play_url': f"第1集${vid}" + } + + return { + 'vod_id': vid, + 'vod_name': title, + 'vod_pic': pic, + 'type_name': '', + 'vod_year': '', + 'vod_area': '', + 'vod_remarks': '', + 'vod_actor': actor, + 'vod_director': director, + 'vod_content': desc, + 'vod_play_from': '$$$'.join(play_from), + 'vod_play_url': '$$$'.join(play_urls) + } + except Exception as e: + self.log(f"获取详情出错: {str(e)}") + return None + + def _get_text(self, doc, selectors): + """通用文本提取""" + for selector in selectors: + try: + texts = doc.xpath(selector) + for text in texts: + if text and text.strip(): + return text.strip() + except: + continue + return '' + + def log(self, message): + """日志输出""" + print(f"[苹果视频] {message}") + + def fetch(self, url, headers=None, method='GET', data=None, timeout=10): + """网络请求""" + try: + if headers is None: + headers = self.headers + if method == 'GET': + response = requests.get(url, headers=headers, timeout=timeout, verify=False) + else: + response = requests.post(url, headers=headers, data=data, timeout=timeout, verify=False) + return response + except Exception as e: + self.log(f"网络请求失败: {url}, 错误: {str(e)}") + return None + +# 注册爬虫 +if __name__ == '__main__': + from base.spider import Spider as BaseSpider + BaseSpider.register(Spider()) \ No newline at end of file diff --git a/lib/apiv1821小红薯APP.py b/lib/apiv1821小红薯APP.py new file mode 100644 index 0000000..adc57c7 --- /dev/null +++ b/lib/apiv1821小红薯APP.py @@ -0,0 +1,186 @@ +# -*- coding: utf-8 -*- +# by @嗷呜 +import json +import random +import string +import sys +import time +from base64 import b64decode +from Crypto.Cipher import AES +from Crypto.Hash import MD5 +from Crypto.Util.Padding import unpad +sys.path.append('..') +from base.spider import Spider + + +class Spider(Spider): + + def init(self, extend=""): + self.did = self.getdid() + self.token,self.phost,self.host = self.gettoken() + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def destroy(self): + pass + + hs = ['fhoumpjjih', 'dyfcbkggxn', 'rggwiyhqtg', 'bpbbmplfxc'] + + def homeContent(self, filter): + data = self.fetch(f'{self.host}/api/video/queryClassifyList?mark=4', headers=self.headers()).json()['encData'] + data1 = self.aes(data) + result = {} + classes = [] + for k in data1['data']: + classes.append({'type_name': k['classifyTitle'], 'type_id': k['classifyId']}) + result['class'] = classes + return result + + def homeVideoContent(self): + pass + + def categoryContent(self, tid, pg, filter, extend): + path=f'/api/short/video/getShortVideos?classifyId={tid}&videoMark=4&page={pg}&pageSize=20' + result = {} + videos = [] + data=self.fetch(f'{self.host}{path}', headers=self.headers()).json()['encData'] + vdata=self.aes(data) + for k in vdata['data']: + videos.append({"vod_id": k['videoId'], 'vod_name': k.get('title'), 'vod_pic': self.getProxyUrl() + '&url=' + k['coverImg'], + 'vod_remarks': self.dtim(k.get('playTime')),'style': {"type": "rect", "ratio": 1.33}}) + result["list"] = videos + result["page"] = pg + result["pagecount"] = 9999 + result["limit"] = 90 + result["total"] = 999999 + return result + + def detailContent(self, ids): + path = f'/api/video/getVideoById?videoId={ids[0]}' + data = self.fetch(f'{self.host}{path}', headers=self.headers()).json()['encData'] + v = self.aes(data) + d=f'{v["title"]}$auth_key={v["authKey"]}&path={v["videoUrl"]}' + vod = {'vod_name': v["title"], 'type_name': ''.join(v.get('tagTitles',[])),'vod_play_from': v.get('nickName') or "小红书官方", 'vod_play_url': d} + result = {"list": [vod]} + return result + + def searchContent(self, key, quick, pg='1'): + pass + + def playerContent(self, flag, id, vipFlags): + h=self.headers() + h['Authorization'] = h.pop('aut') + del h['deviceid'] + result = {"parse": 0, "url": f"{self.host}/api/m3u8/decode/authPath?{id}", "header": h} + return result + + def localProxy(self, param): + return self.action(param) + + def md5(self, text): + h = MD5.new() + h.update(text.encode('utf-8')) + return h.hexdigest() + + def aes(self, word): + key = b64decode("SmhiR2NpT2lKSVV6STFOaQ==") + iv = key + cipher = AES.new(key, AES.MODE_CBC, iv) + decrypted = unpad(cipher.decrypt(b64decode(word)), AES.block_size) + return json.loads(decrypted.decode('utf-8')) + + def dtim(self, seconds): + try: + seconds = int(seconds) + hours = seconds // 3600 + remaining_seconds = seconds % 3600 + minutes = remaining_seconds // 60 + remaining_seconds = remaining_seconds % 60 + + formatted_minutes = str(minutes).zfill(2) + formatted_seconds = str(remaining_seconds).zfill(2) + + if hours > 0: + formatted_hours = str(hours).zfill(2) + return f"{formatted_hours}:{formatted_minutes}:{formatted_seconds}" + else: + return f"{formatted_minutes}:{formatted_seconds}" + except: + return '' + + def getdid(self): + did = self.getCache('did') + if not did: + t = str(int(time.time())) + did = self.md5(t) + self.setCache('did', did) + return did + + def getsign(self): + t=str(int(time.time() * 1000)) + return self.md5(t[3:8]),t + + def gettoken(self, i=0, max_attempts=10): + if i >= len(self.hs) or i >= max_attempts: + return '' + current_domain = f"https://{''.join(random.choices(string.ascii_lowercase + string.digits, k=random.randint(5, 10)))}.{self.hs[i]}.work" + try: + sign,t=self.getsign() + url = f'{current_domain}/api/user/traveler' + headers = { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 11; M2012K10C Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36;SuiRui/xhs/ver=1.2.6', + 'deviceid': self.did, 't': t, 's': sign, } + data = {'deviceId': self.did, 'tt': 'U', 'code': '', 'chCode': 'dafe13'} + data1 = self.post(url, json=data, headers=headers) + data1.raise_for_status() + data2 = data1.json()['data'] + return data2['token'], data2['imgDomain'],current_domain + except: + return self.gettoken(i+1, max_attempts) + + def headers(self): + sign,t=self.getsign() + henda = { + 'User-Agent': 'Mozilla/5.0 (Linux; Android 11; M2012K10C Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36;SuiRui/xhs/ver=1.2.6', + 'deviceid': self.did, 't': t, 's': sign, 'aut': self.token} + return henda + + def action(self, param): + headers = { + 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 11; M2012K10C Build/RP1A.200720.011)'} + data = self.fetch(f'{self.phost}{param["url"]}', headers=headers) + type=data.headers.get('Content-Type').split(';')[0] + base64_data = self.img(data.content, 100, '2020-zq3-888') + return [200, type, base64_data] + + def img(self, data: bytes, length: int, key: str): + GIF = b'\x47\x49\x46' + JPG = b'\xFF\xD8\xFF' + PNG = b'\x89\x50\x4E\x47\x0D\x0A\x1A\x0A' + + def is_dont_need_decode_for_gif(data): + return len(data) > 2 and data[:3] == GIF + + def is_dont_need_decode_for_jpg(data): + return len(data) > 7 and data[:3] == JPG + + def is_dont_need_decode_for_png(data): + return len(data) > 7 and data[1:8] == PNG[1:8] + + if is_dont_need_decode_for_png(data): + return data + elif is_dont_need_decode_for_gif(data): + return data + elif is_dont_need_decode_for_jpg(data): + return data + else: + key_bytes = key.encode('utf-8') + result = bytearray(data) + for i in range(length): + result[i] ^= key_bytes[i % len(key_bytes)] + return bytes(result) diff --git a/lib/apiv323推特APP.py b/lib/apiv323推特APP.py new file mode 100644 index 0000000..ec4c155 --- /dev/null +++ b/lib/apiv323推特APP.py @@ -0,0 +1,246 @@ +# -*- coding: utf-8 -*- +# by @嗷呜 +import json +import random +import string +import sys +import time +from base64 import b64decode +from urllib.parse import quote +from Crypto.Cipher import AES +from Crypto.Hash import MD5 +from Crypto.Util.Padding import unpad +sys.path.append('..') +from base.spider import Spider + + +class Spider(Spider): + + def init(self, extend=""): + self.did = self.getdid() + self.token,self.phost,self.host = self.gettoken() + pass + + def isVideoFormat(self, url): + pass + + def manualVideoCheck(self): + pass + + def action(self, action): + pass + + def destroy(self): + pass + + hs=['wcyfhknomg','pdcqllfomw','alxhzjvean','bqeaaxzplt','hfbtpixjso'] + + ua='Mozilla/5.0 (Linux; Android 11; M2012K10C Build/RP1A.200720.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.141 Mobile Safari/537.36;SuiRui/twitter/ver=1.4.4' + + def homeContent(self, filter): + data = self.fetch(f'{self.host}/api/video/classifyList', headers=self.headers()).json()['encData'] + data1 = self.aes(data) + result = {'filters': {"1": [{"key": "fl", "name": "分类", + "value": [{"n": "最近更新", "v": "1"}, {"n": "最多播放", "v": "2"}, + {"n": "好评榜", "v": "3"}]}], "2": [{"key": "fl", "name": "分类", + "value": [ + {"n": "最近更新", "v": "1"}, + {"n": "最多播放", "v": "2"}, + {"n": "好评榜", "v": "3"}]}], + "3": [{"key": "fl", "name": "分类", + "value": [{"n": "最近更新", "v": "1"}, {"n": "最多播放", "v": "2"}, + {"n": "好评榜", "v": "3"}]}], "4": [{"key": "fl", "name": "分类", + "value": [ + {"n": "最近更新", "v": "1"}, + {"n": "最多播放", "v": "2"}, + {"n": "好评榜", "v": "3"}]}], + "5": [{"key": "fl", "name": "分类", + "value": [{"n": "最近更新", "v": "1"}, {"n": "最多播放", "v": "2"}, + {"n": "好评榜", "v": "3"}]}], "6": [{"key": "fl", "name": "分类", + "value": [ + {"n": "最近更新", "v": "1"}, + {"n": "最多播放", "v": "2"}, + {"n": "好评榜", "v": "3"}]}], + "7": [{"key": "fl", "name": "分类", + "value": [{"n": "最近更新", "v": "1"}, {"n": "最多播放", "v": "2"}, + {"n": "好评榜", "v": "3"}]}], "jx": [{"key": "type", "name": "精选", + "value": [{"n": "日榜", "v": "1"}, + {"n": "周榜", "v": "2"}, + {"n": "月榜", "v": "3"}, + {"n": "总榜", + "v": "4"}]}]}} + classes = [{'type_name': "精选", 'type_id': "jx"}] + for k in data1['data']: + classes.append({'type_name': k['classifyTitle'], 'type_id': k['classifyId']}) + result['class'] = classes + return result + + def homeVideoContent(self): + pass + + def categoryContent(self, tid, pg, filter, extend): + path = f'/api/video/queryVideoByClassifyId?pageSize=20&page={pg}&classifyId={tid}&sortType={extend.get("fl", "1")}' + if 'click' in tid: + path = f'/api/video/queryPersonVideoByType?pageSize=20&page={pg}&userId={tid.replace("click", "")}' + if tid == 'jx': + path = f'/api/video/getRankVideos?pageSize=20&page={pg}&type={extend.get("type", "1")}' + data = self.fetch(f'{self.host}{path}', headers=self.headers()).json()['encData'] + data1 = self.aes(data)['data'] + result = {} + videos = [] + for k in data1: + id = f'{k.get("videoId")}?{k.get("userId")}?{k.get("nickName")}' + if 'click' in tid: + id = id + 'click' + videos.append({"vod_id": id, 'vod_name': k.get('title'), 'vod_pic': self.getProxyUrl() + f"&url={k.get('coverImg')[0]}", + 'vod_remarks': self.dtim(k.get('playTime')),'style': {"type": "rect", "ratio": 1.33}}) + result["list"] = videos + result["page"] = pg + result["pagecount"] = 9999 + result["limit"] = 90 + result["total"] = 999999 + return result + + def detailContent(self, ids): + vid = ids[0].replace('click', '').split('?') + path = f'/api/video/can/watch?videoId={vid[0]}' + data = self.fetch(f'{self.host}{path}', headers=self.headers()).json()['encData'] + data1 = self.aes(data)['playPath'] + clj = '[a=cr:' + json.dumps({'id': vid[1] + 'click', 'name': vid[2]}) + '/]' + vid[2] + '[/a]' + if 'click' in ids[0]: + clj = vid[2] + vod = {'vod_director': clj, 'vod_play_from': "推特", 'vod_play_url': vid[2] + "$" + data1} + result = {"list": [vod]} + return result + + def searchContent(self, key, quick, pg='1'): + path = f'/api/search/keyWord?pageSize=20&page={pg}&searchWord={quote(key)}&searchType=1' + data = self.fetch(f'{self.host}{path}', headers=self.headers()).json()['encData'] + data1 = self.aes(data)['videoList'] + result = {} + videos = [] + for k in data1: + id = f'{k.get("videoId")}?{k.get("userId")}?{k.get("nickName")}' + videos.append({"vod_id": id, 'vod_name': k.get('title'), 'vod_pic': self.getProxyUrl() + f"&url={k.get('coverImg')[0]}", + 'vod_remarks': self.dtim(k.get('playTime')), 'style': {"type": "rect", "ratio": 1.33}}) + result["list"] = videos + result["page"] = pg + result["pagecount"] = 9999 + result["limit"] = 90 + result["total"] = 999999 + return result + + def playerContent(self, flag, id, vipFlags): + return {"parse": 0, "url": id, "header": self.headers()} + + def localProxy(self, param): + return self.imgs(param) + + def getsign(self): + t = str(int(time.time() * 1000)) + sign = self.md5(t) + return sign, t + + def headers(self): + sign, t = self.getsign() + return {'User-Agent': self.ua,'deviceid': self.did, 't': t, 's': sign, 'aut': self.token} + + def aes(self, word): + key = b64decode("SmhiR2NpT2lKSVV6STFOaQ==") + iv = key + cipher = AES.new(key, AES.MODE_CBC, iv) + decrypted = unpad(cipher.decrypt(b64decode(word)), AES.block_size) + return json.loads(decrypted.decode('utf-8')) + + def dtim(self, seconds): + try: + seconds = int(seconds) + hours = seconds // 3600 + remaining_seconds = seconds % 3600 + minutes = remaining_seconds // 60 + remaining_seconds = remaining_seconds % 60 + + formatted_minutes = str(minutes).zfill(2) + formatted_seconds = str(remaining_seconds).zfill(2) + + if hours > 0: + formatted_hours = str(hours).zfill(2) + return f"{formatted_hours}:{formatted_minutes}:{formatted_seconds}" + else: + return f"{formatted_minutes}:{formatted_seconds}" + except: + return "666" + + def gettoken(self, i=0, max_attempts=10): + if i >= len(self.hs) or i >= max_attempts: + return '' + current_domain = f"https://{''.join(random.choices(string.ascii_lowercase + string.digits, k=random.randint(5, 10)))}.{self.hs[i]}.work" + try: + url = f'{current_domain}/api/user/traveler' + sign, t = self.getsign() + headers = { + 'User-Agent': self.ua, + 'Accept': 'application/json', + 'deviceid': self.did, + 't': t, + 's': sign, + } + data = { + 'deviceId': self.did, + 'tt': 'U', + 'code': '##X-4m6Goo4zzPi1hF##', + 'chCode': 'tt09' + } + response = self.post(url, json=data, headers=headers) + response.raise_for_status() + data1 = response.json()['data'] + return data1['token'], data1['imgDomain'], current_domain + except Exception as e: + return self.gettoken(i + 1, max_attempts) + + def getdid(self): + did = self.getCache('did') + if not did: + t = str(int(time.time())) + did = self.md5(t) + self.setCache('did', did) + return did + + def md5(self, text): + h = MD5.new() + h.update(text.encode('utf-8')) + return h.hexdigest() + + def imgs(self, param): + headers = {'User-Agent': self.ua} + url = param['url'] + data = self.fetch(f"{self.phost}{url}",headers=headers) + bdata = self.img(data.content, 100, '2020-zq3-888') + return [200, data.headers.get('Content-Type'), bdata] + + def img(self, data: bytes, length: int, key: str): + GIF = b'\x47\x49\x46' + JPG = b'\xFF\xD8\xFF' + PNG = b'\x89\x50\x4E\x47\x0D\x0A\x1A\x0A' + + def is_dont_need_decode_for_gif(data): + return len(data) > 2 and data[:3] == GIF + + def is_dont_need_decode_for_jpg(data): + return len(data) > 7 and data[:3] == JPG + + def is_dont_need_decode_for_png(data): + return len(data) > 7 and data[1:8] == PNG[1:8] + + if is_dont_need_decode_for_png(data): + return data + elif is_dont_need_decode_for_gif(data): + return data + elif is_dont_need_decode_for_jpg(data): + return data + else: + key_bytes = key.encode('utf-8') + result = bytearray(data) + for i in range(length): + result[i] ^= key_bytes[i % len(key_bytes)] + return bytes(result) diff --git a/lib/apiv3756apiv2134色播.js b/lib/apiv3756apiv2134色播.js new file mode 100644 index 0000000..0d4f09b --- /dev/null +++ b/lib/apiv3756apiv2134色播.js @@ -0,0 +1,98 @@ +import { Crypto, load, _ } from 'assets://js/lib/cat.js'; +/** + * 直播源 + * author:Leospring + */ + +let siteUrl = 'http://api.maiyoux.com:81/mf/'; +let siteKey = ''; +let siteType = 0; +let cateList = {}; +async function request(reqUrl, postData, post) { + + let res = await req(reqUrl, { + method: post ? 'post' : 'get', + data: postData || {}, + postType: post ? 'form' : '', + }); + let content = res.content; + return content; +} + +async function init(cfg) { + siteKey = cfg.skey; + siteType = cfg.stype; + if (cfg.ext) { + siteUrl = cfg.ext; + } + cateList = JSON.parse(await request(siteUrl + 'json.txt')); +} + +async function home(filter) { + let classes = []; + Object.keys(cateList).forEach(function(key) { + classes.push({ + type_id: key, + type_name: key, + }); + }); + return JSON.stringify({ + class: classes, + // filters: filterObj + }); +} + +async function category(tid, pg, filter, ext) { + let videos = _.map(cateList[tid], (item) => { + return { + vod_id: item['address'], + vod_name: item['title'], + vod_pic: item['xinimg'], + vod_remarks: item['Number'] + } + }) + return JSON.stringify({ + list: videos, + page: pg, + pagecount: 1, + total: videos.length + }); +} + +async function detail(id) { + try { + const res = JSON.parse(await request(siteUrl + id))['zhubo']; + let playUrls = _.map(res, (vod) => { + return vod.title + '$' + vod.address; + }).join('#'); + const video = { + vod_play_from: 'Leospring', + vod_play_url: playUrls, + vod_content: '作者:Leospring 公众号:蚂蚁科技杂谈', + }; + const list = [video]; + const result = { list }; + return JSON.stringify(result); + } catch (e) { + console.log('err', e); + } + return null; +} + +async function play(flag, id, flags) { + let playUrl = id; + return JSON.stringify({ + parse: 0, + url: playUrl, + }); +} + +export function __jsEvalReturn() { + return { + init: init, + home: home, + category: category, + detail: detail, + play: play, + }; +} \ No newline at end of file diff --git a/lib/apiv583lf_live_min.js b/lib/apiv583lf_live_min.js new file mode 100644 index 0000000..d6d5bd2 --- /dev/null +++ b/lib/apiv583lf_live_min.js @@ -0,0 +1 @@ +const _0x3c0fe8=_0x38f3;(function(_0x187a6e,_0x56e928){const _0x230888=_0x38f3,_0x3a97a5=_0x187a6e();while(!![]){try{const _0x5ca0fe=-parseInt(_0x230888(0x13d))/0x1+parseInt(_0x230888(0x194))/0x2+parseInt(_0x230888(0x137))/0x3*(-parseInt(_0x230888(0x13a))/0x4)+-parseInt(_0x230888(0x1a2))/0x5*(parseInt(_0x230888(0x1aa))/0x6)+-parseInt(_0x230888(0x158))/0x7*(parseInt(_0x230888(0x12f))/0x8)+parseInt(_0x230888(0x13c))/0x9+-parseInt(_0x230888(0x18a))/0xa*(-parseInt(_0x230888(0x17a))/0xb);if(_0x5ca0fe===_0x56e928)break;else _0x3a97a5['push'](_0x3a97a5['shift']());}catch(_0x1dad60){_0x3a97a5['push'](_0x3a97a5['shift']());}}}(_0x8dec,0xc58a5));function m_decode(_0xc80413){const _0x36f09e=_0x38f3;var _0x3893e9=_0x36f09e(0x180),_0x2a04dd,_0x5bfb1a,_0x29b813,_0x46e6fc,_0x59d57c,_0x22eb7c,_0x92bc4,_0x166eb1,_0xade4c5=0x0,_0x542b56=0x0,_0x550948='',_0x4b1441=[];if(!_0xc80413)return _0xc80413;_0xc80413+='';do{_0x46e6fc=_0x3893e9[_0x36f09e(0x192)](_0xc80413['charAt'](_0xade4c5++)),_0x59d57c=_0x3893e9[_0x36f09e(0x192)](_0xc80413['charAt'](_0xade4c5++)),_0x22eb7c=_0x3893e9['indexOf'](_0xc80413[_0x36f09e(0x1a5)](_0xade4c5++)),_0x92bc4=_0x3893e9[_0x36f09e(0x192)](_0xc80413[_0x36f09e(0x1a5)](_0xade4c5++)),_0x166eb1=_0x46e6fc<<0x12|_0x59d57c<<0xc|_0x22eb7c<<0x6|_0x92bc4,_0x2a04dd=_0x166eb1>>0x10&0xff,_0x5bfb1a=_0x166eb1>>0x8&0xff,_0x29b813=_0x166eb1&0xff,_0x22eb7c==0x40?_0x4b1441[_0x542b56++]=String[_0x36f09e(0x181)](_0x2a04dd):_0x92bc4==0x40?_0x4b1441[_0x542b56++]=String[_0x36f09e(0x181)](_0x2a04dd,_0x5bfb1a):_0x4b1441[_0x542b56++]=String[_0x36f09e(0x181)](_0x2a04dd,_0x5bfb1a,_0x29b813);}while(_0xade4c5<_0xc80413[_0x36f09e(0x185)]);return _0x550948=_0x4b1441[_0x36f09e(0x16b)](''),_0x550948;}function startPlayer(_0x153d48,_0x350412,_0x202898,_0x4ff90f){const _0x587110=_0x38f3;function _0x5b0b60(_0x4799d2,_0x5a4395){const _0x3fc893=_0x38f3;let _0x15ee81=_0x49a283(_0x4799d2),_0x323e22=_0x5a4395[_0x3fc893(0x185)],_0x3bea7='';for(let _0x543067=0x0;_0x543067<_0x15ee81[_0x3fc893(0x185)];_0x543067++){let _0x1d8d78=_0x543067%_0x323e22;_0x3bea7+=String[_0x3fc893(0x181)](_0x15ee81[_0x3fc893(0x169)](_0x543067)^_0x5a4395[_0x3fc893(0x169)](_0x1d8d78));}let _0x514f2e=_0x49a283(_0x3bea7);return _0x514f2e;}function _0x49a283(_0x3b77a4){const _0x288ebe=_0x38f3;var _0x2029f2=_0x288ebe(0x180),_0x1d0508,_0xcaceb9,_0x19656b,_0x394f55,_0x160a54,_0xec8cfd,_0x535b0d,_0x1f00ce,_0x458dae=0x0,_0x504a47=0x0,_0x1928e5='',_0x460106=[];if(!_0x3b77a4)return _0x3b77a4;_0x3b77a4+='';do{_0x394f55=_0x2029f2[_0x288ebe(0x192)](_0x3b77a4[_0x288ebe(0x1a5)](_0x458dae++)),_0x160a54=_0x2029f2[_0x288ebe(0x192)](_0x3b77a4['charAt'](_0x458dae++)),_0xec8cfd=_0x2029f2[_0x288ebe(0x192)](_0x3b77a4[_0x288ebe(0x1a5)](_0x458dae++)),_0x535b0d=_0x2029f2[_0x288ebe(0x192)](_0x3b77a4[_0x288ebe(0x1a5)](_0x458dae++)),_0x1f00ce=_0x394f55<<0x12|_0x160a54<<0xc|_0xec8cfd<<0x6|_0x535b0d,_0x1d0508=_0x1f00ce>>0x10&0xff,_0xcaceb9=_0x1f00ce>>0x8&0xff,_0x19656b=_0x1f00ce&0xff;if(_0xec8cfd==0x40)_0x460106[_0x504a47++]=String['fromCharCode'](_0x1d0508);else _0x535b0d==0x40?_0x460106[_0x504a47++]=String[_0x288ebe(0x181)](_0x1d0508,_0xcaceb9):_0x460106[_0x504a47++]=String[_0x288ebe(0x181)](_0x1d0508,_0xcaceb9,_0x19656b);}while(_0x458dae<_0x3b77a4[_0x288ebe(0x185)]);return _0x1928e5=_0x460106[_0x288ebe(0x16b)](''),_0x1928e5;}return _0x153d48=_0x153d48['split']('')['reverse']()[_0x587110(0x16b)](''),_0x153d48=_0x5b0b60(_0x153d48,_0x350412),_0x153d48=_0x153d48['replace'](_0x587110(0x146),_0x587110(0x150)+_0x4ff90f),_0x153d48=_0x153d48[_0x587110(0x14c)](_0x587110(0x150)+_0x202898,_0x587110(0x150)+_0x4ff90f),_0x153d48=_0x153d48[_0x587110(0x14c)](_0x350412,''),_0x153d48;}function m_parse_url(_0x2ee1ff){const _0x138182=_0x38f3;let _0x15d57f=_0x2ee1ff[_0x138182(0x188)]('&p=')[0x0],_0x2c70c9=_0x2ee1ff['split'](_0x138182(0x152))[0x1],_0x93058f=req(_0x15d57f,{'headers':config[_0x138182(0x149)]})[_0x138182(0x19d)],_0x146ee1=_0x1ba294[_0x138182(0x138)](_0x93058f);if(_0x2c70c9>=_0x146ee1(_0x138182(0x13b))[_0x138182(0x185)])return'';let _0x3d67f3=_0x146ee1(_0x138182(0x13b))['eq'](_0x2c70c9)[_0x138182(0x168)](),_0x1fe469=_0x93058f[_0x138182(0x167)](/