diff --git a/app.py b/app.py index c230184..464ddf4 100755 --- a/app.py +++ b/app.py @@ -29,7 +29,36 @@ async def mail_qq_spider(account: str,display: int) -> str: return json.dumps(data, ensure_ascii=False) except Exception as e: data["status"] = 500 - return json.dumps(data, ensure_ascii=False) + return json.dumps(data, ensure_ascii=False)@mcp.tool() +async def start_xvnc_server(display: int) -> str: + """启动VNC服务 + + Args: + display: VNC 显示编号 + """ + data={"display": display} + try: + # 调用外部 start_browser.sh 脚本,传入 index 作为参数 + process = await asyncio.create_subprocess_exec( + f"{SHELL_DIR}/start_browser.sh", + str("123456"), # VNC 密码 + str(5900), # VNC 端口 + str(99), # 显示编号 + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE + ) + stdout, stderr = await process.communicate() + data["message"] = stdout.decode() + data["status"] = 200 if process.returncode == 0 else 500 + + if process.returncode == 0: + data["vnc_url"] = f"{VNC_SERVER_HOST}/vnc_lite.html?path=?token=user{display}" + return json.dumps(data, ensure_ascii=False) + else: + return json.dumps(data, ensure_ascii=False) + except Exception as e: + data["status"] = 500 + return json.dumps(data, ensure_ascii=False) @mcp.tool() async def start_vnc_server(display: int) -> str: """启动VNC服务 diff --git a/bin/start_browser.sh b/bin/start_browser.sh new file mode 100755 index 0000000..d76e2df --- /dev/null +++ b/bin/start_browser.sh @@ -0,0 +1,81 @@ +#!/bin/bash +set -euo pipefail + +TARGET_URL="https://www.baidu.com" # 直接打开百度 +VNC_PWD=$1 +VNC_PORT=$2 +DISPLAY_NUM=$3 +CDP_PORT=30010 +PROFILE_DIR="/tmp/chrome-profile-$$" +LOCK_FILE="/tmp/cdp.lock" + + +GREEN='\033[0;32m'; RED='\033[0;31m'; NC='\033[0m' +log() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $*"; } +err() { echo -e "${RED}[$(date '+%H:%M:%S')]${NC} $*" >&2; } + +exec 9>"$LOCK_FILE" +flock -n 9 || { err "Another instance running"; exit 1; } + +cleanup() { + log "Cleaning up..." + pkill -P $$ 2>/dev/null || true + pkill -f "remote-debugging-port=${CDP_PORT}" 2>/dev/null || true + pkill -f "Xvfb :${DISPLAY_NUM}" 2>/dev/null || true + pkill -f "x11vnc.*${DISPLAY_NUM}" 2>/dev/null || true + rm -rf "$PROFILE_DIR" 2>/dev/null || true + rm -f /tmp/login_done 2>/dev/null || true +} +trap cleanup EXIT INT TERM + +log "Starting Xvfb :${DISPLAY_NUM}" +Xvfb :${DISPLAY_NUM} -screen 0 1280x1024x24 -nolisten tcp & +sleep 2 +export DISPLAY=:${DISPLAY_NUM} + +log "Starting Chromium" +mkdir -p "$PROFILE_DIR" +CHROME_BIN=$(ls $HOME/.cache/ms-playwright/chromium-*/chrome-linux/chrome 2>/dev/null | head -1) +if [ -z "$CHROME_BIN" ]; then + CHROME_BIN=$(which chromium-browser 2>/dev/null || which google-chrome-stable 2>/dev/null || true) +fi +[ -z "$CHROME_BIN" ] && { err "Chromium not found"; exit 1; } + +# 去掉 --headless=new,这样才能看到界面 +"$CHROME_BIN" \ + --no-sandbox \ + --disable-gpu \ + --disable-dev-shm-usage \ + --remote-debugging-port=${CDP_PORT} \ + --remote-debugging-address=127.0.0.1 \ + --remote-allow-origins=* \ + --user-data-dir=${PROFILE_DIR} \ + --window-size=1280,1024 \ + "${TARGET_URL}" & + +CHROME_PID=$! + +# 启动 x11vnc(将 Xvfb 转为 VNC 服务) +log "Starting x11vnc on port ${VNC_PORT}..." +x11vnc -display :${DISPLAY_NUM} -forever -shared -passwd ${VNC_PWD} -rfbport ${VNC_PORT} -bg & + +log "Waiting for CDP..." +for i in {1..30}; do + curl -sf "http://127.0.0.1:${CDP_PORT}/json/version" >/dev/null 2>&1 && { log "CDP ready"; break; } + sleep 1 + [ $i -eq 30 ] && { err "CDP timeout"; exit 1; } +done + +PUBLIC_HOST=$(curl -sf ifconfig.me 2>/dev/null || hostname -I | awk '{print $1}') +log "==========================================" +log "✅ Browser is running!" +log "📝 CDP: http://${PUBLIC_HOST}:${CDP_PORT}" +log "🖥️ VNC: ${PUBLIC_HOST}:${VNC_PORT} (密码: ${VNC_PWD})" +log "==========================================" + +rm -f /tmp/login_done +log "Waiting for /tmp/login_done ..." +while [ ! -f /tmp/login_done ]; do sleep 1; done +log "Login detected, automation can start" + +wait $CHROME_PID 2>/dev/null || true diff --git a/bin/update.sh b/bin/update.sh index 0eb22e2..88f257c 100644 --- a/bin/update.sh +++ b/bin/update.sh @@ -1,7 +1,7 @@ #!/bin/bash PUBLIC_DIR="${1:-/shared}" -GIT_PY_SPIDER="${2:-https://git.nps.crabapples.cn/crabapples/learn-spider.git}" +GIT_PY_SPIDER="${2:-https://git.nps.crabapples.cn}" echo "开始更新爬虫" cd $PUBLIC_DIR if [ -d "learn-spider" ]; then diff --git a/start_spider.sh b/start_spider.sh deleted file mode 100644 index 8a8e676..0000000 --- a/start_spider.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -spider_code=$1 -echo "爬虫代码:$spider_code" -if [ "$spider_code" = "01" ]; then - spider_name="china_net.py" -elif [ "$spider_code" = "02" ]; then - spider_name="mail_qq.py" -else - echo "爬虫名称错误" - exit -1 -fi -echo "爬虫名称:$spider_name" -.venv/bin/python3.12 "spider/$spider_name" \ No newline at end of file