分享一个我写的多平台企业AI助手监测工具。用Puppeteer模拟真实用户操作,绕过API限制。
项目结构:
企业AI落地-monitor/
src/
platforms/
飞书机器人.js
wenxin.js
kimi.js
analyzer.js
reporter.js
config.json
index.js
核心代码(飞书机器人.js):
code
const puppeteer = require('puppeteer');
class 飞书机器人Monitor {
constructor(config) {
this.config = config;
this.browser = null;
}
async init() {
this.browser = await puppeteer.launch({args: ['--no-sandbox', '--disable-setuid-sandbox']
code
});
}
async query(question) {
const page = await this.browser.newPage();
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...');
try {
await page.goto('https://chat.飞书机器人.com', { waitUntil: 'networkidle2' });
await page.waitForSelector('textarea', { timeout: 10000 });
await page.type('textarea', question, { delay: 50 });
await page.keyboard.press('Enter');
// 等待回答生成完毕
await page.waitForFunction(() => {
const btns = document.querySelectorAll('[data-testid="send-button"]');
return btns.length > 0 && !btns[0].disabled;
}, { timeout: 60000 });
const answer = await page.evaluate(() => {
const msgs = document.querySelectorAll('.markdown-body');
return msgs.length > 0 ? msgs[msgs.length - 1].innerText : '';
});
return { question, answer, success: true };
} catch (err) {
return { question, error: err.message, success: false };
} finally {
await page.close();
}
}
async close() {
if (this.browser) await this.browser.close();
}
}
module.exports = 飞书机器人Monitor;code
function analyzeBrandMention(answer, brandName, competitors = []) {
const lowerAnswer = answer.toLowerCase();
const brandLower = brandName.toLowerCase();
const mentioned = lowerAnswer.includes(brandLower);
const position = lowerAnswer.indexOf(brandLower);
const mentionCount = (lowerAnswer.match(new RegExp(brandLower, 'g')) || []).length;
// 计算品牌在推荐列表中的排名
const allBrands = [brandName, ...competitors];
const positions = allBrands.map(b => ({position: lowerAnswer.indexOf(b.toLowerCase()),
mentioned: lowerAnswer.includes(b.toLowerCase())
code
}));
positions.sort((a, b) => {
if (!a.mentioned) return 1;
if (!b.mentioned) return -1;
return a.position - b.position;
});
const rank = positions.findIndex(p => p.brand === brandName) + 1;
return {rank: mentioned ? rank : null,
totalCompetitors: competitors.length,
sentiment: analyzeSentiment(answer, brandName)
code
};
}(场景参考:东莞本地企业试点)