快轉到主要內容

讓 AI 成為您的專屬編輯部:一套基於 Linux 的自動化報紙系統設計

·1270 字·3 分鐘·
PolloChang
作者
PolloChang
我是一隻雞

讓 AI 成為您的專屬編輯部:一套基於 Linux 的自動化報紙系統設計
#

在資訊爆炸的時代,每天手動去檢查監控數據、搜集新聞簡直是浪費生命。作為工程師,我們應該追求極致的自動化。今天分享一套我親手打造的 Pollo AI News 自動化生產線

這套系統不只是個腳本,它是一套具備「職位分工」與「pipeline 解耦」設計的生產流程

實測結果
#

pollo-news

核心設計理念:解耦與職責分離 (SoC)
#

不同於將所有邏輯塞進一個腳本,我將整個新聞系統拆解為三個核心職位,分別處理不同的業務邏輯。這種設計的好處在於:若某個環節掛掉,不會導致系統崩潰,且方便隨時擴充新的業務邏輯。

1. 職位定義
#

  • 記者 (Reporter):負責資料收集 (Data Acquisition)。它只管把世界各地的數據(如 Prometheus 指標、API、RSS)轉化為 Markdown 草稿。
  • 總編 (Editor-in-Chief):負責彙整與校對 (Aggregation & Formatting)。它不關心資料怎麼來,只關心如何將所有草稿整合,產出最終的 MD 文件。
  • 郵差 (Mailman):負責派送 (Distribution)。它唯一的任務就是把最終檔案送到讀者手中。

系統架構圖 (Project Structure)
#

1
2
3
4
5
6
7
/home/hermes/news-paper/
├── daily-draft/yyyy-mm-dd/  # 記者存放的 raw markdown 產出
├── news/yyyy-mm-dd.md        # 總編產出的最終報紙成品
└── scripts/                  # 職位 SOP 腳本
    ├── collect_data.sh       # 記者 SOP
    ├── editor_merge.sh       # 總編 SOP
    └── send_mail.sh          # 郵差 SOP

實作細節:職位 SOP (Shell Scripts)
#

記者 SOP (collect_data.sh)
#

利用 curljq 直接從 Prometheus 撈取即時監控數據,並生成 Markdown。

1
2
3
4
5
6
7
# 抓取並計算數據後,輸出至草稿資料夾
cat << EOF > "$DRAFT_DIR/01_weather.md"
## 現在氣溫
* 目前溫度: $TEMP °C
* 目前濕度: $HUMID %
* 體感溫度: $FEELS_LIKE °C
EOF

總編 SOP (editor_merge.sh)
#

這是系統的靈魂。不管記者產出多少份草稿,總編只透過 cat 進行線性彙整。這意味著您隨時可以增加 02_news.md03_stock.md,系統完全不需要修改任何程式碼。

郵差 SOP (send_mail.sh)
#

結合專用的 CLI 工具進行郵件寄送。


精準的排程調度 (Cron Pipeline)
#

我們利用 Linux Cron 來控制業務節奏,確保資訊流按時湧動:

1
2
3
4
5
6
7
8
# 07:30 記者截稿:開始搜集所有數據
30 07 * * * /home/hermes/news-paper/scripts/collect_data.sh

# 07:40 總編彙整:將所有 MD 檔案併入最終稿
40 07 * * * /home/hermes/news-paper/scripts/editor_merge.sh

# 08:00 郵差派送:準時把當日報紙寄出
00 08 * * * /home/hermes/news-paper/scripts/send_mail.sh

為什麼我要這樣做?
#

  1. 高度擴充性:明天如果想加一個「財經快訊」,只需再寫一個記者腳本,並在 07:30-07:40 之間塞進排程,總編會自動幫你彙整。
  2. 極致容錯:如果記者蒐集失敗,總編會發現草稿目錄是空的或不完整;如果最終稿不存在,郵差會自動放棄派送,不會寄出空信件給讀者。
  3. 無痛維運:純 Linux 原生工具(Bash, Curl, JQ),沒有複雜的框架依賴,極輕量,極穩定。

這就是我每天早上 8 點準時收到客製化報紙的秘密。想玩轉自動化的朋友,不妨也打造一套屬於自己的「編輯部」吧!

腳本內容
#

  • /home/hermes/news-paper/scripts/collect_data.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/bin/bash
DATE=$(date +%Y-%m-%d)
DRAFT_DIR="/home/hermes/news-paper/daily-draft/$DATE"
mkdir -p "$DRAFT_DIR"

TEMP=$(curl -s -u  "http://127.0.0.1:9090/prometheus/api/v1/query?query=j18_temperature_celsius" | jq -r '.data.result[0].value[1]')
HUMID=$(curl -s -u  "http://127.0.0.1:9090/prometheus/api/v1/query?query=j18_humidity_percent" | jq -r '.data.result[0].value[1]')
FEELS_LIKE=$(python3 -c "import math; t=$TEMP; rh=$HUMID; print(f'{t + 0.33 * ((rh/100) * 6.105 * math.exp(17.27 * t / (237.7 + t))) - 4.00:.2f}')")

cat << EOF > "$DRAFT_DIR/01_weather.md"
## 現在氣溫

* 目前溫度: $TEMP °C
* 目前濕度: $HUMID %
* 體感溫度: $FEELS_LIKE °C
EOF
  • /home/hermes/news-paper/scripts/editor_merge.sh
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#!/bin/bash
DATE=$(date +%Y-%m-%d)
DRAFT_DIR="/home/hermes/news-paper/daily-draft/$DATE"
FINAL_NEWS="/home/hermes/news-paper/news/$DATE.md"

echo "# Pollo AI News $DATE" > "$FINAL_NEWS"
echo "" >> "$FINAL_NEWS"

if [ -d "$DRAFT_DIR" ]; then
    cat "$DRAFT_DIR"/*.md >> "$FINAL_NEWS"
fi
  • /home/hermes/news-paper/scripts/send_mail.sh
1
2
3
4
5
6
7
8
9
#!/bin/bash
DATE=$(date +%Y-%m-%d)
FINAL_NEWS="/home/hermes/news-paper/news/$DATE.md"

if [ -f "$FINAL_NEWS" ]; then
    pollo-mail-cli send -t [email protected] -s "Pollo AI News $DATE" -b "$(cat $FINAL_NEWS)"
else
    echo "錯誤: $FINAL_NEWS 不存在,無法寄送。"
fi