278 lines
10 KiB
Python
278 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
# by @嗷呜
|
|
import concurrent.futures
|
|
import json
|
|
import re
|
|
import sys
|
|
import time
|
|
from base64 import b64decode, b64encode
|
|
import requests
|
|
from pyquery import PyQuery as pq
|
|
sys.path.append('..')
|
|
from base.spider import Spider
|
|
|
|
|
|
class Spider(Spider):
|
|
|
|
def init(self, extend=""):
|
|
self.host = "https://vip.wwgz.cn:5200"
|
|
self.headers = {
|
|
'User-Agent': 'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36',
|
|
'Referer': self.host + '/',
|
|
'Accept': 'text/html'
|
|
}
|
|
self.cateConfig = {
|
|
"12": [{"key": "cateId", "name": "类型", "value": [{"n": "国产剧", "v": "12"}]}],
|
|
"4": [{"key": "cateId", "name": "类型", "value": [{"n": "动漫", "v": "4"}]}],
|
|
"1": [{"key": "cateId", "name": "类型", "value": [{"n": "电影", "v": "1"}]}],
|
|
"2": [{"key": "cateId", "name": "类型", "value": [{"n": "电视剧", "v": "2"}]}],
|
|
"3": [{"key": "cateId", "name": "类型", "value": [{"n": "综艺", "v": "3"}]}],
|
|
"26": [{"key": "cateId", "name": "类型", "value": [{"n": "短剧", "v": "26"}]}]
|
|
}
|
|
self.filterConfig = {}
|
|
|
|
def getName(self):
|
|
return "农民影视"
|
|
|
|
def isVideoFormat(self, url):
|
|
pass
|
|
|
|
def manualVideoCheck(self):
|
|
pass
|
|
|
|
def destroy(self):
|
|
pass
|
|
|
|
def homeContent(self, filter):
|
|
result = {}
|
|
classes = [
|
|
{'type_name': '国产剧', 'type_id': '12'},
|
|
{'type_name': '动漫', 'type_id': '4'},
|
|
{'type_name': '电影', 'type_id': '1'},
|
|
{'type_name': '电视剧', 'type_id': '2'},
|
|
{'type_name': '综艺', 'type_id': '3'},
|
|
{'type_name': '短剧', 'type_id': '26'}
|
|
]
|
|
try:
|
|
data = self.fetch(self.host, headers=self.headers).text
|
|
doc = pq(data)
|
|
videos = []
|
|
# 修改选择器并添加去重逻辑
|
|
seen_ids = set() # 用于记录已处理的影片ID
|
|
for item in doc('.globalPicList li:has(img)').items():
|
|
vod_id = self.host + item('a').attr('href')
|
|
if vod_id not in seen_ids: # 检查是否已处理过
|
|
seen_ids.add(vod_id) # 记录已处理的ID
|
|
pic_url = item('img').attr('data-echo') or item('img').attr('data-src') or item('img').attr('src')
|
|
# 替换图片域名
|
|
if pic_url and 'pic.lzzypic.com' in pic_url:
|
|
pic_url = pic_url.replace('https://pic.lzzypic.com', 'https://img.lzzyimg.com')
|
|
videos.append({
|
|
'vod_id': vod_id,
|
|
'vod_name': item('.sTit').text(),
|
|
'vod_pic': pic_url,
|
|
'vod_remarks': item('.sBottom').text()
|
|
})
|
|
result['class'] = classes
|
|
result['filters'] = self.cateConfig
|
|
result['list'] = videos
|
|
except Exception as e:
|
|
print(f"首页数据获取失败: {str(e)}")
|
|
result['class'] = classes
|
|
result['filters'] = self.cateConfig
|
|
result['list'] = []
|
|
return result
|
|
|
|
def homeVideoContent(self):
|
|
pass
|
|
|
|
def categoryContent(self, tid, pg, filter, extend):
|
|
result = {}
|
|
try:
|
|
if tid == "4-dm":
|
|
# 处理大陆人气动漫分类
|
|
url = "https://www.wwgz.cn/vod-list-id-4-pg-{}-order--by-hits-class-0-year-0-letter--area-大陆-lang-.html".format(pg)
|
|
else:
|
|
cateId = tid
|
|
url = f"{self.host}/vod-list-id-{cateId}-pg-{pg}.html"
|
|
|
|
data = self.fetch(url, headers=self.headers).text
|
|
doc = pq(data)
|
|
|
|
videos = []
|
|
for item in doc('.globalPicList li').items():
|
|
pic_url = item('img').attr('data-echo') or item('img').attr('data-src') or item('img').attr('src')
|
|
# 替换图片域名
|
|
if pic_url and 'pic.lzzypic.com' in pic_url:
|
|
pic_url = pic_url.replace('https://pic.lzzypic.com', 'https://img.lzzyimg.com')
|
|
videos.append({
|
|
'vod_id': self.host + item('a').attr('href'),
|
|
'vod_name': item('.sTit').text(),
|
|
'vod_pic': pic_url,
|
|
'vod_remarks': item('.sBottom').text()
|
|
})
|
|
|
|
result['list'] = videos
|
|
result['page'] = pg
|
|
result['pagecount'] = 9999
|
|
result['limit'] = 90
|
|
result['total'] = 999999
|
|
except Exception as e:
|
|
print(f"分类数据获取失败: {str(e)}")
|
|
result['list'] = []
|
|
result['page'] = pg
|
|
result['pagecount'] = 1
|
|
result['limit'] = 90
|
|
result['total'] = 0
|
|
return result
|
|
|
|
def detailContent(self, ids):
|
|
result = {}
|
|
try:
|
|
url = ids[0]
|
|
data = self.fetch(url, headers=self.headers).text
|
|
doc = pq(data)
|
|
|
|
# 获取播放线路和剧集
|
|
play_from = []
|
|
play_url = []
|
|
|
|
tab_box = doc('#leftTabBox')
|
|
if tab_box:
|
|
for tab in tab_box('ul li').items():
|
|
play_from.append(tab.text())
|
|
|
|
play_lists = []
|
|
for num_list in tab_box('.numList').items():
|
|
episodes = []
|
|
# 修改这里:将items()转换为列表后反转顺序
|
|
for ep in list(num_list('li').items())[::-1]: # 反转列表顺序
|
|
episodes.append(f"{ep('a').text()}${self.host}{ep('a').attr('href')}")
|
|
play_lists.append('#'.join(episodes))
|
|
|
|
play_url = play_lists
|
|
|
|
# 获取详情信息
|
|
vod = {
|
|
'vod_name': doc('h1 a').text(),
|
|
'vod_year': doc('span:contains("年代:")').text().replace('年代:', ''),
|
|
'vod_area': '',
|
|
'vod_actor': doc('.sDes:contains("主演:")').text().replace('主演:', ''),
|
|
'vod_director': '',
|
|
'vod_content': doc('.detail-con p').text().replace('简介:', ''),
|
|
'vod_play_from': '$$$'.join(play_from),
|
|
'vod_play_url': '$$$'.join(play_url)
|
|
}
|
|
result['list'] = [vod]
|
|
except Exception as e:
|
|
print(f"详情数据获取失败: {str(e)}")
|
|
result['list'] = []
|
|
return result
|
|
|
|
def searchContent(self, key, quick, pg="1"):
|
|
result = {}
|
|
try:
|
|
url = f"{self.host}/index.php?m=vod-search"
|
|
data = {'wd': key}
|
|
headers = {
|
|
'User-Agent': self.headers['User-Agent'],
|
|
'Referer': self.host + '/'
|
|
}
|
|
html = self.post(url, data=data, headers=headers).text
|
|
doc = pq(html)
|
|
|
|
videos = []
|
|
for item in doc('#data_list li').items():
|
|
pic_url = item('.lazyload').attr('data-src')
|
|
# 替换图片域名
|
|
if pic_url and 'pic.lzzypic.com' in pic_url:
|
|
pic_url = pic_url.replace('https://pic.lzzypic.com', 'https://img.lzzyimg.com')
|
|
videos.append({
|
|
'vod_id': self.host + item('a').attr('href'),
|
|
'vod_name': item('.sTit').text(),
|
|
'vod_pic': pic_url,
|
|
'vod_remarks': item('.sDes').eq(-1).text()
|
|
})
|
|
|
|
result['list'] = videos
|
|
result['page'] = pg
|
|
except Exception as e:
|
|
print(f"搜索数据获取失败: {str(e)}")
|
|
result['list'] = []
|
|
result['page'] = pg
|
|
return result
|
|
|
|
def playerContent(self, flag, id, vipFlags):
|
|
result = {}
|
|
try:
|
|
if '@' in id:
|
|
ids = id.split('@')
|
|
if not ids[0]:
|
|
raise Exception('未找到播放地址')
|
|
|
|
js_url = f"{self.host}/player/{ids[0]}.js"
|
|
js_data = self.fetch(js_url, headers=self.headers).text
|
|
jxurl = re.search(r'http.*?url=', js_data).group()
|
|
|
|
data = self.fetch(f"{jxurl}{ids[1]}", headers=self.headers).text
|
|
matches = re.findall(r'http.*?url=', data)
|
|
|
|
if matches:
|
|
url = []
|
|
for i, x in enumerate(matches):
|
|
js = {'jx': x, 'id': ids[1]}
|
|
purl = f"{self.getProxyUrl()}&wdict={self.e64(json.dumps(js))}"
|
|
url.extend([f'线路{i + 1}', purl])
|
|
else:
|
|
url = re.search(r"url='(.*?)'", data).group(1)
|
|
|
|
if not url:
|
|
raise Exception('未找到播放地址')
|
|
|
|
p = 0
|
|
else:
|
|
p, url = 1, id
|
|
|
|
result['parse'] = p
|
|
result['url'] = url
|
|
result['header'] = self.headers
|
|
except Exception as e:
|
|
print(f"播放数据获取失败: {str(e)}")
|
|
result['parse'] = 1
|
|
result['url'] = id
|
|
result['header'] = self.headers
|
|
return result
|
|
|
|
def localProxy(self, param):
|
|
try:
|
|
wdict = json.loads(self.d64(param['wdict']))
|
|
url = f"{wdict['jx']}{wdict['id']}"
|
|
data = self.fetch(url, headers=self.headers).text
|
|
doc = pq(data)
|
|
html = doc('script').eq(-1).text()
|
|
url = re.search(r'src="(.*?)"', html).group(1)
|
|
return [302, 'text/html', None, {'Location': url}]
|
|
except Exception as e:
|
|
print(f"代理处理失败: {str(e)}")
|
|
return [500, 'text/plain', str(e).encode('utf-8')]
|
|
|
|
def liveContent(self, url):
|
|
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 "" |