Sync all projects
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
import sys
|
||||
import re
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from base.spider import Spider
|
||||
from urllib.parse import urljoin, quote,unquote
|
||||
|
||||
class Spider(Spider):
|
||||
def getName(self):
|
||||
return "WhosTV"
|
||||
|
||||
def init(self, extend=""):
|
||||
self.host = "https://whos.tv"
|
||||
self.header = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
|
||||
"Referer": self.host
|
||||
}
|
||||
|
||||
def _decode_cover(self, encoded):
|
||||
"""解密 data-cover-src(还原前端 coolDecrypt 函数)"""
|
||||
if not encoded:
|
||||
return ""
|
||||
try:
|
||||
key_hex = encoded[-2:]
|
||||
key = int(key_hex, 16)
|
||||
data_hex = encoded[:-2]
|
||||
chars = []
|
||||
for i in range(0, len(data_hex), 2):
|
||||
byte_val = int(data_hex[i:i+2], 16)
|
||||
chars.append(chr(byte_val ^ key))
|
||||
return ''.join(chars)
|
||||
except:
|
||||
return ""
|
||||
|
||||
|
||||
def homeContent(self, filter):
|
||||
result = {}
|
||||
result['class'] = [
|
||||
{'type_name': '影片库', 'type_id': '/videos'},
|
||||
{'type_name': '女优库', 'type_id': '/actresses'}
|
||||
]
|
||||
return result
|
||||
|
||||
def categoryContent(self, tid, pg, filter, extend):
|
||||
result = {}
|
||||
url = f"{self.host}{tid}"
|
||||
if int(pg) > 1:
|
||||
url += f"/page-{pg}"
|
||||
|
||||
rsp = self.fetch(url, headers=self.header)
|
||||
soup = BeautifulSoup(rsp.text, 'html.parser')
|
||||
videos = []
|
||||
|
||||
# 女优名录页
|
||||
if tid == "/actresses":
|
||||
items = soup.find_all('a', href=re.compile(r'^/actresses/.'))
|
||||
for item in items:
|
||||
img = item.find('img')
|
||||
if not img:
|
||||
continue
|
||||
name = img.get('alt', '').strip()
|
||||
href = item.get('href')
|
||||
if not name or href == "/actresses" or "page-" in href:
|
||||
continue
|
||||
pic_url = img.get('src', '')
|
||||
count_text = ""
|
||||
icon_span = item.find('span', class_=re.compile(r'icon-\[lucide--film\]'))
|
||||
if icon_span:
|
||||
parent_flex = icon_span.find_parent('span', class_='flex')
|
||||
if parent_flex:
|
||||
count_text = parent_flex.get_text(strip=True) + "部作品"
|
||||
videos.append({
|
||||
"vod_id": href,
|
||||
"vod_name": name,
|
||||
"vod_pic": pic_url,
|
||||
"vod_remarks": count_text if count_text else "作品集",
|
||||
"vod_tag": "folder"
|
||||
})
|
||||
# 影片网格页(包括女优个人页的作品列表)
|
||||
else:
|
||||
items = soup.find_all('a', href=re.compile(r'^/videos/.'))
|
||||
for item in items:
|
||||
h3 = item.find('h3')
|
||||
v_name = h3.get_text(strip=True) if h3 else item.get('alt', '')
|
||||
if not v_name:
|
||||
continue
|
||||
div_cover = item.find('div', attrs={'data-cover-src': True})
|
||||
if div_cover:
|
||||
encoded = div_cover.get('data-cover-src')
|
||||
real_pic = self._decode_cover(encoded)
|
||||
else:
|
||||
real_pic = ""
|
||||
real_pic = real_pic
|
||||
remarks = self.regStr(v_name, r'([A-Z0-9]+-[0-9]+)')
|
||||
videos.append({
|
||||
"vod_id": item.get('href'),
|
||||
"vod_name": v_name,
|
||||
"vod_pic": real_pic,
|
||||
"vod_remarks": remarks if remarks else ""
|
||||
})
|
||||
|
||||
result['list'] = videos
|
||||
result['page'] = pg
|
||||
result['pagecount'] = 999
|
||||
result['limit'] = len(videos)
|
||||
result['total'] = 9999
|
||||
|
||||
if tid.startswith("/actresses/"):
|
||||
h1_tag = soup.find('h1')
|
||||
if h1_tag:
|
||||
result['type_name'] = h1_tag.get_text(strip=True)
|
||||
return result
|
||||
|
||||
def detailContent(self, ids):
|
||||
vodId = ids[0]
|
||||
if vodId.startswith("/actresses/"):
|
||||
return self.categoryContent(vodId, "1", None, None)
|
||||
|
||||
url = self.host + vodId
|
||||
rsp = self.fetch(url, headers=self.header)
|
||||
soup = BeautifulSoup(rsp.text, 'html.parser')
|
||||
|
||||
title_meta = soup.find('meta', property="og:title")
|
||||
title = title_meta.get('content') if title_meta else ""
|
||||
|
||||
pic_meta = soup.find('meta', property="og:image")
|
||||
pic = pic_meta.get('content') if pic_meta else ""
|
||||
pic = pic
|
||||
|
||||
source = soup.find('source', type="application/x-mpegURL")
|
||||
play_url = source.get('src') if source else ""
|
||||
|
||||
actor_tags = soup.select('a[href^="/actresses/"]')
|
||||
actors = ",".join([a.get_text(strip=True) for a in actor_tags if a.get_text(strip=True)])
|
||||
|
||||
tag_tags = soup.select('a[href^="/tags/"] span.truncate')
|
||||
tags = ",".join([t.get_text(strip=True) for t in tag_tags])
|
||||
|
||||
vod = {
|
||||
"vod_id": vodId,
|
||||
"vod_name": title,
|
||||
"vod_pic": pic,
|
||||
"type_name": tags,
|
||||
"vod_actor": actors,
|
||||
"vod_content": title,
|
||||
"vod_play_from": "WhosTV",
|
||||
"vod_play_url": "全高清$" + play_url if play_url else ""
|
||||
}
|
||||
return {'list': [vod]}
|
||||
|
||||
def playerContent(self, flag, id, vipFlags):
|
||||
return {
|
||||
"parse": 0,
|
||||
"url": id,
|
||||
"header": {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
|
||||
"Referer": "https://whos.tv/",
|
||||
"Origin": "https://whos.tv"
|
||||
}
|
||||
}
|
||||
|
||||
def searchContent(self, key, quick):
|
||||
url = f"{self.host}/result?serach={key}"
|
||||
rsp = self.fetch(url, headers=self.header)
|
||||
soup = BeautifulSoup(rsp.text, 'html.parser')
|
||||
videos = []
|
||||
|
||||
items = soup.find_all('a', href=re.compile(r'^/videos/.'))
|
||||
for item in items:
|
||||
h3 = item.find('h3')
|
||||
if h3:
|
||||
v_name = h3.get_text(strip=True)
|
||||
div_cover = item.find('div', attrs={'data-cover-src': True})
|
||||
if div_cover:
|
||||
encoded = div_cover.get('data-cover-src')
|
||||
real_pic = self._decode_cover(encoded)
|
||||
else:
|
||||
real_pic = ""
|
||||
real_pic = real_pic
|
||||
remarks = self.regStr(v_name, r'([A-Z0-9]+-[0-9]+)')
|
||||
videos.append({
|
||||
"vod_id": item.get('href'),
|
||||
"vod_name": v_name,
|
||||
"vod_pic": real_pic,
|
||||
"vod_remarks": remarks if remarks else ""
|
||||
})
|
||||
return {"list": videos}
|
||||
Reference in New Issue
Block a user