Files
ProxyPool/app/services/proxy_scoring.py
祀梦 7bc6d4e4de feat: JSON 配置、质量分与仪表盘,及设置与爬取流程
- 后端改为 config/app.json;pytest 使用 config/app.test.json 与 set_config_file,不再依赖环境变量;移除 pydantic-settings。

- 前端 API/WebSocket 由 config/webui.json 经 Vite define 注入。

- 代理分数按延迟与随机取用次数计算,新增 use_count 与 proxy_scoring;保存设置时同步调度器启停。

- 仪表盘双饼图(可用/待验证协议);设置页去掉调度器启停按钮并移动立即验证;爬取全部结束后自动提交全量验证。

- 删除 script/settings_maintain.py(此前已标记删除)。

Made-with: Cursor
2026-04-05 16:08:32 +08:00

55 lines
1.8 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.

"""代理质量分:延迟越低越高,被取用次数越多越低。
设计要点
--------
1. **延迟项**0100用平滑倒数把毫秒映射到质量避免线性过于极端。
``latency_quality = 100 / (1 + latency_ms / latency_ref_ms)``
在 ``latency_ref_ms`` 处约为 50 分;越快越接近 100。
2. **使用惩罚**:每次通过 API 随机取出代理视为一次「使用」,``use_count`` 递增;
惩罚 ``min(max_use_penalty, use_count * use_penalty_per_pick)`` 从延迟项上扣除。
3. **未知延迟**:尚无 ``response_time_ms`` 时用 ``default_latency_ms`` 代替,避免给满分。
验证失败仍走 ``update_score`` 扣分;验证成功则用本函数**覆盖**分数(与当前延迟、使用次数一致)。
"""
from __future__ import annotations
from typing import Optional
from app.core.config import Settings
def compute_proxy_quality_score(
latency_ms: Optional[float],
use_count: int,
settings: Settings,
) -> int:
"""根据延迟与累计使用次数计算 0100 的整数分。"""
ref = float(settings.score_latency_ref_ms)
penalty_per = float(settings.score_use_penalty_per_pick)
cap = float(settings.score_max_use_penalty)
default_lat = float(settings.score_default_latency_ms)
lo = int(settings.score_min)
hi = int(settings.score_max)
if ref <= 0:
ref = 500.0
if penalty_per < 0:
penalty_per = 0.0
if cap < 0:
cap = 0.0
if default_lat <= 0:
default_lat = 1500.0
ms = latency_ms
if ms is None or ms <= 0:
ms = default_lat
latency_quality = 100.0 / (1.0 + float(ms) / ref)
uses = max(0, int(use_count))
usage_penalty = min(cap, uses * penalty_per)
raw = latency_quality - usage_penalty
score = int(round(raw))
return max(lo, min(hi, score))