回到頂部
3 秒掃完 195 篇中文文章的 SEO 體質:seo-check.mjs 怎麼寫 — 封面

3 秒掃完 195 篇中文文章的 SEO 體質:seo-check.mjs 怎麼寫

中文沒有空格、沒有現成 tokenizer,要怎麼用 100 行 Node 自動檢查全站文章的關鍵字密度、meta 長度、SERP 友善度?這是我的解法。

為什麼會做這個

我幫網站做 SEO 體檢時,發現一個尷尬的事:我的文章標題寫得太「文案」了

例如這篇:

「空拍機與病蟲害視覺辨識:你的 24 小時免費植物醫師」

讀者覺得有趣,但 Google 抓不到核心關鍵字「農業 AI」「植物醫生」。搜「農業 AI 教學」找不到我——白寫。

問題是我有 195 篇文章,人工檢查不可能。我需要一個工具:

  • 掃過全站
  • 從每篇標題抽出主關鍵字
  • 檢查這個關鍵字有沒有出現在 description、前 300 字
  • 標記出有問題的文章

為什麼不用現成工具?

中文 SEO 的悲慘現實:

工具中文支援
Yoast SEO❌ 假裝有
SEMrush⚠️ 簡體尚可,繁體很差
Ahrefs⚠️ 同上
Screaming Frog❌ 不檢查內容質量

而且這些工具都假設你站在 WordPress 上。我用 Astro,所有內容是 .md,要套這些工具還得先架一個 staging server。寫 100 行 Node 比較快——這也是 AI 輔助寫程式 最適合的場景:小規模、一次性、零依賴。

中文最大的坑:沒有空格

英文 SEO 工具能做的事,大半建立在「文字用空格切詞」這個假設上。中文沒有空格——這是中文 NLP 第一道難題。

正規解法是用 jieba(結巴分詞),但這需要安裝 Python、載 200MB 詞典、跑模型。對一個 build-time 腳本太重了

我的啟發式做法:取標題前 2 個 CJK 字符當主關鍵字

function extractPrimaryKeyword(title) {
  let head = title.split(/[::((]/)[0];      // 1. 截到第一個冒號/括號之前
  head = head.replace(/AI/gi, '')              // 2. 去掉「AI」這個無意義詞
             .replace(/[「」『』,,。!!??\s+]/g, '');
  while (head.length && STOP.has(head[0])) {   // 3. 去掉開頭的停用字
    head = head.slice(1);
  }
  const m = head.match(/[\u4e00-\u9fa5]{2}/);  // 4. 抓第一段連續 2 個 CJK 字
  return m ? m[0] : head.slice(0, 2);
}

例子:

  • 會計的 AI 實戰指南」→ 會計
  • 製造業 AI 工廠」→ 製造
  • 空拍機與病蟲害視覺辨識」→ 空拍(這個有點偏,但比拿整段更實用)

這個 heuristic 不完美,但目的不是學術研究,是「對啦你這篇 description 沒寫核心關鍵字」這種粗暴提醒。夠用就好

評分邏輯

function score(article) {
  const kw = extractPrimaryKeyword(article.title);
  const head = article.body.slice(0, 300);
  
  const issues = [];
  if (!article.description.includes(kw))
    issues.push(`description 缺主關鍵字「${kw}」`);
  if (!head.includes(kw))
    issues.push(`前 300 字未出現「${kw}」`);
  if ([...article.title].length > 35)
    issues.push(`title 過長 (SERP 約 30 字截斷)`);
  if ([...article.description].length > 80)
    issues.push(`description 過長`);
  if ([...article.description].length < 30)
    issues.push(`description 過短`);

  if (issues.length === 0) return 'PASS';
  if (issues.length === 1) return 'WARN';
  return 'FAIL';
}

真實結果

SEO Health Check — 195 articles scanned
PASS 69  WARN 67  FAIL 59

第一次看到這個數字我嚇了一跳。59 篇 FAIL——也就是 30% 的文章在 SEO 上是裸奔的。

最常見的 FAIL 模式:標題寫得很「文青」,description 直接抄標題的延伸,結果主關鍵字一次都沒出現在前 300 字

例如:

[FAIL] career/ai-arch-bidding.md  (kw: 公共)
       公共工程標單與估價解析:三秒破解巨型 RFP 招標書
       · description 缺主關鍵字「公共」
       · 前 300 字未出現「公共」

這篇文章內容講「建築業如何用 AI 解 RFP」,但整篇前 300 字都在講「我的客戶痛苦的故事」,等講到「公共工程」已經是第 4 段了。Google 看不到。

學到的事

  1. 不要假設「中文 SEO 工具」存在。它不存在。或者存在但很爛。最快的解法是寫 100 行 Node。
  2. 啟發式 > 完美 tokenizer。我花 30 分鐘寫的「取前 2 個 CJK 字」雖然粗糙,但它真的能跑 195 篇文章 並標出 59 個問題。完美的中文分詞器需要花一週搞定。
  3. 「文案感」與「SEO 友善」是 trade-off。我的標題寫得讓人想點,但 Google 看不到。正確做法不是放棄文案感,而是兩個都要:標題前半放關鍵字,後半放文案。例:「會計 AI 實戰:用 ChatGPT 把月結從 4 小時變 30 分鐘」。
  4. 零依賴工具是長期資產。這個腳本沒有 npm install 任何東西,只用 Node 內建模組。三年後我重灌電腦、換 Node 版本、刪 node_modules,它都還能跑。

接下來要做的事

  • 把 59 篇 FAIL 文章逐篇修 description(這是 SEO 報酬率最高的單一行動)
  • --fix flag,讓腳本自己提議新的 description(餵給 LLM 改寫,類似 LangChain 的 pipeline 模式)
  • 整合到 CI:PR 如果引入新的 FAIL 文章就 block

原始碼在 scripts/seo-check.mjs。100 行,零依賴,可直接 fork 套到你的 Astro 站。


❓ FAQ

Q:這個啟發式的「取前 2 個 CJK 字」準確率如何?

A:粗估約 70–80% 的情況能抓到有意義的主關鍵字。主要失敗情境是:標題以動詞開頭(如「打造⋯」抓到「打造」而非核心名詞)、或標題完全用英文術語。但它的目的不是完美分詞,而是「快速標出有問題的文章」——即使關鍵字抓偏了,那篇文章通常也確實有 SEO 問題需要關注。

Q:為什麼不用 jieba 分詞?

A:jieba 是正規的中文分詞工具,品質遠好於啟發式。但它需要 Python 環境 + 200MB 詞典,對一個 build-time 的輕量腳本來說太重了。而且我的需求不是「精準分詞」,只是「粗暴的 SEO 體檢」。當你只需要 80% 的準確度時,100 行零依賴的 Node 腳本比完美的 NLP 方案更有價值。

Q:其他 Astro 站也能直接用這個腳本嗎?

A:可以,只要你的內容也是 Markdown + frontmatter 格式。需要改的只有:1) CONTENT_DIR 路徑,2) frontmatter 的欄位名(你可能叫 name 不叫 title),3) 停用字清單(根據你的內容領域調整)。整體改動不超過 10 行。

Q:PASS / WARN / FAIL 的分級標準可以自己調嗎?

A:可以,而且應該調。我用的是「0 個問題 = PASS / 1 個 = WARN / 2+ 個 = FAIL」,但這只是我自己的容忍度。如果你的內容比較技術向,title 長度限制可能可以放寬;如果你主攻 Google Discover,description 長度門檻要拉更嚴。腳本本身只是框架,規則請依站調。

Q:這個腳本會不會誤殺寫得很好的「文案型」標題?

A:會,而且這正是它的價值。被 FAIL 不代表文章不好,而是提醒你:「這個標題讀者愛看,但 Google 看不到關鍵字」。解法不是改回無聊的標題,而是用「關鍵字 + 文案感」的混合寫法,例:「會計 AI 實戰:把月結從 4 小時變 30 分鐘」——前半吃 SEO,後半吃點擊率。

Q:和用 LLM 評分比起來,這個腳本的優劣是?

A:LLM 評分(丟給 GPT 看每篇文章 SEO 如何)會更細膩、能給出質化建議,但也有三個缺點:1) 每篇要 API call,195 篇跑一次不便宜;2) 不同時段跑結果會飄,難以當基線;3) 慢。這個腳本 3 秒跑完、完全 deterministic、零成本。兩者定位不同:腳本做定期體檢,LLM 做深度診斷。