Coverage for src / keyword_research / analyzer.py: 98%
44 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-13 20:29 +0800
« prev ^ index » next coverage.py v7.13.4, created at 2026-02-13 20:29 +0800
1"""关键词分析器.
3提供关键词竞争度和价值分析功能。
4"""
6from __future__ import annotations
8from dataclasses import dataclass
9from typing import TYPE_CHECKING
11if TYPE_CHECKING:
12 from src.keyword_research.google_planner import KeywordData
15@dataclass
16class KeywordScore:
17 """关键词评分结果.
19 Attributes:
20 keyword: 关键词
21 search_volume_score: 搜索量得分 (0-100)
22 competition_score: 竞争度得分 (0-100,越高越好)
23 value_score: 综合价值得分 (0-100)
24 overall_score: 总体得分 (0-100)
25 recommendation: 推荐等级 (high, medium, low)
26 """
28 keyword: str
29 search_volume_score: float
30 competition_score: float
31 value_score: float
32 overall_score: float
33 recommendation: str
36class KeywordAnalyzer:
37 """关键词竞争度和价值分析器."""
39 def __init__(self) -> None:
40 """初始化分析器."""
41 self.volume_weights = {
42 "very_high": (10000, 100),
43 "high": (1000, 80),
44 "medium": (100, 60),
45 "low": (10, 40),
46 "very_low": (0, 20),
47 }
49 def calculate_volume_score(self, avg_monthly_searches: int) -> float:
50 """计算搜索量得分."""
51 for _tier, (threshold, score) in sorted(
52 self.volume_weights.items(),
53 key=lambda x: x[1][0],
54 reverse=True,
55 ):
56 if avg_monthly_searches >= threshold:
57 return float(score)
58 return 0.0
60 def calculate_competition_score(self, competition: str, cpc: float) -> float:
61 """计算竞争度得分(越高竞争越好)."""
62 competition_map = {"LOW": 80, "MEDIUM": 50, "HIGH": 20}
63 base_score = competition_map.get(competition.upper(), 50)
65 # CPC 调整
66 if cpc < 1.0:
67 cpc_adjustment = 10
68 elif cpc < 3.0:
69 cpc_adjustment = 0
70 else:
71 cpc_adjustment = -10
73 return max(0, min(100, base_score + cpc_adjustment))
75 def calculate_value_score(
76 self, volume_score: float, competition_score: float, cpc: float
77 ) -> float:
78 """计算综合价值得分."""
79 base_value = volume_score * 0.4 + competition_score * 0.4
80 cpc_value = min(20, cpc * 5)
81 return min(100, base_value + cpc_value)
83 def analyze(self, data: KeywordData) -> KeywordScore:
84 """分析单个关键词."""
85 avg_cpc = (data.low_cpc + data.high_cpc) / 2
87 volume_score = self.calculate_volume_score(data.avg_monthly_searches)
88 competition_score = self.calculate_competition_score(data.competition, avg_cpc)
89 value_score = self.calculate_value_score(volume_score, competition_score, avg_cpc)
91 overall_score = volume_score * 0.3 + competition_score * 0.3 + value_score * 0.4
93 if overall_score >= 70:
94 recommendation = "high"
95 elif overall_score >= 50:
96 recommendation = "medium"
97 else:
98 recommendation = "low"
100 return KeywordScore(
101 keyword=data.keyword,
102 search_volume_score=volume_score,
103 competition_score=competition_score,
104 value_score=value_score,
105 overall_score=overall_score,
106 recommendation=recommendation,
107 )