This commit is contained in:
zhinianboke 2025-09-27 19:34:47 +08:00
parent e189bde70a
commit a09f2c3873
7 changed files with 157 additions and 14 deletions

6
.gitignore vendored
View File

@ -372,4 +372,8 @@ check_disk_usage.py
.env
.env.*
!.env.example
.env.docker
.env.docker
# === 允许跟踪二进制扩展模块(用于分发)===
!utils/xianyu_slider_stealth*.pyd
!utils/xianyu_slider_stealth*.so

View File

@ -5613,7 +5613,7 @@ class XianyuLive:
await self.close_session() # 确保关闭session
# 从全局实例字典中注销当前实例
self._unregister_instance()
# self._unregister_instance()
logger.info(f"{self.cookie_id}】XianyuLive主程序已完全退出")
async def get_item_list_info(self, page_number=1, page_size=20, retry_count=0):

75
build_binary_module.py Normal file
View File

@ -0,0 +1,75 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
utils/xianyu_slider_stealth.py 编译为可直接 import 的二进制扩展模块.pyd/.so
- 使用 Nuitka --module 模式
- 输出文件放到 utils/ 目录名称为 xianyu_slider_stealth.<abi>.pyd/.so
- 这样 Python 将优先加载二进制扩展而不是同名 .py
"""
import sys
import subprocess
from pathlib import Path
SRC = Path("utils/xianyu_slider_stealth.py")
OUT_DIR = Path("utils")
def ensure_nuitka():
try:
import nuitka # noqa: F401
print("✓ Nuitka 已安装")
return True
except Exception:
print("✗ 未检测到 Nuitka。请先允许我安装: pip install nuitka ordered-set zstandard")
return False
def build():
OUT_DIR.mkdir(parents=True, exist_ok=True)
cmd = [
sys.executable, "-m", "nuitka",
"--module",
"--output-dir=%s" % str(OUT_DIR),
"--remove-output",
"--assume-yes-for-downloads",
"--show-progress",
"--python-flag=no_docstrings",
"--python-flag=no_warnings",
"--enable-plugin=anti-bloat",
str(SRC)
]
print("执行编译命令:\n ", " ".join(cmd))
result = subprocess.run(cmd, text=True)
if result.returncode != 0:
print("✗ 编译失败 (Nuitka 返回非零)")
return 1
# 列出 utils 目录下的产物
built = sorted(p for p in OUT_DIR.glob("xianyu_slider_stealth.*.pyd"))
if not built:
built = sorted(p for p in OUT_DIR.glob("xianyu_slider_stealth.*.so"))
if not built:
print("✗ 未找到编译产物。请检查输出日志。")
return 2
print("\n✓ 编译产物:")
for p in built:
print(" -", p)
return 0
def main():
if not SRC.exists():
print(f"✗ 源文件不存在: {SRC}")
return 1
if not ensure_nuitka():
return 2
return build()
if __name__ == "__main__":
raise SystemExit(main())

View File

@ -119,8 +119,8 @@ start_services() {
# 停止服务
stop_services() {
print_info "停止服务..."
docker-compose down
print_success "服务已停止"
docker-compose stop
print_success "服务已停止(未删除容器和镜像)"
}
# 重启服务
@ -249,19 +249,19 @@ update_deployment() {
# 清理环境
cleanup() {
print_warning "这将删除所有容器、镜像和数据,确定要继续吗?(y/N)"
print_warning "这将停止服务并清理数据目录,但不会删除容器和镜像,确定要继续吗?(y/N)"
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
print_info "清理环境..."
# 停止并删除容器
docker-compose down -v --rmi all
# 删除数据目录
print_info "清理环境(保留容器与镜像)..."
# 停止容器,保留历史容器与镜像
docker-compose stop || true
# 删除数据目录(如需保留数据,可注释下行)
rm -rf data logs backups
print_success "环境清理完成"
print_success "环境清理完成(容器与镜像已保留)"
else
print_info "取消清理操作"
fi

View File

@ -60,6 +60,13 @@ email-validator>=2.0.0
# ==================== 数据处理和验证 ====================
xlsxwriter>=3.1.0
# ==================== 构建二进制扩展模块Nuitka ====================
# 用于运行 build_binary_module.py 将 utils/xianyu_slider_stealth.py 编译为 .pyd/.so
nuitka>=2.7
ordered-set>=4.1.0
zstandard>=0.22.0
# ==================== 版本说明 ====================
# 本文件包含闲鱼自动回复系统的所有必需依赖
# 版本号已经过测试验证,确保兼容性和稳定性

Binary file not shown.

View File

@ -0,0 +1,57 @@
# This file was generated by Nuitka
# Stubs included by default
from __future__ import annotations
from playwright.sync_api import ElementHandle, sync_playwright
from typing import Any, Dict, List, Optional, Tuple
from typing_extensions import Self
import asyncio
import json
import logging
import os
import random
import time
class XianyuSliderStealth:
def __init__(self: Self, user_id: str, enable_learning: bool) -> None: ...
def init_browser(self: Self) -> Any: ...
def _load_success_history(self: Self) -> List[Dict[str, Any]]: ...
def _save_success_record(self: Self, trajectory_data: Dict[str, Any]) -> Any: ...
def _optimize_trajectory_params(self: Self) -> Dict[str, Any]: ...
def _get_cookies_after_success(self: Self) -> Any: ...
def _save_cookies_to_file(self: Self, cookies: Any) -> Any: ...
def _get_random_browser_features(self: Self) -> Any: ...
def _get_stealth_script(self: Self, browser_features: Any) -> Any: ...
def generate_human_trajectory(self: Self, distance: float) -> Any: ...
def simulate_slide(self: Self, slider_button: ElementHandle, trajectory: Any) -> Any: ...
def find_slider_elements(self: Self) -> Any: ...
def calculate_slide_distance(self: Self, slider_button: ElementHandle, slider_track: ElementHandle) -> Any: ...
def check_verification_success(self: Self, slider_button: ElementHandle) -> Any: ...
def check_page_changed(self: Self) -> Any: ...
def check_verification_failure(self: Self) -> Any: ...
def solve_slider(self: Self) -> Any: ...
def close_browser(self: Self) -> Any: ...
def run(self: Self, url: str) -> Any: ...
def process_user_url(user_id: str, url: str, enable_learning: bool) -> Any:
...
__name__ = ...
# Modules used internally, to allow implicit dependencies to be seen:
import time
import random
import logging
import asyncio
import json
import os
import playwright
import playwright.sync_api
import playwright.sync_api.sync_playwright
import playwright.sync_api.ElementHandle
import typing
import re
import sys