You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于TypeScript开发SEO审计工具:孤立页面检测、类PageRank链接权益计算及主题关联链接建议实现需求

实现SEO审计工具的核心功能方案

针对你开发SEO审计工具时遇到的三个核心需求,以及现有手动方案的痛点,我整理了一套可落地的实现思路,结合你期望的API设计来拆解:

一、先解决URL标准化,构建靠谱的有向链接图

URL标准化是所有链接分析的基础,之前的匹配遗漏问题大多源于此。先写一个工具函数统一处理URL:

function normalizeUrl(url) {
  const urlObj = new URL(url);
  // 统一去掉末尾斜杠
  urlObj.pathname = urlObj.pathname.replace(/\/$/, '');
  // 忽略大小写、统一协议(按需调整)
  return urlObj.href.toLowerCase();
}

接着实现buildLinkGraph,帮你构建包含入站/出站计数的有向图——这是后续所有分析的核心载体:

function buildLinkGraph(pages) {
  const nodes = new Map();
  const edges = new Map();

  // 先初始化所有页面节点
  pages.forEach(page => {
    const normalizedUrl = normalizeUrl(page.url);
    nodes.set(normalizedUrl, {
      url: page.url,
      normalizedUrl,
      inboundCount: 0,
      outboundCount: page.links.length,
      outboundLinks: page.links.map(link => normalizeUrl(link))
    });
  });

  // 遍历统计每个页面的入站链接数
  nodes.forEach(node => {
    node.outboundLinks.forEach(targetUrl => {
      if (nodes.has(targetUrl)) {
        nodes.get(targetUrl).inboundCount += 1;
        // 存储边信息,用于后续权益计算
        if (!edges.has(node.normalizedUrl)) edges.set(node.normalizedUrl, []);
        edges.get(node.normalizedUrl).push(targetUrl);
      }
    });
  });

  return { nodes, edges };
}

这个图结构直接解决了你之前无法统计入站/出站链接的问题,而且性能比手动遍历高得多。

二、高效检测孤立页面

基于上面的链接图,findOrphanPages可以做到O(n)时间复杂度,再也不用纠结URL匹配的问题:

function findOrphanPages(graph) {
  return Array.from(graph.nodes.values())
    .filter(node => node.inboundCount === 0)
    .map(({ url, outboundCount }) => ({ url, outboundCount }));
}

只要页面的入站计数为0,就是爬虫无法发现的孤立页面,逻辑清晰又准确。

三、计算类PageRank的链接权益分数

PageRank的核心是“链接投票”,这里实现一个简化版,支持阻尼因子和迭代次数配置:

function analyzeLinkEquity(graph, { damping = 0.85, iterations = 20 }) {
  const nodeList = Array.from(graph.nodes.keys());
  const totalNodes = nodeList.length;
  let scores = new Map();

  // 初始化分数:每个页面初始权重均等
  nodeList.forEach(url => scores.set(url, 1 / totalNodes));

  for (let i = 0; i < iterations; i++) {
    const newScores = new Map();
    const randomSurferScore = (1 - damping) / totalNodes;

    nodeList.forEach(nodeUrl => {
      let score = randomSurferScore;
      const edges = graph.edges.get(nodeUrl) || [];

      if (edges.length > 0) {
        // 有出站链接的页面,按比例传递权重
        const share = damping * scores.get(nodeUrl) / edges.length;
        edges.forEach(targetUrl => {
          newScores.set(targetUrl, (newScores.get(targetUrl) || 0) + share);
        });
      } else {
        // 无出站链接的页面,权重均匀分给所有页面
        nodeList.forEach(targetUrl => {
          newScores.set(targetUrl, (newScores.get(targetUrl) || 0) + damping * scores.get(nodeUrl) / totalNodes);
        });
      }
    });

    scores = newScores;
  }

  // 转换为你期望的输出格式,按分数从高到低排序
  return Array.from(scores.entries())
    .map(([normalizedUrl, score]) => ({
      url: graph.nodes.get(normalizedUrl).url,
      score: parseFloat(score.toFixed(2)),
      inboundCount: graph.nodes.get(normalizedUrl).inboundCount
    }))
    .sort((a, b) => b.score - a.score);
}

这个函数会输出每个页面的权威度分数,帮你快速定位全站最有价值的页面。

四、基于主题重叠的链接建议

要实现这个功能,核心是计算页面间的主题相似度。这里给你一个简化版的实现,你可以后续结合专业NLP库优化:

// 辅助函数:提取页面关键词(简单版,实际可替换为TF-IDF等算法)
function extractKeywords({ title, content }) {
  const text = `${title} ${content}`.toLowerCase();
  // 基础停用词表,可按需扩展
  const stopWords = ['the', 'and', 'of', 'a', 'to', 'in', 'is'];
  return text.match(/\w+/g)
    ?.filter(word => !stopWords.includes(word))
    .reduce((acc, word) => {
      acc[word] = (acc[word] || 0) + 1;
      return acc;
    }, {}) || {};
}

// 计算两个关键词集合的余弦相似度
function calculateSimilarity(keywordsA, keywordsB) {
  const allWords = new Set([...Object.keys(keywordsA), ...Object.keys(keywordsB)]);
  let dotProduct = 0;
  let normA = 0;
  let normB = 0;

  allWords.forEach(word => {
    const a = keywordsA[word] || 0;
    const b = keywordsB[word] || 0;
    dotProduct += a * b;
    normA += a * a;
    normB += b * b;
  });

  if (normA === 0 || normB === 0) return 0;
  return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}

function suggestLinks(pages, { minRelevance = 0.15, maxSuggestions = 3 }) {
  // 先给每个页面提取关键词
  const pageData = pages.map(page => ({
    ...page,
    keywords: extractKeywords(page)
  }));

  const suggestions = [];

  // 两两对比页面,计算相似度
  for (let i = 0; i < pageData.length; i++) {
    const sourcePage = pageData[i];
    for (let j = i + 1; j < pageData.length; j++) {
      const targetPage = pageData[j];
      const similarity = calculateSimilarity(sourcePage.keywords, targetPage.keywords);

      if (similarity >= minRelevance) {
        suggestions.push({
          sourceUrl: sourcePage.url,
          targetUrl: targetPage.url,
          relevance: parseFloat(similarity.toFixed(3))
        });
      }
    }
  }

  // 按相关性排序,取前N个建议
  return suggestions.sort((a, b) => b.relevance - a.relevance).slice(0, maxSuggestions);
}

这个方案会根据页面标题、内容的主题重叠度,生成上下文相关的链接建议,帮你优化网站内部链接结构。


内容的提问来源于stack exchange,提问作者Al Amin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 06:39:39