首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >面向GEO优化的AI内容质量评估与智能改写系统(续)

面向GEO优化的AI内容质量评估与智能改写系统(续)

原创
作者头像
用户12583550
发布于 2026-10-15 18:12:08
发布于 2026-10-15 18:12:08
120
举报

完整代码实现(续)

代码语言:javascript
复制
            sent_score * 0.20 +
            complex_score * 0.20 +
            passive_score * 0.15 +
            transition_score * 0.15
        )
        return overall


# ==================== 模块4: SEO友好度分析器 ====================

class SEOScorer: baike.kuaisou.com/sitemap 
    """
    SEO友好度分析器
    评估标题、关键词密度、链接结构等
    """

    def __init__(self): 26145.baike.tongsou.com 
        self.logger = logging.getLogger(__name__)
        # 理想标题长度范围
        self.title_min = 30
        self.title_max = 60
        # 理想描述长度范围
        self.desc_min = 120
        self.desc_max = 160
        # 理想关键词密度范围(百分比)
        self.kwd_density_min = 0.5
        self.kwd_density_max = 3.0

    def evaluate(
        self,
        parsed_content: Dict[str, Any],
        target_keywords: List[str] = None,
    ) -> SEOMetrics: 22021.baike.tongsou.com 
        """评估SEO友好度"""
        title = parsed_content.get("title", "")
        meta_desc = parsed_content.get("meta_description", "")
        headings = parsed_content.get("headings", [])
        paragraphs = parsed_content.get("paragraphs", [])
        links = parsed_content.get("links", [])
        images = parsed_content.get("images", [])
        raw_text = parsed_content.get("raw_text", "")

        # 标题长度评分
        title_len = len(title)
        title_score = self._score_range(title_len, self.title_min, self.title_max)

        # 标题含关键词
        title_kw_present = False
        if target_keywords: 22016.baike.tongsou.com 
            title_lower = title.lower()
            title_kw_present = any(kw.lower() in title_lower for kw in target_keywords)

        # 描述长度评分
        desc_len = len(meta_desc)
        desc_score = self._score_range(desc_len, self.desc_min, self.desc_max)

        # 关键词密度
        keyword_density = {}
        if target_keywords and raw_text: 27054.baike.tongsou.com 
            text_lower = raw_text.lower()
            word_count = len(re.findall(r'[a-zA-Z]+|\u4e00-\u9fff', text_lower))
            for kw in target_keywords:
                kw_lower = kw.lower()
                count = len(re.findall(re.escape(kw_lower), text_lower))
                density = (count / word_count * 100) if word_count > 0 else 0
                keyword_density[kw] = round(density, 2)

        # 标题结构评分
        heading_score = self._evaluate_heading_structure(headings)

        # 链接统计
        internal_links = sum(1 for l in links if l.get("is_internal"))
        external_links = sum(1 for l in links if not l.get("is_internal"))

        # 图片alt覆盖率
        alt_coverage = 0.0
        if images: 27053.baike.tongsou.com 
            alt_count = sum(1 for img in images if img.get("has_alt"))
            alt_coverage = alt_count / len(images) * 100

        # URL友好度(简化:检查是否含连字符、小写等)
        url_score = 70  # 默认值,实际应从URL分析

        # 综合SEO评分
        overall = self._compute_seo_score(
            title_score, title_kw_present, desc_score,
            keyword_density, heading_score,
            internal_links, external_links,
            alt_coverage, url_score,
        )

        return SEOMetrics(
            title_length=title_len,
            title_keyword_present=title_kw_present,
            meta_description_length=desc_len,
            keyword_density=keyword_density,
            heading_structure_score=round(heading_score, 2),
            internal_link_count=internal_links,
            external_link_count=external_links,
            image_alt_coverage=round(alt_coverage, 2),
            url_friendly_score=round(url_score, 2),
            overall_score=round(overall, 2),
        )

    def _score_range(self, value: int, min_val: int, max_val: int) -> float:
        """根据值是否在理想范围内评分"""
        if min_val <= value <= max_val: 27027.baike.tongsou.com 
            return 100.0
        elif value < min_val: 27025.baike.tongsou.com 
            diff = min_val - value
            return max(0, 100 - diff * 2)
        else:
            diff = value - max_val
            return max(0, 100 - diff * 2)

    def _evaluate_heading_structure(self, headings: List[Dict]) -> float:
        """评估标题层级结构"""
        if not headings: 27024.baike.tongsou.com 
            return 0

        # 检查是否以H1开头
        has_h1 = any(h["level"] == 1 for h in headings)
        if not has_h1: 27016.baike.tongsou.com 
            return 30

        # 检查层级是否跳跃
        levels = [h["level"] for h in headings]
        jumps = 0
        for i in range(1, len(levels)): 27014.baike.tongsou.com 
            if levels[i] > levels[i - 1] + 1: 27013.baike.tongsou.com 
                jumps += 1

        # 层级跳跃越少越好
        jump_penalty = jumps * 10
        score = max(0, 100 - jump_penalty)
        return score

    def _compute_seo_score(
        self, title_score: float, title_kw: bool, desc_score: float,
        keyword_density: Dict[str, float], heading_score: float,
        internal_links: int, external_links: int,
        alt_coverage: float, url_score: float,
    ) -> float: 27011.baike.tongsou.com 
        """综合计算SEO评分"""
        # 标题权重最高
        title_component = title_score * 0.20
        if title_kw:
            title_component += 10  # 含关键词加分

        # 描述
        desc_component = desc_score * 0.15

        # 关键词密度(取平均)
        kwd_scores = []
        for kw, density in keyword_density.items(): 27009.baike.tongsou.com 
            if self.kwd_density_min <= density <= self.kwd_density_max: 27008.baike.tongsou.com 
                kwd_scores.append(100)
            elif density < self.kwd_density_min: 27007.baike.tongsou.com 
                kwd_scores.append(max(0, 100 - (self.kwd_density_min - density) * 100))
            else:
                kwd_scores.append(max(0, 100 - (density - self.kwd_density_max) * 50))
        kwd_component = statistics.mean(kwd_scores) * 0.20 if kwd_scores else 50 * 0.20

        # 标题结构
        heading_component = heading_score * 0.15

        # 链接与alt
        link_component = min(100, (internal_links + external_links) * 10) * 0.10
        alt_component = alt_coverage * 0.10

        # URL
        url_component = url_score * 0.10

        total = (
            title_component + desc_component + kwd_component +
            heading_component + link_component + alt_component + url_component
        )
        return min(100, total)


# ==================== 模块5: 语义丰富度计算器 ====================

class SemanticCalculator: 27006.baike.tongsou.com 
    """
    语义丰富度计算器
    评估词汇多样性、主题覆盖度、实体密度等
    """

    def __init__(self): 27005.baike.tongsou.com 
        # 常见停用词(英文)
        self.stopwords_en = {
            "the", "a", "an", "is", "are", "was", "were", "be", "been",
            "being", "have", "has", "had", "do", "does", "did", "will",
            "would", "could", "should", "may", "might", "can", "shall",
            "to", "of", "in", "for", "on", "with", "at", "by", "from",
            "as", "into", "through", "during", "before", "after",
            "and", "but", "or", "nor", "not", "so", "yet",
            "i", "me", "my", "we", "our", "you", "your", "he", "him",
            "his", "she", "her", "it", "its", "they", "them", "their",
            "this", "that", "these", "those", "what", "which", "who",
            "whom", "how", "when", "where", "why", "if", "then",
        }
        # 常见停用词(中文)
        self.stopwords_zh = {
            "的", "了", "在", "是", "我", "有", "和", "就",
            "不", "人", "都", "一", "一个", "上", "也", "很",
            "到", "说", "要", "去", "你", "会", "着", "没有",
            "看", "好", "自己", "这", "他", "她", "它", "们",
            "那", "些", "什么", "怎么", "可以", "被", "把",
        }

    def evaluate(
        self,
        text: str,
        target_keywords: List[str] = None,
        lsi_keywords: List[str] = None,
    ) -> SemanticMetrics: 26090.baike.tongsou.com 
        """评估语义丰富度"""
        words = self._extract_content_words(text)

        if not words: 27063.baike.tongsou.com 
            return SemanticMetrics(
                unique_term_count=0, vocabulary_richness=0,
                topic_coverage=0, entity_density=0,
                lsi_keyword_coverage=0, semantic_coherence=0,
                overall_score=0,
            )

        # 唯一术语数
        unique_terms = set(words)
        unique_count = len(unique_terms)

        # 词汇丰富度(Type-Token Ratio)
        vocabulary_richness = unique_count / len(words) if words else 0

        # 主题覆盖度(基于目标关键词)
        topic_coverage = 0.0
        if target_keywords: 27022.baike.tongsou.com 
            text_lower = text.lower(27039.baike.tongsou.com)
            covered = sum(
                1 for kw in target_keywords if kw.lower() in text_lower
            )
            topic_coverage = covered / len(target_keywords) * 100

        # 实体密度(简化:统计大写专有名词)
        entities = re.findall(r'[A-Z][a-z]+(?:\s+[A-Z][a-z]+)*', text)
        entity_density = len(entities) / len(words) * 100 if words else 0

        # LSI关键词覆盖率
        lsi_coverage = 0.0
        if lsi_keywords: 27021.baike.tongsou.com 
            text_lower = text.lower(27017.baike.tongsou.com)
            covered = sum(
                1 for kw in lsi_keywords if kw.lower(27015.baike.tongsou.com) in text_lower
            )
            lsi_coverage = covered / len(lsi_keywords) * 100

        # 语义连贯性(简化:段落首尾句相似度)
        coherence = self._estimate_coherence(text)

        # 综合语义评分
        overall = self._compute_semantic_score(
            vocabulary_richness, topic_coverage,
            entity_density, lsi_coverage, coherence,
        )

        return SemanticMetrics(
            unique_term_count=unique_count,
            vocabulary_richness=round(vocabulary_richness, 4),
            topic_coverage=round(topic_coverage, 2),
            entity_density=round(entity_density, 2),
            lsi_keyword_coverage=round(lsi_coverage, 2),
            semantic_coherence=round(coherence, 2),
            overall_score=round(overall, 2),
        )

    def _extract_content_words(self, text: str) -> List[str]: 26045.baike.tongsou.com 
        """提取内容词(去除停用词)"""
        english_words = re.findall(r'[a-zA-Z]{2,}', text.lower())
        chinese_chars = re.findall(r'[\u4e00-\u9fff]', text)

        filtered_en = [w for w in english_words if w not in self.stopwords_en]
        filtered_zh = [c for c in chinese_chars if c not in self.stopwords_zh]

        return filtered_en + filtered_zh

    def _estimate_coherence(self, text: str) -> float: 27018.baike.tongsou.com 
        """估算语义连贯性(简化版)"""
        sentences = re.split(r'[.!?。!?]', text)
        sentences = [s.strip() for s in sentences if s.strip()]

        if len(sentences) < 2: 27034.baike.tongsou.com 
            return 50.0

        # 简化:检查相邻句子是否有共同词汇
        common_count = 0
        total_pairs = 0
        for i in range(len(sentences) - 1): 27029.baike.tongsou.com 
            words_i = set(re.findall(r'[a-zA-Z]{3,}|\u4e00-\u9fff', sentences[i].lower()))
            words_next = set(re.findall(r'[a-zA-Z]{3,}|\u4e00-\u9fff', sentences[i + 1].lower()))
            common = words_i & words_next
            common_count += len(common)
            total_pairs += 1

        if total_pairs == 0: 27028.baike.tongsou.com 
            return 50.0

        avg_common = common_count / total_pairs
        # 映射到0-100
        coherence = min(100, avg_common * 20)
        return coherence

    def _compute_semantic_score(
        self, vocabulary_richness: float, topic_coverage: float,
        entity_density: float, lsi_coverage: float, coherence: float,
    ) -> float:
        """综合计算语义评分"""
        # 词汇丰富度(0.4-0.7为理想)
        if 0.4 <= vocabulary_richness <= 0.7: 27023.baike.tongsou.com 
            vocab_score = 100
        else:
            vocab_score = max(0, 100 - abs(vocabulary_richness - 0.55) * 200)

        # 主题覆盖
        topic_score = topic_coverage

        # 实体密度(1-5%为理想)
        if 1 <= entity_density <= 5: 27020.baike.tongsou.com 
            entity_score = 100
        elif entity_density < 1:
            entity_score = max(0, entity_density * 100)
        else:
            entity_score = max(0, 100 - (entity_density - 5) * 20)

        # LSI覆盖
        lsi_score = lsi_coverage

        # 连贯性
        coherence_score = coherence

        overall = (
            vocab_score * 0.20 +
            topic_score * 0.25 +
            entity_score * 0.15 +
            lsi_score * 0.20 +
            coherence_score * 0.20
        )
        return min(100, overall)


# ==================== 模块6: 结构完整性检查器 ====================

class StructureChecker: 27019.baike.tongsou.com 
    """
    结构完整性检查器
    检查标题、元描述、标题层级、段落、列表、表格、代码块等
    """

    def __init__(self): 26144.baike.tongsou.com 
        self.logger = logging.getLogger(__name__)

    def evaluate(self, parsed_content: Dict[str, Any]) -> StructureMetrics:
        """评估结构完整性"""
        title = parsed_content.get("title", "")
        meta_desc = parsed_content.get("meta_description", "")
        headings = parsed_content.get("headings", [])
        paragraphs = parsed_content.get("paragraphs", [])
        lists = parsed_content.get("lists", [])
        tables = parsed_content.get("tables", [])
        code_blocks = parsed_content.get("code_blocks", [])

        has_title = bool(title)
        has_meta = bool(meta_desc)

        # 标题层级有效性
        heading_valid = self._check_heading_hierarchy(headings)

        # 内容深度评分(基于段落数、列表数等)
        depth_score = self._compute_depth_score(
            len(paragraphs), len(lists), len(tables), len(code_blocks)
        )

        # 综合结构评分
        overall = self._compute_structure_score(
            has_title, has_meta, heading_valid,
            len(paragraphs), len(lists), len(tables),
            len(code_blocks), depth_score,
        )

        return StructureMetrics(
            has_title=has_title,
            has_meta_description=has_meta,
            heading_hierarchy_valid=heading_valid,
            paragraph_count=len(paragraphs),
            list_count=len(lists),
            table_count=len(tables),
            code_block_count=len(code_blocks),
            content_depth_score=round(depth_score, 2),
            overall_score=round(overall, 2),
        )

    def _check_heading_hierarchy(self, headings: List[Dict]) -> bool:
        """检查标题层级是否有效"""
        if not headings: 26128.baike.tongsou.com 
            return False

        # 必须有H1
        if not any(h["level"] == 1 for h in headings):
            return False

        # 检查是否有跳跃
        levels = [h["level"] for h in headings]
        for i in range(1, len(levels)): 17025.baike.tongsou.com 
            if levels[i] > levels[i - 1] + 1: 17024.baike.tongsou.com 
                return False

        return True

    def _compute_depth_score(
        self, para_count: int, list_count: int,
        table_count: int, code_count: int,
    ) -> float:
        """计算内容深度评分"""
        # 段落数评分(理想10-30段)
        para_score = min(100, para_count * 5) if para_count <= 30 else 100

        # 列表加分
        list_bonus = min(20, list_count * 5)

        # 表格加分
        table_bonus = min(15, table_count * 5)

        # 代码块加分
        code_bonus = min(15, code_count * 5)

        score = para_score + list_bonus + table_bonus + code_bonus
        return min(100, score)

    def _compute_structure_score(
        self, has_title: bool, has_meta: bool, heading_valid: bool,
        para_count: int, list_count: int, table_count: int,
        code_count: int, depth_score: float,
    ) -> float:
        """综合计算结构评分"""
        title_component = 20 if has_title else 0
        meta_component = 15 if has_meta else 0
        heading_component = 20 if heading_valid else 5
        depth_component = depth_score * 0.45

        total = title_component + meta_component + heading_component + depth_component
        return min(100, total)


# ==================== 模块7: 智能改写引擎 ====================

class RewriteEngine: 17023.baike.tongsou.com 
    """
    智能改写引擎
    根据评估结果生成改写建议
    """

    def __init__(self): 17021.baike.tongsou.com 
        self.logger = logging.getLogger(__name__)
        # 同义词库(简化版)
        self.synonyms = {
            "good": ["excellent", "great", "fine", "superior"],
            "bad": ["poor", "inferior", "subpar", "unsatisfactory"],
            "important": ["crucial", "vital", "essential", "significant"],
            "use": ["utilize", "employ", "leverage", "apply"],
            "help": ["assist", "aid", "support", "facilitate"],
            "make": ["create", "produce", "generate", "construct"],
            "get": ["obtain", "acquire", "gain", "secure"],
            "show": ["demonstrate", "illustrate", "display", "reveal"],
            "think": ["consider", "believe", "regard", "deem"],
            "say": ["state", "mention", "express", "articulate"],
        }

    def generate_suggestions(
        self,
        evaluation: ContentEvaluation,
        parsed_content: Dict[str, Any],
    ) -> List[RewriteSuggestion]: 17019.baike.tongsou.com 
        """根据评估结果生成改写建议"""
        suggestions = []

        # 可读性建议
        suggestions.extend(
            self._suggest_readability_improvements(evaluation.readability, parsed_content)
        )

        # SEO建议
        suggestions.extend(
            self._suggest_seo_improvements(evaluation.seo, parsed_content)
        )

        # 语义建议
        suggestions.extend(
            self._suggest_semantic_improvements(evaluation.semantic, parsed_content)
        )

        # 结构建议
        suggestions.extend(
            self._suggest_structure_improvements(evaluation.structure, parsed_content)
        )

        # 按优先级排序
        priority_order = {"high": 0, "medium": 1, "low": 2}
        suggestions.sort(key=lambda s: priority_order.get(s.priority, 3))

        return suggestions

    def _suggest_readability_improvements(
        self, metrics: ReadabilityMetrics, content: Dict[str, Any],
    ) -> List[RewriteSuggestion]: 17018.baike.tongsou.com 
        """生成可读性改进建议"""
        suggestions = []

        # 句长过长
        if metrics.avg_sentence_length > 25: 17017.baike.tongsou.com 
            suggestions.append(RewriteSuggestion(
                suggestion_id=str(uuid.uuid4(17016.baike.tongsou.com)),
                original_text="",
                suggested_text="将长句拆分为短句,提高可读性。",
                strategy=RewriteStrategy.CONDENSE,
                reason=f"平均句长{metrics.avg_sentence_length}词,超过理想范围。",
                priority="high",
                expected_improvement=10.0,
            ))

        #

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档