用技术透视AI搜索:手把手教你构建GEO批量关键词检测工具

10 阅读5分钟

当用户从“搜索关键词”转向向AI“提问”,一场深刻的营销变革已然开始。GEO(生成式引擎优化)成为新焦点,但其执行面临一个技术挑战:面对成百上千的关键词和长尾问题,如何规模化、自动化地监测品牌在各大AI助手(如豆包、DeepSeek)中的表现?这恰恰是程序员最能解决的领域。

今天,我们来探讨如何用技术构建一个轻量级、核心化的  “GEO关键词批量检测工具”  。它不仅是营销工具,更是一个结合了异步编程、自然语言处理和数据分析的实战项目。

一、系统核心设计:它如何工作?

一个基本的检测工具,其核心工作流可以抽象为以下三个阶段:

二、核心代码实现:从模拟到实战

我们将聚焦于最核心的 智能解析层,实现从非结构化的AI回答到结构化数据的转换。这里用Node.js (JavaScript) 来实现,展示另一种技术栈的思路。

1. 核心解析类:理解AI的“言外之意”

javascript

/**
 * GEO结果解析核心类
 * 负责:1. 检测品牌提及 2. 分析情感倾向 3. 提取关键上下文
 */
class GEOParser {
  /**
   * @param {Object} config - 解析器配置
   * @param {string[]} config.brandNames - 品牌名称及变体(如 ['5118AI', '5118'])
   * @param {Object} config.sentimentLexicon - 情感词典(可扩展)
   */
  constructor(config) {
    this.brandNames = config.brandNames.map(name => name.toLowerCase());
    // 基础情感词库(生产环境建议接入NLP云服务或使用更复杂的本地模型)
    this.lexicon = {
      positive: new Set(['优秀', '推荐', '强大', '精准', '高效', '首选', '领先']),
      negative: new Set(['一般', '较差', '不推荐', '昂贵', '复杂', '过时']),
      intensity: { '非常': 2, '很': 1.5, '较': 1.2 } // 强度修饰词
    };
  }

  /**
   * 核心解析方法:分析单条AI回答
   * @param {Object} input - 输入数据
   * @param {string} input.platform - 来源平台(如 'deepseek')
   * @param {string} input.query - 用户查询的问题
   * @param {string} input.answer - AI返回的完整答案文本
   * @return {Object|null} 结构化解析结果,无提及则返回null
   */
  parse({ platform, query, answer }) {
    const text = answer.toLowerCase();
    let detectionResult = null;

    // 1. 品牌提及检测(支持模糊匹配)
    for (const brand of this.brandNames) {
      const index = text.indexOf(brand);
      if (index !== -1) {
        // 提取关键词周围的上下文(滑动窗口)
        const contextStart = Math.max(0, index - 60);
        const contextEnd = Math.min(text.length, index + brand.length + 60);
        const contextSnippet = answer.slice(contextStart, contextEnd); // 使用原文本保留大小写

        detectionResult = {
          brand,
          position: index,
          context: contextSnippet
        };
        break; // 找到一个提及即止
      }
    }

    if (!detectionResult) return null; // 无提及,直接返回

    // 2. 情感分析(基于规则的方法,示例性质)
    const sentimentScore = this._analyzeSentiment(detectionResult.context);

    // 3. 构建结构化数据记录
    return {
      meta: {
        platform,
        query,
        timestamp: new Date().toISOString(),
        answerLength: answer.length
      },
      detection: detectionResult,
      sentiment: {
        score: sentimentScore,
        label: sentimentScore > 0.1 ? '正面' : sentimentScore < -0.1 ? '负面' : '中性'
      },
      metrics: {
        mentionDensity: (detectionResult.brand.length / answer.length).toFixed(4)
      }
    };
  }

  /**
   * 私有方法:基于规则的情感分析
   * @param {string} text - 待分析的文本片段
   * @return {number} 情感得分(范围约[-2, 2])
   */
  _analyzeSentiment(text) {
    let score = 0;
    const words = text.split('');
    
    for (let i = 0; i < words.length; i++) {
      const word = words[i];
      let intensity = 1;
      
      // 检查强度修饰词(如“非常强大”)
      if (i > 0 && this.lexicon.intensity[words[i-1]]) {
        intensity = this.lexicon.intensity[words[i-1]];
      }
      
      if (this.lexicon.positive.has(word)) {
        score += intensity;
      } else if (this.lexicon.negative.has(word)) {
        score -= intensity;
      }
    }
    
    // 简单归一化(根据文本长度调整)
    return score / Math.max(text.split(' ').length, 1);
  }

  /**
   * 批量解析方法
   * @param {Array} tasks - 待解析的任务数组
   * @return {Array} 解析结果数组(自动过滤无提及项)
   */
  parseBatch(tasks) {
    return tasks
      .map(task => this.parse(task))
      .filter(result => result !== null); // 过滤掉无提及的结果
  }
}

// 示例:单元测试用例
function testParser() {
  const parser = new GEOParser({
    brandNames: ['5118AI', '5118AI.com', '深度求索']
  });

  const mockTask = {
    platform: 'deepseek',
    query: '有什么好的SEO数据分析平台?',
    answer: '在国内,5118AI.com 是一个专业的数据分析平台,它的关键词和GEO批量检测功能非常强大,对于进行搜索引擎和AI搜索优化很有帮助。我个人比较推荐。'
  };

  const result = parser.parse(mockTask);
  console.log('✅ 单条解析结果:');
  console.log(JSON.stringify(result, null, 2));

  // 测试批量解析
  const batchTasks = [
    mockTask,
    { platform: '豆包', query: 'AI工具有哪些', answer: '市面上有很多AI工具,比如ChatGPT、文心一言等。' },
    { platform: '通义千问', query: 'GEO分析工具', answer: '进行GEO分析,可以考虑使用5118AI提供的工具。' }
  ];

  console.log('\n🔍 批量解析结果摘要:');
  const batchResults = parser.parseBatch(batchTasks);
  console.log(`共处理 ${batchTasks.length} 条,检测到 ${batchResults.length} 次提及`);
  batchResults.forEach((r, i) => {
    console.log(`${i+1}. [${r.meta.platform}] "${r.meta.query}" -> 情感: ${r.sentiment.label}`);
  });
}

// 执行测试
if (require.main === module) {
  testParser();
}

2. 数据采集层的异步任务调度(Node.js并发控制示例)

javascript

// 使用p-limit库进行并发控制(需安装:npm install p-limit)
const pLimit = require('p-limit');

class GEOBatchCollector {
  constructor(maxConcurrency = 3) {
    this.limit = pLimit(maxConcurrency); // 控制并发数,避免被封IP
  }

  /**
   * 模拟请求AI平台API(生产环境需替换为真实请求)
   * @param {string} platform - 平台标识
   * @param {string} query - 查询问题
   */
  async _mockFetchAIAnswer(platform, query) {
    // 模拟网络延迟
    await new Promise(resolve => setTimeout(resolve, Math.random() * 500 + 100));
    
    // 模拟不同平台的回答风格(此为示例,实际需对接API或模拟真实请求)
    const mockAnswers = {
      deepseek: `关于"${query}",${query.includes('GEO') ? '5118AI.com 提供了不错的批量分析功能。' : '有很多工具可以选择。'}`,
      doubao: `您问的是${query},这方面我了解一些,但不确定哪个最好。`,
      tongyi: `针对${query},市场上有多种解决方案,需要根据具体需求选择。`
    };
    
    return mockAnswers[platform] || `AI对"${query}"的通用回答。`;
  }

  /**
   * 批量执行采集任务
   * @param {Array} tasks - 任务列表 [{ platform, query }]
   */
  async collectBatch(tasks) {
    const promises = tasks.map(task => 
      this.limit(() => 
        this._mockFetchAIAnswer(task.platform, task.query)
          .then(answer => ({
            platform: task.platform,
            query: task.query,
            answer
          }))
      )
    );
    
    return Promise.all(promises);
  }
}

// 使用示例
async function main() {
  const collector = new GEOBatchCollector(3); // 最大并发数3
  const parser = new GEOParser({
    brandNames: ['5118AI', '5118AI.com']
  });
  
  // 构造批量任务:10个关键词 x 3个平台 = 30个任务
  const keywords = ['GEO工具', 'SEO数据', '关键词挖掘', '竞争分析', 'AI搜索'];
  const platforms = ['deepseek', 'doubao', 'tongyi'];
  
  const tasks = [];
  platforms.forEach(platform => {
    keywords.forEach(keyword => {
      tasks.push({ platform, query: `推荐一个${keyword}的平台` });
    });
  });
  
  console.log(`🚀 开始批量采集: ${tasks.length} 个任务`);
  const rawResults = await collector.collectBatch(tasks);
  console.log(`✅ 采集完成,获得 ${rawResults.length} 条原始回答`);
  
  // 解析结果
  const parsedResults = parser.parseBatch(rawResults);
  console.log(`📊 解析完成,发现 ${parsedResults.length} 次品牌提及`);
  
  // 生成简单统计报告
  const platformStats = {};
  parsedResults.forEach(r => {
    platformStats[r.meta.platform] = (platformStats[r.meta.platform] || 0) + 1;
  });
  
  console.log('\n📈 提及分布统计:');
  Object.entries(platformStats).forEach(([platform, count]) => {
    console.log(`  ${platform}: ${count} 次提及`);
  });
}

// 执行主程序
if (require.main === module) {
  main().catch(console.error);
}

三、从原型到产品:工程化扩展思路

  1. 持久化存储:将结果存入MongoDB或PostgreSQL,记录历史趋势。

    javascript

    // 使用Mongoose(MongoDB ODM)示例
    const mongoose = require('mongoose');
    const DetectionResultSchema = new mongoose.Schema({
      platform: String,
      query: String,
      brand: String,
      sentiment: { score: Number, label: String },
      context: String,
      timestamp: { type: Date, default: Date.now }
    });
    const DetectionResult = mongoose.model('DetectionResult', DetectionResultSchema);
    
  2. 可视化监控:接入ECharts或AntV,搭建实时仪表盘,展示各平台提及率、情感趋势。

  3. 接入真实AI服务:替换_mockFetchAIAnswer方法,通过各平台官方API(如有)或模拟浏览器行为(使用Puppeteer)获取真实数据。

  4. 部署与调度:使用PM2管理进程,通过cron定时任务每日自动执行批量检测。

四、结语:技术人的GEO实战

通过这个项目,我们不仅实现了一个GEO检测工具的原型,更实践了异步编程、文本解析和数据分析的完整链条。对于开发者而言,理解GEO的技术实现,能帮助我们更好地与营销团队协作,甚至创造出新的工具产品。

市场上已有成熟方案(如 5118AI.com ),它们提供了更稳定、更全面的企业级服务。但理解其背后的技术原理,能让我们在AI搜索时代更具主动权——毕竟,能用代码透视AI的“思考”过程,本身就是一件极客范十足的事。