Skip to content

Hawk0321/vpn_gateway

Repository files navigation

VPN Gateway - 智能节点切换系统

基于 Clash 的多节点智能切换系统,专为数据采集场景设计。通过程序化控制 VPN 节点,实现多 IP 轮换,提升爬虫效率。

功能特性

  • 自动切换多国节点 - 支持按国家、延迟、成功率智能切换
  • 智能节点选择 - 基于延迟和成功率的综合评分
  • 节点健康监控 - 实时统计节点性能,自动剔除异常节点
  • 无缝集成 - 提供 Scrapy 中间件,支持任何使用 requests 的框架
  • 多种策略 - 支持手动、定时、请求数、智能等多种切换策略

架构设计

爬虫代码 (Scrapy / Requests / aiohttp)
    ↓ proxies={'http': 'http://127.0.0.1:8901'}
VPN Gateway
    ├─ VPNGateway    — 统一入口,管理切换策略
    ├─ ClashClient   — Clash API 通信 (:9097)
    └─ NodeManager   — 节点过滤、评分、统计
    ↓ API 控制节点切换
Clash mihomo 内核 (port 8901)
    ↓
VPN 节点 (🇭🇰🇯🇵🇸🇬🇹🇼🇺🇸🇬🇧)

关于代理端口

端口 用途 说明
8901 爬虫专用 Clash 内核直连,IP 跟随节点切换,VPNGateway 初始化时自动开启
7897 日常上网 Clash Verge 主进程转发,节点由 Clash Verge 界面控制
9097 API 控制 Clash External Controller,用于程序化控制节点

重要: 爬虫必须用 8901 端口。7897 是 Clash Verge 主进程转发,IP 不跟随程序切换节点。

快速开始

前置要求

  • Clash Verge 客户端(推荐 Clash Verge Rev
  • Python 3.7+
  • 活跃的 VPN 订阅(含多国节点)
  • 支持平台: macOS / Windows / Linux

安装

# 1. 克隆项目
git clone <repository-url>
cd vpn_gateway

# 2. 安装依赖
pip install -r requirements.txt

# 3. 配置
cp config.example.yaml config.yaml
# 编辑 config.yaml:
#   clash.port: 9097 (Clash Verge 默认)
#   clash.secret: 你的 API 密码
#   proxy.port: 8901 (内核直连端口)

Clash Verge 配置

  1. 下载安装 Clash Verge Rev

    • macOS: .dmg(Apple Silicon 选 aarch64,Intel 选 x64
    • Windows: .msi 安装包
    • Linux: .deb / .rpm / .AppImage
  2. 导入 VPN 订阅 → 设置 → 订阅 → 添加订阅地址

  3. 启用 External Controller

    • 设置 → Clash 内核
    • External Controller: 127.0.0.1:9097
    • Secret: 设置密码(需与 config.yaml 一致)
  4. 测试连接

    python test_connection.py 127.0.0.1 9097 <your-secret> 8901

基础使用

from src import VPNGateway
import requests

gateway = VPNGateway("config.yaml")
proxy = gateway.get_proxy()  # {'http': 'http://127.0.0.1:8901', ...}

# 切换到美国节点
gateway.switch_to_country('US')

# 发起请求
response = requests.get('https://api.ipify.org', proxies=proxy)
print(f"当前 IP: {response.text}")

# 记录结果(驱动智能切换)
gateway.record_request(success=response.ok)

爬虫集成

带自动切换的请求封装

from src import VPNGateway
import requests, time

gateway = VPNGateway("config.yaml")
proxy = gateway.get_proxy()

def scrape_with_rotation(url, max_retries=3, **kwargs):
    """请求失败自动切换节点重试"""
    for attempt in range(max_retries):
        try:
            resp = requests.get(url, proxies=proxy, timeout=15, **kwargs)
            if resp.status_code in (403, 429, 503):
                gateway.record_request(success=False)
                gateway.smart_switch()
                time.sleep(2)
                continue
            gateway.record_request(success=True)
            return resp
        except (requests.Timeout, requests.ConnectionError):
            gateway.record_request(success=False)
            gateway.smart_switch()
            time.sleep(2)
    return None

按国家轮换采集

countries = ['US', 'JP', 'SG', 'HK', 'GB', 'TW']

for i, url in enumerate(url_list):
    country = countries[i % len(countries)]
    gateway.switch_to_country(country)
    time.sleep(1)
    resp = scrape_with_rotation(url)
    if resp:
        process(resp)

Scrapy 集成

python examples/scrapy_integration.py

详见 examples/scrapy_integration.py 中的 VPNMiddleware 实现。

配置说明

config.yaml 完整配置:

clash:
  host: "127.0.0.1"
  port: 9097              # Clash External Controller 端口
  secret: "your-secret"   # API 密码

proxy:
  host: "127.0.0.1"
  port: 8901              # 内核直连端口(爬虫用)

strategy:
  mode: "smart"           # manual | time_based | request_based | smart
  time_interval: 300      # time_based: 每 N 秒切换
  request_threshold: 100  # request_based: 每 N 个请求切换
  smart:
    health_check_interval: 60
    failure_rate_threshold: 0.3  # 失败率超过 30% 自动切换

node_filter:
  include_countries: []   # 例: ["US", "JP", "SG"]
  exclude_countries: []
  include_keywords: []    # 例: ["优质", "IEPL"]
  exclude_keywords: []

切换策略

策略 说明 适用场景
manual 不自动切换 手动控制
time_based 每 N 秒切换 长时间采集
request_based 每 N 个请求切换 批量采集
smart 失败率过高自动切换 爬虫推荐

API 速查

gateway.get_proxy()                    # 获取代理字典
gateway.switch_to_country('US')        # 切到指定国家
gateway.switch_to_node(node_name)      # 切到指定节点
gateway.smart_switch()                 # 自动选最优节点
gateway.record_request(success=True)   # 记录请求结果
gateway.get_available_nodes()          # 列出所有可用节点
gateway.get_current_node()             # 当前节点名
gateway.get_nodes_by_country()         # 按国家分组
gateway.get_stats()                    # 统计信息

Terminal 代理设置

# 爬虫任务(跟随程序节点切换)
export http_proxy=http://127.0.0.1:8901
export https_proxy=http://127.0.0.1:8901

# 日常上网
export http_proxy=http://127.0.0.1:7897
export https_proxy=http://127.0.0.1:7897

# 取消代理
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY

故障排查

Clash API 连不上

# 检查 Clash 是否运行
# macOS/Linux:
ps aux | grep -i clash
# Windows:
tasklist | findstr clash

# 测试 API
curl --noproxy "*" http://127.0.0.1:9097/proxies

节点切换后 IP 不变

  1. 确认使用的是 8901 端口(不是 7897)
  2. 确认 Clash 运行模式为 Global:curl --noproxy "*" http://127.0.0.1:9097/configs | python -m json.tool | grep mode
  3. 运行验证脚本:python test_connection.py 127.0.0.1 9097 <secret> 8901

查找 Clash 配置文件

python scripts/find_clash_config.py

文档

安全提示

  • config.yaml 包含 API 密码,已在 .gitignore
  • 不要将订阅链接提交到代码仓库
  • 使用 config.example.yaml 作为模板分享

许可证

MIT License

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages