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

179 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#coding=utf-8
#!/usr/bin/python
import os
import sys
import json
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
from importlib.machinery import SourceFileLoader
from urllib.parse import urlparse, parse_qs
import types
import base64
# ============================================================
# 禁止生成 __pycache__
# ============================================================
sys.dont_write_bytecode = True
# ============================================================
# 自动兼容旧版 Spider 导入
# ============================================================
if 'base' not in sys.modules:
base_module = types.ModuleType('base')
sys.modules['base'] = base_module
if 'base.spider' not in sys.modules:
import spider # spider.py 与 server.py 同目录
sys.modules['base.spider'] = spider
# ============================================================
# 强制标准输出为 UTF-8(防止中文打印报错)
# ============================================================
try:
sys.stdout.reconfigure(encoding='utf-8')
except Exception:
pass
# ============================================================
# Spider 动态加载
# ============================================================
_spider_module_cache = {} # 缓存模块对象
def load_spider(spider_name):
# 1️⃣ 检查模块缓存
if spider_name in _spider_module_cache:
module = _spider_module_cache[spider_name]
else:
# 2️⃣ 指定 sy 子目录
server_dir = os.path.dirname(os.path.abspath(__file__))
path = os.path.join(server_dir, "sy", f"{spider_name}.py")
if not os.path.exists(path):
raise FileNotFoundError(f"Spider file not found: {path}")
module = SourceFileLoader(spider_name, path).load_module()
_spider_module_cache[spider_name] = module
# 3️⃣ 每次生成新的 Spider 实例
spider_instance = module.Spider()
if hasattr(spider_instance, 'init'):
spider_instance.init(extend="") # 实时初始化
print(f"[载入] 已初始化 Spider: {spider_name}")
return spider_instance
# ============================================================
# 多线程 HTTPServer
# ============================================================
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
daemon_threads = True
timeout = 10
# ============================================================
# HTTP 请求处理
# ============================================================
class SpiderHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.connection.settimeout(10)
query = urlparse(self.path).query
params = parse_qs(query)
response = {}
sp = params.get('sp', [None])[0]
t = params.get('t', [None])[0]
pg = params.get('pg', ['1'])[0]
ids = params.get('ids', [None])[0]
play = params.get('play', [None])[0]
wd = params.get('wd', [None])[0]
filter_param = params.get('filter', [None])[0]
# 兼容 ext 参数(Base64 编码 JSON
ext = params.get('ext', [None])[0]
ext_obj = {}
if ext:
try:
ext_json = base64.b64decode(ext).decode('utf-8')
ext_obj = json.loads(ext_json) if ext_json.strip() else {}
except Exception:
ext_obj = {}
if not sp:
self.send_error(400, "Missing 'sp' parameter (e.g. ?sp=Iktv)")
return
try:
spider = load_spider(sp)
# ===========================
# 根据参数判断访问类型
# ===========================
if (not t and not ids and not play and not wd) or (filter_param and not t and not ids and not play and not wd):
response = spider.homeContent(filter=filter_param)
access_type = "home"
elif ids:
response = spider.detailContent([ids])
access_type = "detail"
elif play:
response = spider.playerContent("", play, None)
access_type = "play"
elif wd:
response = spider.searchContent(key=wd, quick=False)
access_type = "search"
elif t:
response = spider.categoryContent(t, pg, None, ext_obj)
access_type = "category"
else:
response = spider.homeContent(filter=filter_param)
access_type = "home"
# ===========================
# 返回 JSON
# ===========================
self.send_response(200)
self.send_header("Content-type", "application/json; charset=utf-8")
self.end_headers()
try:
self.wfile.write(json.dumps(response, ensure_ascii=False).encode('utf-8'))
except BrokenPipeError:
print("[警告] 客户端已断开连接(BrokenPipeError")
return
# 日志
try:
log_line = f"[访问] Spider={sp}, 类型={access_type}, params={params}"
print(log_line.encode('utf-8', 'ignore').decode('utf-8'))
except Exception as log_error:
print("[日志错误]", log_error)
except BrokenPipeError:
print("[警告] 客户端已断开连接(BrokenPipeError")
except Exception as e:
self.send_response(500)
self.end_headers()
try:
self.wfile.write(str(e).encode('utf-8'))
except Exception:
pass
print(f"[错误] {e}")
# ============================================================
# 启动服务
# ============================================================
def run_server(host="0.0.0.0", port=8080):
try:
server = ThreadingHTTPServer((host, port), SpiderHandler)
print(f"[提示] 动态 Spider 服务已启动: http://{host}:{port}/?sp=YourSpider")
server.serve_forever()
except Exception as e:
print(f"[错误] 服务启动失败: {e}")
# ============================================================
# 命令行入口
# ============================================================
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--port", type=int, default=8080, help="端口号")
args = parser.parse_args()
run_server(port=args.port)