Coverage for src/keyword_research/analyzer.py: 98%

1"""关键词分析器.

2

3提供关键词竞争度和价值分析功能。

4"""

5

6 from __future__ import annotations

7

8 from dataclasses import dataclass

9 from typing import TYPE_CHECKING

10

11 if TYPE_CHECKING:

12 from src.keyword_research.google_planner import KeywordData

13

14

15@dataclass

16 class KeywordScore:

17 """关键词评分结果.

18

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 """

27

28 keyword: str

29 search_volume_score: float

30 competition_score: float

31 value_score: float

32 overall_score: float

33 recommendation: str

34

35

36 class KeywordAnalyzer:

37 """关键词竞争度和价值分析器."""

38

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 }

48

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

59

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)

64

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

72

73 return max(0, min(100, base_score + cpc_adjustment))

74

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)

82

83 def analyze(self, data: KeywordData) -> KeywordScore:

84 """分析单个关键词."""

85 avg_cpc = (data.low_cpc + data.high_cpc) / 2

86

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)

90

91 overall_score = volume_score * 0.3 + competition_score * 0.3 + value_score * 0.4

92

93 if overall_score >= 70:

94 recommendation = "high"

95 elif overall_score >= 50:

96 recommendation = "medium"

97 else:

98 recommendation = "low"

99

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 )