Files
tvbox_collect/jaychouqq/yingshi/py/hohoj.py
T
2026-06-29 03:41:14 +00:00

208 lines
7.6 KiB
Python

# -*- coding: utf-8 -*-
#七哥爱瑟瑟
import json
import re
import requests
from pyquery import PyQuery as pq
import sys
sys.path.append('..')
from base.spider import Spider
class Spider(Spider):
host = 'https://hohoj.tv'
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'referer': 'https://hohoj.tv/'
}
def init(self, extend=''):
self.proxies = json.loads(extend).get('proxy', {}) if extend else {}
def getName(self):
return "hohoj"
def fetch(self, url, params=None):
try:
return requests.get(url, headers=self.headers, params=params,
proxies=self.proxies, timeout=10).text
except:
return ''
def homeContent(self, filter):
html = self.fetch(self.host)
return {
'class': [
{'type_name': '有码', 'type_id': 'search?type=censored'},
{'type_name': '無碼', 'type_id': 'search?type=uncensored'},
{'type_name': '中文字幕', 'type_id': 'search?type=chinese'},
{'type_name': '歐美', 'type_id': 'search?type=europe'},
{'type_name': '女優', 'type_id': 'all_models'},
{'type_name': '亂倫', 'type_id': 'main_ctg?id=8&name=亂倫'},
{'type_name': '強姦凌辱', 'type_id': 'main_ctg?id=2&name=強姦凌辱'},
{'type_name': '內射受孕', 'type_id': 'main_ctg?id=12&name=內射受孕'},
{'type_name': '多P群交', 'type_id': 'main_ctg?id=5&name=多P群交'},
{'type_name': '巨乳美乳', 'type_id': 'main_ctg?id=9&name=巨乳美乳'},
{'type_name': '出軌', 'type_id': 'main_ctg?id=7&name=出軌'},
{'type_name': '角色劇情', 'type_id': 'main_ctg?id=6&name=角色劇情'},
{'type_name': '絲襪美腿', 'type_id': 'main_ctg?id=1&name=絲襪美腿'},
{'type_name': '潮吹放尿', 'type_id': 'main_ctg?id=10&name=潮吹放尿'},
{'type_name': '走後門', 'type_id': 'main_ctg?id=11&name=走後門'},
{'type_name': '制服誘惑', 'type_id': 'main_ctg?id=4&name=制服誘惑'},
{'type_name': '主奴調教', 'type_id': 'main_ctg?id=3&name=主奴調教'},
],
'filters': self.get_filters(),
'list': self.parse_videos(pq(html)('.video-item'))
}
def get_filters(self):
base = [{'key': 'order', 'name': '排序', 'value': [
{'n': '最新', 'v': 'latest'},
{'n': '最热', 'v': 'hot'},
{'n': '最多观看', 'v': 'views'},
{'n': '最多喜欢', 'v': 'likes'},
]}]
return {
'search?type=censored': base,
'search?type=uncensored': base,
'search?type=chinese': base,
'search?type=europe': base,
}
def categoryContent(self, tid, pg, filter, extend):
url = f"{self.host}/{tid if tid != 'all_models' else 'all_models'}"
params = extend.copy() if extend else {}
if int(pg) > 1:
params['p'] = pg
html = self.fetch(url, params)
data = pq(html)
videos = self.parse_models(data('.model')) if tid == 'all_models' else self.parse_videos(data('.video-item'))
return {
'list': videos,
'page': pg,
'pagecount': data('.pagination a').length or 1,
'limit': 90,
'total': 999999
}
def detailContent(self, ids):
vid = ids[0]
url = f"{self.host}{vid}" if vid.startswith('/') else f"{self.host}/{vid}"
html = self.fetch(url)
data = pq(html)
video_id = vid.split('id=')[-1].split('&')[0] if 'id=' in vid else ''
title = data('h1').text() or data('title').text() or ''
title = re.sub(r'\s*HoHoJ.*$', '', title)
title = re.sub(r'\s*\|.*$', '', title)
title = title.strip()
vod = {
'vod_name': title,
'vod_play_from': '撸出血',
'vod_play_url': f"{title}${video_id}",
'vod_pic': data('.video-player img').attr('src') or data('meta[property="og:image"]').attr('content'),
'vod_year': data('.info span').eq(-1).text(),
}
actors = []
for a in data('.model a').items():
name = a('.model-name').text().strip()
href = a.attr('href')
if name and href:
actors.append(f'[a=cr:{json.dumps({"id": href, "name": name})}/]{name}[/a]')
if actors:
vod['vod_actor'] = ' '.join(actors)
tags = []
for ctg_span in data('span.ctg').items():
a = ctg_span.find('a')
if a:
name = a.text().strip()
href = a.attr('href')
if name and href:
tags.append(f'[a=cr:{json.dumps({"id": href, "name": name})}/]{name}[/a]')
if tags:
vod['vod_content'] = ' '.join(tags)
return {'list': [vod]}
def searchContent(self, key, quick, pg="1"):
params = {'text': key}
if int(pg) > 1:
params['p'] = pg
html = self.fetch(f"{self.host}/search", params)
return {'list': self.parse_videos(pq(html)('.video-item')), 'page': pg}
def playerContent(self, flag, id, vipFlags):
html = self.fetch(f"{self.host}/embed?id={id}")
video_url = ''
match = re.search(r'<video[^>]+src="([^"]+)"', html)
if match:
video_url = match.group(1)
else:
match = re.search(r'var\s+videoSrc\s*=\s*["\']([^"\']+)["\']', html)
video_url = match.group(1) if match else pq(html)('video').attr('src') or ''
return {
'parse': 0,
'url': video_url,
'header': {
'user-agent': self.headers['user-agent'],
'referer': f"{self.host}/embed?id={id}",
'origin': self.host,
}
} if video_url else {'parse': 0, 'url': ''}
def parse_videos(self, items):
videos = []
for i in items.items():
link = i('a').attr('href')
title = i('.video-item-title').text() or i('img').attr('alt')
if not link or not title:
continue
title = re.sub(r'\s*HoHoJ.*$', '', title)
title = re.sub(r'\s*\|.*$', '', title).strip()
rating = i('.video-item-rating')
views = rating.find('.fa-eye').parent().text().strip()
likes = rating.find('.fa-heart').parent().text().strip()
videos.append({
'vod_id': link,
'vod_name': title,
'vod_pic': i('img').attr('src'),
'vod_remarks': f"👁 {views}{likes}",
'vod_tag': '无码' if i('.video-item-badge').length else '',
'style': {"type": "rect", "ratio": 1.5}
})
return videos
def parse_models(self, items):
return [{
'vod_id': i('a').attr('href'),
'vod_name': i('.model-name').text(),
'vod_pic': i('img').attr('src'),
'vod_tag': 'folder',
'style': {"type": "rect", "ratio": 0.75}
} for i in items.items() if i('a').attr('href')]
def isVideoFormat(self, url):
pass
def manualVideoCheck(self):
pass
def destroy(self):
pass
def homeVideoContent(self):
pass
def localProxy(self, param):
pass
def liveContent(self, url):
pass