# Acquisition Dependencies

> 红龙获客系统依赖安装技能 v2.0 - 跨平台自动检测+安装。自动识别 Linux/Windows/macOS 环境，安装所有 Python/npm 系统依赖。触发：安装依赖、更新依赖、补全依赖、一键安装依赖。

- Skill: `wike-chi/acquisition-dependencies` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add wike-chi/acquisition-dependencies`
- Raw SKILL.md: https://api.skillmd.com/api/skills/wike-chi/acquisition-dependencies/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: wike-chi (https://skillmd.com/u/wike-chi)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/wike-chi/acquisition-dependencies

---


# 红龙获客系统 · 依赖安装技能 v2.0

> **Skill Graph：** 领域 → [[_index-meta|系统元技能领域]] | 上游 ← [[_index-acquisition|核心流程领域]] | 下游 → [[acquisition-init|系统初始化]]（依赖安装后）


## 功能

自动检测当前系统环境（Linux/Windows/macOS/WSL2），根据检测结果安装所有必需的 Python 和 npm 依赖。

## 一键安装

```bash
# Linux/macOS/WSL2
bash ~/.hermes/skills/acquisition/acquisition-dependencies/scripts/install-deps.sh

# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.hermes\skills\acquisition\acquisition-dependencies\scripts\install-deps.ps1"
```

离线环境下直接运行本地脚本即可（脚本已安装在 skills/ 目录内，无需联网）。

## 环境检测逻辑

```
检测顺序：
  1. uname -s  → 判断 Linux/Darwin/NT
  2. /proc/version → 判断 WSL2
  3. command -v node/npm/python3 → 判断已安装的工具
```

| 检测结果 | 系统类型 | 安装方式 |
|----------|----------|----------|
| Linux + /proc/version含microsoft | WSL2 | apt-get + node symlink修复 |
| Linux + 无WSL特征 | Debian/Ubuntu | apt-get |
| Darwin | macOS | brew |
| NT/CYGWIN/MINGW | Windows | PowerShell + pip |

## 陷阱记录

- **不要依赖远程curl安装**：GitHubraw可能不通，脚本必须已在本地 skills/ 目录内
- **WSL2 node路径问题**：WSL2下node可能在~/.nvm/，需要symlink到/usr/bin/否则子进程找不到
- **pip3 --user vs sudo apt**：apt的python包版本可能旧，pip3 --user补充安装确保最新版
- **Playwright Chromium体积大**：180MB，首次安装用tail -5避免长时间无输出
- **patch误删风险**：修改RETAINED_SKILLS清单时易漏掉整块技能组（如CRM/工具层），修复后需重新验证清单数量与目录一致

## 依赖清单

### Python 依赖（所有平台）

| 包名 | 用途 | 验证命令 |
|------|------|----------|
| openpyxl | Excel读写 | `python3 -c "import openpyxl"` |
| docx | Word读写 | `python3 -c "import docx"` |
| yaml | YAML解析 | `python3 -c "import yaml"` |
| Pillow | 图片处理 | `python3 -c "from PIL import Image"` |
| requests | HTTP请求 | `python3 -c "import requests"` |
| regex | 正则增强 | `python3 -c "import regex"` |
| lxml | XML/HTML解析 | `python3 -c "import lxml"` |
| playwright | 浏览器自动化 | `python3 -c "from playwright.sync_api import sync_playwright"` |

### Node.js 依赖（所有平台）

| 包名 | 用途 | 验证命令 |
|------|------|----------|
| nodemailer | 邮件发送 | `node -e "require('nodemailer')"` |

### 浏览器（可选）

| 浏览器 | 用途 | 安装命令 |
|--------|------|----------|
| Chromium | Playwright主力 | `python3 -m playwright install chromium` |
| Chrome | 备用 | `python3 -m playwright install chrome` |

## 安装脚本

### Linux/macOS: install-deps.sh

```bash
#!/usr/bin/env bash
# =============================================================
# 红龙获客系统 · 依赖安装脚本 (Linux/macOS/WSL2)
# 版本: 2.0.0 | 自动检测系统环境
# =============================================================

set -euo pipefail

# --- 颜色输出 ---
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'

log()  { echo -e "${CYAN}[$(date '+%H:%M:%S')]${NC} $*"; }
ok()   { echo -e "${GREEN}  ✓${NC}  $*"; }
warn() { echo -e "${YELLOW}  ⚠${NC}  $*"; }
fail() { echo -e "${RED}  ✗${NC}  $*"; }

# --- 环境检测 ---
detect_os() {
    local os_type
    case "$(uname -s)" in
        Linux*)     os_type="linux" ;;
        Darwin*)    os_type="macos" ;;
        CYGWIN*|MINGW*|MSYS*|NT*) os_type="windows" ;;
        *)          os_type="unknown" ;;
    esac

    # 检测 WSL2
    if [[ "$os_type" == "linux" ]] && grep -qi 'microsoft\|wsl' /proc/version 2>/dev/null; then
        os_type="wsl2"
    fi

    echo "$os_type"
}

detect_node() {
    if command -v node &>/dev/null; then
        echo "node: $(node --version)"
    else
        echo "node: NOT FOUND"
    fi

    if command -v npm &>/dev/null; then
        echo "npm: $(npm --version)"
    else
        echo "npm: NOT FOUND"
    fi

    if command -v python3 &>/dev/null; then
        echo "python3: $(python3 --version 2>&1)"
    elif command -v python &>/dev/null; then
        echo "python: $(python --version 2>&1)"
    else
        echo "python3: NOT FOUND"
    fi
}

# --- 检查依赖是否已安装 ---
check_python_pkg() {
    python3 -c "import $1" 2>/dev/null
}

check_npm_pkg() {
    node -e "require('$1')" 2>/dev/null
}

# --- 安装函数 ---
install_linux() {
    log "${BOLD}==> Linux/WSL2 环境${NC}"

    if command -v apt-get &>/dev/null; then
        log "检测到 apt 包管理器"
        sudo apt-get update -qq

        local pkgs=(
            python3-pip
            python3-openpyxl
            python3-docx
            python3-yaml
            python3-pil
            python3-requests
            python3-regex
            python3-lxml
        )

        log "安装 Python 系统包..."
        sudo apt-get install -y "${pkgs[@]}" 2>&1 | tail -5
        ok "系统包安装完成"
    else
        warn "apt 不可用，尝试 pip3 直接安装..."
    fi

    # pip3 补充安装（确保最新版本）
    log "使用 pip3 补充/升级包..."
    pip3 install --quiet --user openpyxl docx pyyaml Pillow requests regex lxml 2>&1 | tail -3
    ok "pip3 安装完成"
}

install_macos() {
    log "${BOLD}==> macOS 环境${NC}"

    if ! command -v brew &>/dev/null; then
        fail "Homebrew 未安装，请先安装: /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
        return 1
    fi

    log "安装 Homebrew 包..."
    brew install python3 node
    brew install python3-openpyxl python3-docx python3-yaml python3-pillow 2>/dev/null || true
    ok "Homebrew 安装完成"
}

install_python_deps() {
    log "${BOLD}==> 安装 Python 依赖${NC}"

    local python_pkgs="openpyxl docx pyyaml Pillow requests regex lxml"
    local failed=()

    for pkg in $python_pkgs; do
        if python3 -c "import ${pkg%%:*}" 2>/dev/null; then
            echo -n ""
        else
            if pip3 install --quiet --user "$pkg" 2>/dev/null; then
                ok "$pkg"
            else
                fail "$pkg 安装失败"
                failed+=("$pkg")
            fi
        fi
    done

    # Playwright
    if python3 -c "from playwright.sync_api import sync_playwright" 2>/dev/null; then
        ok "playwright 已安装"
    else
        log "安装 Playwright..."
        pip3 install --quiet playwright 2>&1 | tail -2
        python3 -m playwright install chromium --with-deps 2>&1 | tail -5
        ok "playwright + chromium 安装完成"
    fi

    if [[ ${#failed[@]} -gt 0 ]]; then
        warn "以下包安装失败: ${failed[*]}"
        return 1
    fi
    return 0
}

install_npm_deps() {
    log "${BOLD}==> 安装 Node.js 依赖${NC}"

    if ! command -v npm &>/dev/null; then
        warn "npm 未安装，跳过 Node.js 依赖"
        return 0
    fi

    local npm_pkgs="nodemailer"
    local failed=()

    for pkg in $npm_pkgs; do
        if node -e "require('$pkg')" 2>/dev/null; then
            ok "$pkg 已安装"
        else
            if npm install -g "$pkg" 2>/dev/null; then
                ok "$pkg"
            else
                fail "$pkg 安装失败"
                failed+=("$pkg")
            fi
        fi
    done

    if [[ ${#failed[@]} -gt 0 ]]; then
        warn "以下包安装失败: ${failed[*]}"
    fi
}

install_wsl2_extras() {
    log "${BOLD}==> WSL2 特殊处理${NC}"

    # WSL2 下确保 node path 正确
    local node_path
    if [[ -d "$HOME/.nvm/versions/node" ]]; then
        local node_version
        node_version=$(ls "$HOME/.nvm/versions/node" | head -1)
        if [[ -n "$node_version" ]]; then
            local nvm_node="$HOME/.nvm/versions/node/$node_version/bin/node"
            local nvm_npm="$HOME/.nvm/versions/node/$node_version/bin/npm"

            if [[ ! -L /usr/bin/node ]] && [[ -f "$nvm_node" ]]; then
                sudo ln -sf "$nvm_node" /usr/bin/node
                sudo ln -sf "$nvm_npm" /usr/bin/npm
                ok "node/npm symlink 已创建 → $node_version"
            fi
        fi
    fi
}

verify_all() {
    log "${BOLD}==> 验证安装${NC}"

    local failed=0

    # Python
    local py_pkgs="openpyxl docx yaml PIL requests regex lxml"
    for pkg in $py_pkgs; do
        local import_name="${pkg%%:*}"
        if python3 -c "import $import_name" 2>/dev/null; then
            ok "python: $pkg"
        else
            fail "python: $pkg MISSING"
            ((failed++))
        fi
    done

    # Playwright
    if python3 -c "from playwright.sync_api import sync_playwright" 2>/dev/null; then
        ok "python: playwright"
    else
        fail "python: playwright MISSING"
        ((failed++))
    fi

    # Node
    if node -e "require('nodemailer')" 2>/dev/null; then
        ok "node: nodemailer"
    else
        warn "node: nodemailer 未安装 (可选)"
    fi

    return $failed
}

# --- 主流程 ---
main() {
    echo ""
    echo "═══════════════════════════════════════════════════"
    echo "  红龙获客系统 · 依赖安装 v2.0"
    echo "═══════════════════════════════════════════════════"
    echo ""

    # 1. 环境检测
    local os_type
    os_type=$(detect_os)
    log "系统检测:"
    detect_node | while read -r line; do
        echo "       $line"
    done
    echo "       OS类型: $os_type"
    echo ""

    # 2. 根据系统安装
    case "$os_type" in
        linux|wsl2)
            install_linux
            if [[ "$os_type" == "wsl2" ]]; then
                install_wsl2_extras
            fi
            ;;
        macos)
            install_macos
            ;;
        windows)
            fail "Windows 原生环境请使用 PowerShell 脚本: install-deps.ps1"
            return 1
            ;;
        *)
            fail "无法识别的系统: $(uname -a)"
            return 1
            ;;
    esac

    # 3. Python + Playwright（所有环境）
    install_python_deps

    # 4. npm（所有环境）
    install_npm_deps

    # 5. 验证
    echo ""
    if verify_all; then
        echo ""
        ok "全部依赖安装成功！"
        echo ""
    else
        echo ""
        warn "部分依赖安装失败，请参考上方错误信息"
        return 1
    fi
}

main "$@"
```

---

## 详细参考

> 以下内容已拆分到 [[references/windows-install.md]]，仅在需要时读取：
> - acquisition-init 集成
> - 版本历史
>
> Windows PowerShell 安装脚本、集成说明和版本历史。

