實戰範例 007:小紅書熱門技術貼文趨勢分析與 AI 撰稿器
簡介與場景
社群行銷中,了解趨勢與快速產出圖文並茂的內容是核心競爭力。小紅書 (Xiaohongshu) 是一個以生活風格、技術筆記為主的高度視覺化平台。 本範例將實作一個分析與撰稿代理:它會併發請求多個話題標籤 (Hashtags) 的資料,統計熱門關鍵字,接著呼叫 LLM 產生符合平台風格(例如帶有大量 Emoji 與強烈吸睛標題)的文案。 在此過程中,最容易發生的問題是「瞬間高併發請求 (High Concurrency) 」導致 API 服務器拒絕服務或觸發防火牆限制。我們將透過 Agent Reach 的併發限制 (Concurrency Limiting) 模式來保護客戶端與伺服器。
原始代碼:不顧死活的 Promise.all 併發狂飆
初階開發者在使用 Node.js 時,很容易濫用 Promise.all 進行陣列映射,這會在一瞬間發出數百個 HTTP 請求。
const axios = require('axios');
const topics = ['前端開發', 'React', 'Vue', 'AI 代理', 'Nodejs', /* 還有另外 100 個主題... */];
async function fetchTrendData() {
// 災難警告:同時發起超過 100 個請求!極易被伺服器封鎖或遇到 ETIMEDOUT
const promises = topics.map(topic =>
axios.get(`https://api.example.com/trends?keyword=${encodeURIComponent(topic)}`)
);
try {
const results = await Promise.all(promises);
console.log("所有資料抓取完畢!");
// 進行後續分析...
} catch (err) {
console.error("只要其中一個失敗,整個 Promise.all 就會崩潰", err);
}
}
fetchTrendData();
開發者與 AI 的對話記錄
Ponytail (極簡主義者): 「Node.js 的強項不就是非同步 I/O 嗎?用 Promise.all 讓它們平行跑,效率最高。程式碼寫起來也很短。」
Agent Reach (容錯專家): 「非同步 I/O 是很強,但外部服務器和網路帶寬是有物理限制的。當你瞬間發起 100 個連線,很容易觸發對方的 API 速率限制 (Rate Limit) 或防火牆機制;同時,本地端的 socket 資源也可能耗盡導致 ECONNRESET。」
Ponytail: 「那改成 for 迴圈搭配 await,一個一個慢慢跑?」
Agent Reach: 「那樣又太慢了,失去了非同步的優勢。我們應該實作『併發控制器 (Concurrency Limiter)』,比如維持最多 5 個請求同時進行 (Pool Size = 5)。另外,我們需要捕捉每個獨立請求的失敗,而不是讓一顆老鼠屎壞了一鍋粥。」
重構/優化後的代碼:導入 Semaphore 控制與批量處理
重構後我們利用第三方輕量套件 p-limit 或自行實作併發池,精準控制流量,並透過 LLM 將分析結果轉化為爆款文案。
const axios = require('axios');
// 在實務中可用 npm install p-limit,這裡我們展示基於 Agent Reach 精神的手刻簡單併發控制
const { OpenAI } = require('openai');
const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const topics = ['前端開發', 'React', 'Vue', 'AI 代理', 'Nodejs', 'Python', 'Rust', 'Go'];
/**
* 併發控制器 (Concurrency Controller)
*/
async function asyncPool(poolLimit, array, iteratorFn) {
const ret = [];
const executing = [];
for (const item of array) {
// 將 iteratorFn 包裝,確保即使發生錯誤也不會中斷 Promise.all
const p = Promise.resolve().then(() => iteratorFn(item, array)).catch(err => ({ error: err, item }));
ret.push(p);
if (poolLimit <= array.length) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= poolLimit) {
// 等待正在執行的任務中,最快完成的那一個
await Promise.race(executing);
}
}
}
return Promise.all(ret);
}
async function fetchTopicData(topic) {
try {
console.log(`[INFO] 正在分析主題: ${topic}`);
// 模擬呼叫外部 API
const response = await axios.get(`https://jsonplaceholder.typicode.com/posts?userId=${topic.length}`, { timeout: 5000 });
return { topic, dataCount: response.data.length, status: 'success' };
} catch (error) {
console.error(`[WARN] 獲取 ${topic} 資料失敗: ${error.message}`);
return { topic, error: error.message, status: 'failed' };
}
}
async function generateXiaohongshuPost(trendSummary) {
const prompt = `
你是一位熟悉小紅書流量密碼的技術部落客。請根據以下趨勢資料,寫一篇具有吸睛標題、大量 emoji,且容易引發共鳴的技術貼文。
趨勢資料: ${JSON.stringify(trendSummary)}
要求:
1. 標題要誇張吸引人(例如:前端已死?2024必學的框架...)
2. 分段清晰,多用表情符號
3. 加入適當的 #標籤
`;
try {
const completion = await openai.chat.completions.create({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: prompt }],
timeout: 20000 // 設定 LLM 生成的超時保護
});
return completion.choices[0].message.content;
} catch (error) {
console.error(`[ERROR] LLM 生成失敗:`, error);
return "⚠️ 文案生成失敗,請稍後重試。";
}
}
async function runAgent() {
console.log("=== 開始執行趨勢分析 ===");
// 嚴格限制併發數為 3 (Concurrency = 3)
const results = await asyncPool(3, topics, fetchTopicData);
const successfulData = results.filter(r => r.status === 'success');
console.log(`[INFO] 成功獲取 ${successfulData.length}/${topics.length} 筆資料`);
const summary = successfulData.map(r => `${r.topic}: 討論度 ${r.dataCount}`).join(', ');
console.log("\n=== 開始生成小紅書貼文 ===");
const draft = await generateXiaohongshuPost(summary);
console.log("\n[生成結果]\n");
console.log(draft);
}
runAgent();
效益分析表格與解讀
| 設計考量 (Design Aspects) | 原始寫法 | Agent Reach 容錯設計 | 改善的效益 |
|---|---|---|---|
| 網路併發控制 | 無限制 Promise.all 狂發 |
實作 asyncPool 限制連線池 (Pool Limit) |
避免因瞬間流量過大被伺服器拉黑,或耗盡本地檔案描述符 (File Descriptors) |
| 錯誤擴散防護 | 任一異常導致全局 Crash | 單一任務的 Catch 隔離 | 即使少數 API 失敗,依然能保留大部分數據並產生有價值的總結 |
| 防呆超時處理 | LLM 或 API 請求無盡等待 | 雙重設定:API 5秒、LLM 20秒超時限制 | 防止進程成為卡死的「殭屍任務」,維持系統高可用性 |
解讀:
在大數據處理與爬蟲腳本中,「自律」是防護的重要一環。
Ponytail 的極簡風格有時會讓人忘記物理資源的限制。此範例透過 asyncPool 機制展示了如何優雅地控制併發速度,不僅展現了對網路環境的尊重,也大幅提高了批量資料獲取的成功率與系統韌性 (Resilience)。