上传文件至「08/lib」
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
import base64
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import requests
|
||||
import re
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
class Spider(Spider):
|
||||
def getName(self):
|
||||
return "Litv"
|
||||
|
||||
def init(self, extend):
|
||||
self.extend = extend
|
||||
try:
|
||||
self.extendDict = json.loads(extend)
|
||||
except:
|
||||
self.extendDict = {}
|
||||
|
||||
proxy = self.extendDict.get('proxy', None)
|
||||
if proxy is None:
|
||||
self.is_proxy = False
|
||||
else:
|
||||
self.proxy = proxy
|
||||
self.is_proxy = True
|
||||
pass
|
||||
|
||||
def getDependence(self):
|
||||
return []
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
def natural_sort_key(self, s):
|
||||
"""
|
||||
自然排序辅助函数
|
||||
"""
|
||||
return [
|
||||
int(part) if part.isdigit() else part.lower()
|
||||
for part in re.split(r'(\d+)', s)
|
||||
]
|
||||
|
||||
def liveContent(self, url):
|
||||
m3u_content = ['#EXTM3U']
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36',
|
||||
'Referer': 'https://360pai.xyz/',
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get('https://360pai.xyz/live', headers=headers, timeout=10)
|
||||
response.raise_for_status()
|
||||
res = response.text
|
||||
soup = BeautifulSoup(res, 'html.parser')
|
||||
result = []
|
||||
|
||||
cards = soup.select('div.anchor-grid_anchor-card-wrap__NR9Ov')
|
||||
for card in cards:
|
||||
a_tag = card.find('a', class_='anchor-grid_anchor-card__nJf0J')
|
||||
if not a_tag:
|
||||
continue
|
||||
|
||||
href = a_tag.get('href', '')
|
||||
live_id_match = re.search(r'/live/([^/]+)', href)
|
||||
if not live_id_match:
|
||||
continue
|
||||
live_id = live_id_match.group(1)
|
||||
|
||||
title_div = a_tag.find('div', class_='anchor-grid_anchor-avatar-title__5hTsp')
|
||||
title = title_div.get_text(strip=True) if title_div else ''
|
||||
title = title.replace(" vs ","vs")
|
||||
if not title:
|
||||
continue
|
||||
|
||||
extinf = f'#EXTINF:-1 tvg-name="{title}" group-title="360pai",{title}'
|
||||
ch_url = f"video://https://360pai.xyz/live/{live_id}"
|
||||
|
||||
m3u_content.extend([extinf, ch_url])
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"网络请求失败: {e}")
|
||||
except Exception as e:
|
||||
print(f"处理过程中发生错误: {e}")
|
||||
return '\n'.join(m3u_content)
|
||||
|
||||
def homeContent(self, filter):
|
||||
return {}
|
||||
|
||||
def homeVideoContent(self):
|
||||
return {}
|
||||
|
||||
def categoryContent(self, cid, page, filter, ext):
|
||||
return {}
|
||||
|
||||
def detailContent(self, did):
|
||||
return {}
|
||||
|
||||
def searchContent(self, key, quick, page='1'):
|
||||
return {}
|
||||
|
||||
def searchContentPage(self, keywords, quick, page):
|
||||
return {}
|
||||
|
||||
def playerContent(self, flag, pid, vipFlags):
|
||||
return {}
|
||||
|
||||
def localProxy(self, params):
|
||||
if params['type'] == "m3u8":
|
||||
return self.proxyM3u8(params)
|
||||
if params['type'] == "ts":
|
||||
return self.get_ts(params)
|
||||
return [302, "text/plain", None, {'Location': 'https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4'}]
|
||||
|
||||
def proxyM3u8(self, params):
|
||||
pid = params['pid']
|
||||
info = pid.split(',')
|
||||
a = info[0]
|
||||
b = info[1]
|
||||
c = info[2]
|
||||
timestamp = int(time.time() / 4 - 355017625)
|
||||
t = timestamp * 4
|
||||
m3u8_text = f'#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:4\n#EXT-X-MEDIA-SEQUENCE:{timestamp}\n'
|
||||
for i in range(10):
|
||||
url = f'https://ntd-tgc.cdn.hinet.net/live/pool/{a}/litv-pc/{a}-avc1_6000000={b}-mp4a_134000_zho={c}-begin={t}0000000-dur=40000000-seq={timestamp}.ts'
|
||||
if self.is_proxy:
|
||||
url = f'http://127.0.0.1:9978/proxy?do=py&type=ts&url={self.b64encode(url)}'
|
||||
|
||||
m3u8_text += f'#EXTINF:4,\n{url}\n'
|
||||
timestamp += 1
|
||||
t += 4
|
||||
return [200, "application/vnd.apple.mpegurl", m3u8_text]
|
||||
|
||||
def get_ts(self, params):
|
||||
url = self.b64decode(params['url'])
|
||||
headers = {'User-Agent': 'Mozilla/5.0'}
|
||||
response = requests.get(url, headers=headers, stream=True, proxies=self.proxy)
|
||||
return [206, "application/octet-stream", response.content]
|
||||
|
||||
def destroy(self):
|
||||
return '正在Destroy'
|
||||
|
||||
def b64encode(self, data):
|
||||
return base64.b64encode(data.encode('utf-8')).decode('utf-8')
|
||||
|
||||
def b64decode(self, data):
|
||||
return base64.b64decode(data.encode('utf-8')).decode('utf-8')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
@@ -0,0 +1,28 @@
|
||||
var rule = {
|
||||
title:'360影视',
|
||||
host:'https://www.360kan.com',
|
||||
homeUrl:'https://api.web.360kan.com/v1/rank?cat=2&size=9',
|
||||
detailUrl:'https://api.web.360kan.com/v1/detail?cat=fyclass&id=fyid',
|
||||
searchUrl:'https://api.so.360kan.com/index?force_v=1&kw=**&from=&pageno=fypage&v_ap=1&tab=all',
|
||||
url:'https://api.web.360kan.com/v1/filter/list?catid=fyclass&rank=rankhot&cat=&year=&area=&act=&size=35&pageno=fypage&callback=',
|
||||
headers:{
|
||||
'User-Agent':'MOBILE_UA'
|
||||
},
|
||||
timeout:5000,
|
||||
class_name:'电视剧&电影&综艺&动漫',
|
||||
class_url:'2&1&3&4',
|
||||
limit:5,
|
||||
multi:1,
|
||||
searchable:2,
|
||||
play_parse:true,
|
||||
lazy:'js:input=input.split("?")[0];log(input);',
|
||||
// 疑似t4专用的
|
||||
// lazy:'js:input={parse: 1, playUrl: "", jx: 1, url: input.split("?")[0]}',
|
||||
// 手动调用解析请求json的url,此lazy不方便
|
||||
// lazy:'js:input="https://cache.json.icu/home/api?type=ys&uid=292796&key=fnoryABDEFJNPQV269&url="+input.split("?")[0];log(input);let html=JSON.parse(request(input));log(html);input=html.url||input',
|
||||
推荐:'json:data;title;cover;comment;cat+ent_id;description',
|
||||
一级:'json:data.movies;title;cover;pubdate;id;description',
|
||||
二级:'',
|
||||
二级:'js:let html=JSON.parse(fetch(input,fetch_params));let data=html.data;let tilte=data.title;let img=data.cdncover;let vod_type=data.moviecategory.join(",");let area=data.area.join(",");let director=data.director.join(",");let actor=data.actor.join(",");let content=data.description;let base_vod={vod_id:input,vod_name:tilte,type_name:vod_type,vod_actor:actor,vod_director:director,vod_content:content,vod_remarks:area,vod_pic:urljoin2(input,img)};let delta=200;let vod_play={};let sites=data.playlink_sites;sites.forEach(function(site){let playList="";let vodItems=[];if(data.allupinfo){let total=parseInt(data.allupinfo[site]);for(let j=1;j<total;j+=delta){let end=Math.min(total,j+delta-1);let url2=buildUrl(input,{start:j,end:end,site:site});let vod_data=JSON.parse(fetch(url2),fetch_params).data;if(vod_data.allepidetail){vod_data=vod_data.allepidetail[site];vod_data.forEach(function(item,index){vodItems.push((item.playlink_num||"")+"$"+urlDeal(item.url||""))})}else{vod_data=vod_data.defaultepisode;vod_data.forEach(function(item,index){vodItems.push((item.period||"")+(item.name||"")+"$"+urlDeal(item.url)||"")})}}}else{let item=data.playlinksdetail[site];vodItems.push((item.sort||"")+"$"+urlDeal(item.default_url||""))}if(vodItems.length>0){playList=vodItems.join("#")}if(playList.length<1){return}vod_play[site]=playList});let tabs=Object.keys(vod_play);let playUrls=[];for(let id in tabs){print("id:"+id);playUrls.push(vod_play[tabs[id]])}if(tabs.length>0){let vod_play_from=tabs.join("$$$");let vod_play_url=playUrls.join("$$$");base_vod.vod_play_from=vod_play_from;base_vod.vod_play_url=vod_play_url}VOD=base_vod;',
|
||||
搜索:'json:data.longData.rows;titleTxt||titlealias;cover;cat_name;cat_id+en_id;description',
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Author : Doubebly
|
||||
# @Time : 2025/3/23 21:55
|
||||
import base64
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import requests
|
||||
import re
|
||||
from datetime import datetime
|
||||
sys.path.append('..')
|
||||
from base.spider import Spider
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
class Spider(Spider):
|
||||
def getName(self):
|
||||
return "Litv"
|
||||
|
||||
def init(self, extend):
|
||||
self.extend = extend
|
||||
try:
|
||||
self.extendDict = json.loads(extend)
|
||||
except:
|
||||
self.extendDict = {}
|
||||
|
||||
proxy = self.extendDict.get('proxy', None)
|
||||
if proxy is None:
|
||||
self.is_proxy = False
|
||||
else:
|
||||
self.proxy = proxy
|
||||
self.is_proxy = True
|
||||
pass
|
||||
|
||||
def getDependence(self):
|
||||
return []
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
pass
|
||||
|
||||
def manualVideoCheck(self):
|
||||
pass
|
||||
|
||||
|
||||
def liveContent(self, url):
|
||||
cookies = {
|
||||
'_ga': 'GA1.1.782627561.1745936696',
|
||||
'_oredge_rl': 'u1ORyxILkguVwZ3LWQNJTpqceYPzrL/Cgugwu74xDwA=',
|
||||
'dailyMessageShown515': 'shown',
|
||||
'_ga_F2ET4TBC70': 'GS2.1.s1747232930$o3$g1$t1747233259$j0$l0$h0',
|
||||
}
|
||||
|
||||
headers = {
|
||||
'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',
|
||||
'cache-control': 'max-age=0',
|
||||
'priority': 'u=0, i',
|
||||
'sec-ch-ua': '"Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'sec-fetch-dest': 'document',
|
||||
'sec-fetch-mode': 'navigate',
|
||||
'sec-fetch-site': 'none',
|
||||
'sec-fetch-user': '?1',
|
||||
'upgrade-insecure-requests': '1',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36',
|
||||
# 'cookie': '_ga=GA1.1.782627561.1745936696; _oredge_rl=u1ORyxILkguVwZ3LWQNJTpqceYPzrL/Cgugwu74xDwA=; dailyMessageShown515=shown; _ga_F2ET4TBC70=GS2.1.s1747232930$o3$g1$t1747233259$j0$l0$h0',
|
||||
}
|
||||
|
||||
response = requests.get('https://www.515001.tv/', cookies=cookies, headers=headers)
|
||||
|
||||
#print(response.text) #自己添加,表示输出响应的内容
|
||||
|
||||
html = response.text
|
||||
|
||||
soup = BeautifulSoup(html, 'html.parser')
|
||||
|
||||
matches = []
|
||||
for a in soup.find_all('a', class_='clearfix'):
|
||||
# 提取链接
|
||||
link = a.get('href', '')
|
||||
link = f"video://{link}"
|
||||
|
||||
# 提取赛事名称和时间
|
||||
event_time_p = a.find('p', class_='eventtime_wuy')
|
||||
if event_time_p:
|
||||
em = event_time_p.find('em')
|
||||
event_name = em.get_text(strip=True) if em else ''
|
||||
i_tag = event_time_p.find('i')
|
||||
time = i_tag.get_text(strip=True) if i_tag else ''
|
||||
else:
|
||||
event_name = ''
|
||||
time = ''
|
||||
|
||||
# 提取主队名称
|
||||
home_div = a.find('div', class_=lambda c: c and 'zhudui' in c)
|
||||
home_team = home_div.find('p').get_text(strip=True) if home_div else ''
|
||||
|
||||
# 提取客队名称
|
||||
away_div = a.find('div', class_='kedui')
|
||||
away_team = away_div.find('p').get_text(strip=True) if away_div else ''
|
||||
|
||||
if event_name and home_team and away_team and time and link:
|
||||
match_str = f"[{event_name}]{home_team} VS {away_team}{time},{link}"
|
||||
matches.append(match_str)
|
||||
|
||||
m3u_content = ['#EXTM3U']
|
||||
for match in matches:
|
||||
title = match.split(",")[0]
|
||||
ch_url = match.split(",")[1]
|
||||
extinf = f'#EXTINF:-1 tvg-name="{title}" group-title="515001",{title}'
|
||||
m3u_content.extend([extinf, ch_url])
|
||||
|
||||
return '\n'.join(m3u_content)
|
||||
|
||||
def homeContent(self, filter):
|
||||
return {}
|
||||
|
||||
def homeVideoContent(self):
|
||||
return {}
|
||||
|
||||
def categoryContent(self, cid, page, filter, ext):
|
||||
return {}
|
||||
|
||||
def detailContent(self, did):
|
||||
return {}
|
||||
|
||||
def searchContent(self, key, quick, page='1'):
|
||||
return {}
|
||||
|
||||
def searchContentPage(self, keywords, quick, page):
|
||||
return {}
|
||||
|
||||
def playerContent(self, flag, pid, vipFlags):
|
||||
return {}
|
||||
|
||||
def localProxy(self, params):
|
||||
if params['type'] == "m3u8":
|
||||
return self.proxyM3u8(params)
|
||||
if params['type'] == "ts":
|
||||
return self.get_ts(params)
|
||||
return [302, "text/plain", None, {'Location': 'https://sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4'}]
|
||||
def proxyM3u8(self, params):
|
||||
pid = params['pid']
|
||||
info = pid.split(',')
|
||||
a = info[0]
|
||||
b = info[1]
|
||||
c = info[2]
|
||||
timestamp = int(time.time() / 4 - 355017625)
|
||||
t = timestamp * 4
|
||||
m3u8_text = f'#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:4\n#EXT-X-MEDIA-SEQUENCE:{timestamp}\n'
|
||||
for i in range(10):
|
||||
url = f'https://ntd-tgc.cdn.hinet.net/live/pool/{a}/litv-pc/{a}-avc1_6000000={b}-mp4a_134000_zho={c}-begin={t}0000000-dur=40000000-seq={timestamp}.ts'
|
||||
if self.is_proxy:
|
||||
url = f'http://127.0.0.1:9978/proxy?do=py&type=ts&url={self.b64encode(url)}'
|
||||
|
||||
m3u8_text += f'#EXTINF:4,\n{url}\n'
|
||||
timestamp += 1
|
||||
t += 4
|
||||
return [200, "application/vnd.apple.mpegurl", m3u8_text]
|
||||
|
||||
def get_ts(self, params):
|
||||
url = self.b64decode(params['url'])
|
||||
headers = {'User-Agent': 'Mozilla/5.0'}
|
||||
response = requests.get(url, headers=headers, stream=True, proxies=self.proxy)
|
||||
return [206, "application/octet-stream", response.content]
|
||||
|
||||
def destroy(self):
|
||||
return '正在Destroy'
|
||||
|
||||
def b64encode(self, data):
|
||||
return base64.b64encode(data.encode('utf-8')).decode('utf-8')
|
||||
|
||||
def b64decode(self, data):
|
||||
return base64.b64decode(data.encode('utf-8')).decode('utf-8')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
@@ -0,0 +1,61 @@
|
||||
var rule = {
|
||||
title:'88看球',
|
||||
// host:'http://www.88kanqiu.cc',
|
||||
host:'http://www.88kanqiu.bar/',
|
||||
url: "/match/fyclass/live",
|
||||
searchUrl: "",
|
||||
searchable: 0,
|
||||
quickSearch: 0,
|
||||
class_parse: ".nav-pills li;a&&Text;a&&href;/match/(\\d+)/live",
|
||||
headers: {
|
||||
"User-Agent": "PC_UA",
|
||||
},
|
||||
timeout: 5000,
|
||||
play_parse: true,
|
||||
pagecount:{"1":1,"2":1,"4":1,"22":1,"8":1,"9":1,"10":1,"14":1,"15":1,"12":1,"13":1,"16":1,"28":1,"7":1,"11":1,"33":1,"27":1,"23":1,"26":1,"3":1,"21":1,"18":1},
|
||||
lazy: `js:
|
||||
if(/embed=/.test(input)) {
|
||||
let url = input.match(/embed=(.*?)&/)[1];
|
||||
url = base64Decode(url);
|
||||
input = {
|
||||
jx:0,
|
||||
url: url.split('#')[0],
|
||||
parse: 0
|
||||
}
|
||||
} else if (/\?url=/.test(input)){
|
||||
input = {
|
||||
jx:0,
|
||||
url: input.split('?url=')[1].split('#')[0],
|
||||
parse: 0
|
||||
}
|
||||
} else {
|
||||
input
|
||||
}
|
||||
`,
|
||||
limit: 6,
|
||||
double: false,
|
||||
推荐: "*",
|
||||
一级: ".list-group .group-game-item;.d-none&&Text;img&&src;.btn&&Text;a&&href",
|
||||
二级: {
|
||||
title: ".game-info-container&&Text;.customer-navbar-nav li&&Text",
|
||||
img: "img&&src",
|
||||
desc: ";;;div.team-name:eq(0)&&Text;div.team-name:eq(1)&&Text",
|
||||
content: "div.game-time&&Text",
|
||||
tabs: "js:TABS=['实时直播']",
|
||||
lists: `js:
|
||||
LISTS = [];
|
||||
let html = request(input.replace('play', 'play-url'));
|
||||
let pdata = JSON.parse(html).data;
|
||||
pdata = pdata.slice(6);
|
||||
pdata = pdata.slice(0, -2);
|
||||
pdata = base64Decode(pdata);
|
||||
// log(pdata);
|
||||
let jo = JSON.parse(pdata).links;
|
||||
let d = jo.map(function (it) {
|
||||
return it.name + '$' + urlencode(it.url)
|
||||
});
|
||||
LISTS.push(d)
|
||||
`,
|
||||
},
|
||||
搜索: "",
|
||||
};
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user