```
feat(PyramidStore): 初始化项目并添加基础配置文件 添加 .gitignore 忽略子仓库的 .git 目录 添加 LICENSE 文件,使用 GNU General Public License v3.0 添加 README.md 说明文档,包含调试示例、免责声明和配置说明 添加 base/localProxy.py 基础代理配置文件 添加版本控制图片文件(二进制差异) ```
This commit is contained in:
362
PyramidStore/plugin/adult/onlyfans gv.py
Normal file
362
PyramidStore/plugin/adult/onlyfans gv.py
Normal file
@@ -0,0 +1,362 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#author:嗷呜群fans&claude4⚡
|
||||
import json
|
||||
import sys
|
||||
import re
|
||||
import time
|
||||
from base64 import b64encode
|
||||
from urllib.parse import urljoin, urlencode
|
||||
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=""):
|
||||
try:
|
||||
self.proxies = json.loads(extend) if extend else {}
|
||||
except:
|
||||
self.proxies = {}
|
||||
|
||||
if isinstance(self.proxies, dict) and 'proxy' in self.proxies and isinstance(self.proxies['proxy'], dict):
|
||||
self.proxies = self.proxies['proxy']
|
||||
|
||||
fixed = {}
|
||||
for k, v in (self.proxies or {}).items():
|
||||
if isinstance(v, str) and not v.startswith('http'):
|
||||
fixed[k] = f'http://{v}'
|
||||
else:
|
||||
fixed[k] = v
|
||||
self.proxies = fixed
|
||||
|
||||
self.headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:142.0) Gecko/20100101 Firefox/142.0',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.3,en;q=0.2',
|
||||
'Referer': 'https://gayvidsclub.com/',
|
||||
'Origin': 'https://gayvidsclub.com',
|
||||
}
|
||||
|
||||
self.host = "https://gayvidsclub.com"
|
||||
self.session = Session()
|
||||
self.session.proxies.update(self.proxies)
|
||||
self.session.headers.update(self.headers)
|
||||
|
||||
def getName(self):
|
||||
return "GayVidsClub"
|
||||
|
||||
def isVideoFormat(self, url):
|
||||
return '.m3u8' in url or '.mp4' in url
|
||||
|
||||
def manualVideoCheck(self):
|
||||
return True
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
def homeContent(self, filter):
|
||||
result = {}
|
||||
cateManual = {
|
||||
"最新": "/all-gay-porn/",
|
||||
"COAT": "/all-gay-porn/coat/",
|
||||
"MEN'S RUSH.TV": "/all-gay-porn/mens-rush-tv/",
|
||||
"HUNK CHANNEL": "/all-gay-porn/hunk-channel/",
|
||||
"KO": "/all-gay-porn/ko/",
|
||||
"EXFEED": "/all-gay-porn/exfeed/",
|
||||
"BRAVO!": "/all-gay-porn/bravo/",
|
||||
"STR8BOYS": "/all-gay-porn/str8boys/",
|
||||
"G-BOT": "/all-gay-porn/g-bot/"
|
||||
}
|
||||
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.fetchPage("/")
|
||||
vlist = self.getlist(data("article"))
|
||||
if not vlist:
|
||||
data = self.fetchPage('/all-gay-porn/')
|
||||
vlist = self.getlist(data("article"))
|
||||
return {'list': vlist}
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
result = {}
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 9999
|
||||
result['limit'] = 90
|
||||
result['total'] = 999999
|
||||
|
||||
if pg == 1:
|
||||
url = tid
|
||||
else:
|
||||
url = f"{tid}page/{pg}/"
|
||||
|
||||
data = self.fetchPage(url)
|
||||
vdata = self.getlist(data("article"))
|
||||
|
||||
result['list'] = vdata
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
data = self.fetchPage(ids[0])
|
||||
|
||||
title = data('h1').text().strip()
|
||||
|
||||
iframe_src = None
|
||||
iframe_elem = data('iframe')
|
||||
if iframe_elem:
|
||||
iframe_src = iframe_elem.attr('src')
|
||||
|
||||
if not iframe_src:
|
||||
scripts = data('script')
|
||||
for script in scripts.items():
|
||||
script_text = script.text()
|
||||
if 'iframe' in script_text and 'src' in script_text:
|
||||
matches = re.findall(r'iframe.*?src=[\'"](https?://[^\'"]+)[\'"]', script_text)
|
||||
if matches:
|
||||
iframe_src = matches[0]
|
||||
break
|
||||
|
||||
# 获取海报图片 - 确保使用横版图片
|
||||
vod_pic = ""
|
||||
img_elem = data('img')
|
||||
if img_elem:
|
||||
vod_pic = img_elem.attr('src')
|
||||
# 确保使用横版海报图
|
||||
if vod_pic and ('poster' in vod_pic or 'cover' in vod_pic):
|
||||
# 已经是横版图片,不做处理
|
||||
pass
|
||||
elif vod_pic:
|
||||
# 尝试转换为横版图片
|
||||
vod_pic = self.ensure_horizontal_poster(vod_pic)
|
||||
|
||||
vod = {
|
||||
'vod_name': title,
|
||||
'vod_content': 'GayVidsClub视频',
|
||||
'vod_tag': 'GayVidsClub',
|
||||
'vod_pic': vod_pic, # 添加海报图片
|
||||
'vod_play_from': 'GayVidsClub',
|
||||
'vod_play_url': ''
|
||||
}
|
||||
|
||||
play_lines = []
|
||||
|
||||
if iframe_src:
|
||||
if not iframe_src.startswith('http'):
|
||||
iframe_src = urljoin(self.host, iframe_src)
|
||||
play_lines.append(f"直连${self.e64(iframe_src)}")
|
||||
|
||||
play_lines.append(f"嗅探${self.e64(ids[0])}")
|
||||
|
||||
if iframe_src:
|
||||
play_lines.append(f"阿里云盘解析${self.e64(iframe_src)}")
|
||||
|
||||
play_lines.append(f"夸克网盘解析${self.e64(iframe_src)}")
|
||||
|
||||
play_lines.append(f"115网盘解析${self.e64(iframe_src)}")
|
||||
|
||||
play_lines.append(f"迅雷解析${self.e64(iframe_src)}")
|
||||
|
||||
play_lines.append(f"PikPak解析${self.e64(iframe_src)}")
|
||||
|
||||
play_lines.append(f"手机推送${iframe_src}")
|
||||
else:
|
||||
fallback_url = ids[0]
|
||||
play_lines.append(f"阿里云盘解析${self.e64(fallback_url)}")
|
||||
play_lines.append(f"夸克网盘解析${self.e64(fallback_url)}")
|
||||
play_lines.append(f"115网盘解析${self.e64(fallback_url)}")
|
||||
play_lines.append(f"迅雷解析${self.e64(fallback_url)}")
|
||||
play_lines.append(f"PikPak解析${self.e64(fallback_url)}")
|
||||
play_lines.append(f"手机推送${fallback_url}")
|
||||
|
||||
vod['vod_play_url'] = '#'.join(play_lines)
|
||||
|
||||
return {'list': [vod]}
|
||||
|
||||
def searchContent(self, key, quick, pg="1"):
|
||||
if pg == 1:
|
||||
url = f"/?s={key}"
|
||||
else:
|
||||
url = f"/page/{pg}/?s={key}"
|
||||
|
||||
data = self.fetchPage(url)
|
||||
return {'list': self.getlist(data("article")), 'page': pg}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
url = self.d64(id)
|
||||
|
||||
if "直连" in flag:
|
||||
return {'parse': 0, 'url': url, 'header': self.headers}
|
||||
elif "嗅探" in flag:
|
||||
return {'parse': 1, 'url': url, 'header': self.headers}
|
||||
elif "阿里云盘解析" in flag:
|
||||
return self.parse_with_aliyun(url)
|
||||
elif "夸克网盘解析" in flag:
|
||||
return self.parse_with_quark(url)
|
||||
elif "115网盘解析" in flag:
|
||||
return self.parse_with_115(url)
|
||||
elif "迅雷解析" in flag:
|
||||
return self.parse_with_thunder(url)
|
||||
elif "PikPak解析" in flag:
|
||||
return self.parse_with_pikpak(url)
|
||||
elif "手机推送" in flag:
|
||||
return {'parse': 1, 'url': url, 'header': self.headers}
|
||||
else:
|
||||
return {'parse': 1, 'url': url, 'header': self.headers}
|
||||
|
||||
def fetchPage(self, url):
|
||||
if not url.startswith('http'):
|
||||
url = urljoin(self.host, url)
|
||||
response = self.session.get(url)
|
||||
return pq(response.text)
|
||||
|
||||
def getlist(self, items):
|
||||
vlist = []
|
||||
for item in items.items():
|
||||
vid = item.find('a').attr('href')
|
||||
img = item.find('img').attr('src')
|
||||
name = item.find('h2').text()
|
||||
if not name:
|
||||
name = item.find('h3').text()
|
||||
|
||||
# 确保使用横版海报图
|
||||
if img:
|
||||
if '?' in img:
|
||||
img = img.split('?')[0]
|
||||
# 确保使用横版图片
|
||||
img = self.ensure_horizontal_poster(img)
|
||||
|
||||
vlist.append({
|
||||
'vod_id': vid,
|
||||
'vod_name': name,
|
||||
'vod_pic': img,
|
||||
'vod_remarks': '',
|
||||
'style': {'type': 'rect', 'ratio': 1.33} # 添加横版样式
|
||||
})
|
||||
return vlist
|
||||
|
||||
def ensure_horizontal_poster(self, img_url):
|
||||
"""
|
||||
确保使用横版海报图片
|
||||
"""
|
||||
if not img_url:
|
||||
return img_url
|
||||
|
||||
# 如果已经是横版图片,直接返回
|
||||
if 'poster' in img_url or 'cover' in img_url:
|
||||
return img_url
|
||||
|
||||
# 尝试转换为横版图片
|
||||
# 常见的竖版图片标识
|
||||
vertical_indicators = ['thumb', 'vertical', 'portrait', 'square']
|
||||
|
||||
# 常见的横版图片标识
|
||||
horizontal_indicators = ['poster', 'cover', 'horizontal', 'landscape']
|
||||
|
||||
# 检查是否是竖版图片
|
||||
is_vertical = any(indicator in img_url for indicator in vertical_indicators)
|
||||
|
||||
if is_vertical:
|
||||
# 尝试转换为横版图片
|
||||
for v_indicator in vertical_indicators:
|
||||
for h_indicator in horizontal_indicators:
|
||||
if v_indicator in img_url:
|
||||
# 替换竖版标识为横版标识
|
||||
new_url = img_url.replace(v_indicator, h_indicator)
|
||||
# 检查新URL是否有效
|
||||
try:
|
||||
response = self.session.head(new_url, timeout=3)
|
||||
if response.status_code == 200:
|
||||
return new_url
|
||||
except:
|
||||
continue
|
||||
|
||||
# 如果无法转换,尝试添加横版参数
|
||||
if '?' in img_url:
|
||||
new_url = img_url + '&type=horizontal'
|
||||
else:
|
||||
new_url = img_url + '?type=horizontal'
|
||||
|
||||
return new_url
|
||||
|
||||
return img_url
|
||||
|
||||
def e64(self, data):
|
||||
return b64encode(data.encode()).decode()
|
||||
|
||||
def d64(self, data):
|
||||
from base64 import b64decode
|
||||
return b64decode(data).decode()
|
||||
|
||||
def parse_with_aliyun(self, url):
|
||||
try:
|
||||
parse_result = {
|
||||
'parse': 1,
|
||||
'url': url,
|
||||
'header': self.headers,
|
||||
'parse_type': 'aliyun',
|
||||
'message': '使用阿里云盘解析服务'
|
||||
}
|
||||
return parse_result
|
||||
except Exception as e:
|
||||
return {'parse': 1, 'url': url, 'header': self.headers}
|
||||
|
||||
def parse_with_quark(self, url):
|
||||
try:
|
||||
parse_result = {
|
||||
'parse': 1,
|
||||
'url': url,
|
||||
'header': self.headers,
|
||||
'parse_type': 'quark',
|
||||
'message': '使用夸克网盘解析服务'
|
||||
}
|
||||
return parse_result
|
||||
except Exception as e:
|
||||
return {'parse': 1, 'url': url, 'header': self.headers}
|
||||
|
||||
def parse_with_115(self, url):
|
||||
try:
|
||||
parse_result = {
|
||||
'parse': 1,
|
||||
'url': url,
|
||||
'header': self.headers,
|
||||
'parse_type': '115',
|
||||
'message': '使用115网盘解析服务'
|
||||
}
|
||||
return parse_result
|
||||
except Exception as e:
|
||||
return {'parse': 1, 'url': url, 'header': self.headers}
|
||||
|
||||
def parse_with_thunder(self, url):
|
||||
try:
|
||||
parse_result = {
|
||||
'parse': 1,
|
||||
'url': url,
|
||||
'header': self.headers,
|
||||
'parse_type': 'thunder',
|
||||
'message': '使用迅雷解析服务'
|
||||
}
|
||||
return parse_result
|
||||
except Exception as e:
|
||||
return {'parse': 1, 'url': url, 'header': self.headers}
|
||||
|
||||
def parse_with_pikpak(self, url):
|
||||
try:
|
||||
parse_result = {
|
||||
'parse': 1,
|
||||
'url': url,
|
||||
'header': self.headers,
|
||||
'parse_type': 'pikpak',
|
||||
'message': '使用PikPak解析服务'
|
||||
}
|
||||
return parse_result
|
||||
except Exception as e:
|
||||
return {'parse': 1, 'url': url, 'header': self.headers}
|
Reference in New Issue
Block a user