# HBR Taiwan 文章爬蟲系統 - 軟體設計文件 (SDD)
**文件版本**: 2.0
**建立日期**: 2024-12-22
**最後更新**: 2024-12-22
---
## 1. 文件概述
### 1.1 文件目的
本文件描述 HBR Taiwan 文章爬蟲系統的軟體設計規格,包含系統架構、功能模組、資料流程、資料庫設計等技術細節。
### 1.2 專案範圍
本系統旨在自動化爬取 HBR Taiwan 網站文章,並將結果儲存至本地資料庫,同時透過 Gmail 發送 CSV 檔案給指定收件人。
### 1.3 目標讀者
- 開發人員
- 系統維護人員
- 專案管理人員
---
## 2. 系統概述
### 2.1 系統簡介
HBR Taiwan 文章爬蟲系統是一個基於 Scrapy 框架的自動化爬蟲系統,主要功能包括:
- 定期爬取 HBR Taiwan 網站文章
- 識別並標記付費文章
- 將資料儲存至本地資料庫
- 產生 CSV 檔案並透過 Gmail 發送
### 2.2 系統目標
- **自動化**: 可設定的排程時間(預設每天 08:00 Asia/Taipei)自動執行
- **可靠性**: 遵守 robots.txt,處理付費牆限制
- **可維護性**: 模組化設計,易於擴展和維護
- **資料完整性**: 確保資料正確儲存和備份
- **增量爬取**: 僅爬取新文章,提升效率
- **資料管理**: 自動清理舊資料,保留最近30次爬取記錄
### 2.3 技術架構
- **爬蟲框架**: Scrapy 2.x
- **程式語言**: Python 3.11+
- **資料庫**: MySQL / MariaDB(區域網路伺服器,SSL/TLS 加密連線)
- **郵件服務**: Gmail SMTP
- **排程系統**: Crontab(自有伺服器部署)
- **資料格式**: CSV, Excel, 關聯式資料庫
- **Web 介面**: Flask / FastAPI(資料查詢和統計)
- **多語言支援**: 繁體中文、英文、韓文
---
## 3. 系統架構設計
### 3.1 整體架構
```
┌─────────────────────────────────────────────────────────┐
│ 排程觸發器 │
│ (GitHub Actions / Crontab) │
└────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Scrapy 爬蟲引擎 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ HBR Spider │→ │ Pipeline │→ │ Items │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────┬────────────────────────────────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ 資料庫儲存 │ │ CSV 檔案產生 │
│ (Database) │ │ (CSV Export) │
└─────────────────┘ └────────┬─────────┘
│
▼
┌─────────────────┐
│ 郵件發送模組 │
│ (send_mail.py) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Gmail SMTP │
└─────────────────┘
```
### 3.2 模組劃分
#### 3.2.1 爬蟲模組 (Spider Module)
- **檔案**: `hbr_crawler/hbr_crawler/spiders/hbr.py`
- **功能**:
- 解析 HBR Taiwan 網站結構
- 提取文章資訊(標題、作者、日期、內容等)
- 識別付費文章
- 處理分頁和連結追蹤
#### 3.2.2 資料處理模組 (Pipeline Module)
- **檔案**: `hbr_crawler/hbr_crawler/pipelines.py`
- **功能**:
- CSV 匯出處理
- 資料庫儲存處理(待實作)
- 資料清理和驗證
#### 3.2.3 資料模型模組 (Items Module)
- **檔案**: `hbr_crawler/hbr_crawler/items.py`
- **功能**:
- 定義文章資料結構
- 資料欄位驗證
#### 3.2.4 郵件發送模組 (Email Module)
- **檔案**: `send_mail.py`
- **功能**:
- 讀取 CSV 檔案
- 透過 Gmail SMTP 發送郵件
- 處理附件和郵件格式
#### 3.2.5 資料庫模組 (Database Module)
- **檔案**: `hbr_crawler/hbr_crawler/database.py`
- **功能**:
- 資料庫連線管理(支援 SSL/TLS 加密)
- 資料插入和更新
- 查詢和統計功能
- 資料清理(自動刪除超過30天的資料)
#### 3.2.6 Web 查詢介面模組 (Web Interface Module)
- **檔案**: 待建立(`web_app.py` 或 `web_app/`)
- **功能**:
- 提供 Web 介面查詢文章
- 支援按日期、分類、標籤查詢
- 資料統計功能(文章數量、分類分布、作者統計等)
- 多語言支援(繁體中文、英文、韓文)
#### 3.2.7 資料匯出模組 (Export Module)
- **檔案**: 待建立(`export.py`)
- **功能**:
- CSV 匯出(已實作)
- Excel 匯出(待實作)
- JSON 匯出(可選)
---
## 4. 資料流程設計
### 4.1 爬蟲執行流程
```
1. 排程觸發
↓
2. Scrapy 啟動,載入 HBR Spider
↓
3. 訪問起始 URL 列表
↓
4. 解析文章列表頁面
↓
5. 提取文章連結
↓
6. 訪問每篇文章頁面
↓
7. 解析文章內容
├─ 提取標題、作者、日期
├─ 檢查付費牆標記
├─ 提取分類、標籤
└─ 提取內容(僅非付費文章)
↓
8. 產生 Item 物件
↓
9. 通過 Pipeline 處理
├─ CSV 匯出
└─ 資料庫儲存
↓
10. 爬蟲完成
↓
11. 觸發郵件發送
↓
12. 讀取 CSV 並發送郵件
```
### 4.2 資料處理流程
```
原始網頁 HTML
↓
CSS 選擇器解析
↓
提取資料欄位
↓
資料清理和驗證
↓
建立 Item 物件
↓
Pipeline 處理
├─→ CSV 檔案
└─→ 資料庫表格
```
---
## 5. 資料庫設計
### 5.1 資料庫選擇
- **資料庫類型**: MySQL / MariaDB
- **連線方式**: 透過環境變數設定
- **資料庫位置**: 區域網路內的伺服器
- **連線加密**: SSL/TLS 加密連線
- **資料庫名稱**: HBR_scraper
- **連線資訊**:
- Host: mysql.theaken.com
- Port: 33306
- User: A101
- Password: Aa123456(透過環境變數設定)
### 5.2 資料表設計
#### 5.2.1 articles 表(文章主表)
| 欄位名稱 | 資料型態 | 約束 | 說明 |
|---------|---------|------|------|
| id | BIGINT UNSIGNED | PRIMARY KEY, AUTO_INCREMENT | 文章唯一識別碼 |
| title | VARCHAR(500) | NOT NULL | 文章標題 |
| url | VARCHAR(1000) | NOT NULL, UNIQUE | 文章網址 |
| author | VARCHAR(200) | | 作者名稱 |
| publish_date | DATETIME | | 發布日期(資料庫原生格式) |
| summary | TEXT | | 文章摘要 |
| is_paywalled | TINYINT(1) | NOT NULL, DEFAULT 0 | 是否為付費文章 (1/0) |
| category | VARCHAR(100) | | 文章分類 |
| tags | VARCHAR(500) | | 標籤(逗號分隔字串,非正規化設計) |
| content | TEXT | | 文章內容(僅非付費文章,無長度限制) |
| language | VARCHAR(10) | DEFAULT 'zh-TW' | 語言代碼(zh-TW, en, ko) |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 資料建立時間 |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | 資料更新時間 |
| crawled_at | DATETIME | | 爬取時間 |
| crawl_count | INT | DEFAULT 1 | 爬取次數(用於追蹤歷史記錄) |
**索引設計**:
- `articles.url`: UNIQUE INDEX(避免重複爬取)
- `articles.publish_date`: INDEX(方便按日期查詢)
- `articles.category`: INDEX(方便按分類查詢)
- `articles.language`: INDEX(多語言支援)
- `articles.crawled_at`: INDEX(資料清理查詢)
- `articles.crawl_count`: INDEX(歷史記錄管理)
**注意**: 標籤採用非正規化設計,直接以逗號分隔字串儲存在 articles 表中,簡化查詢並提升效能。
#### 5.2.2 logs 表(日誌表)
| 欄位名稱 | 資料型態 | 約束 | 說明 |
|---------|---------|------|------|
| id | BIGINT UNSIGNED | PRIMARY KEY, AUTO_INCREMENT | 日誌唯一識別碼 |
| level | VARCHAR(20) | NOT NULL | 日誌級別(DEBUG, INFO, WARNING, ERROR) |
| message | TEXT | NOT NULL | 日誌訊息 |
| module | VARCHAR(100) | | 模組名稱 |
| function | VARCHAR(100) | | 函數名稱 |
| line_number | INT | | 行號 |
| traceback | TEXT | | 錯誤堆疊追蹤 |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 建立時間 |
**索引設計**:
- `logs.level`: INDEX(按級別查詢)
- `logs.created_at`: INDEX(按時間查詢)
- `logs.module`: INDEX(按模組查詢)
### 5.3 資料庫操作邏輯
#### 5.3.1 插入/更新邏輯
1. 檢查文章 URL 是否已存在
2. 若存在:
- 更新所有欄位(標題、作者、內容等可能變更)
- 更新 `updated_at` 和 `crawled_at` 時間戳
- 增加 `crawl_count` 計數
3. 若不存在:插入新記錄
4. 處理標籤:
- 標籤以逗號分隔字串儲存在 `tags` 欄位
- 直接更新 `tags` 欄位,無需關聯表操作
#### 5.3.2 增量爬取邏輯
- 依據 URL 判斷是否為新文章
- 僅爬取 URL 不在資料庫中的文章
- 可選:依據發布日期判斷(僅爬取最近 N 天的文章)
#### 5.3.3 資料清理邏輯
- **文章資料清理**:
- 自動刪除超過 30 天的資料(依據 `crawled_at`)
- 保留最近 30 次爬取記錄(依據 `crawl_count`)
- 清理策略:先刪除超過 30 天的資料,再檢查是否超過 30 次爬取記錄
- **日誌清理**:
- 保留最近 90 天的日誌記錄
- 自動刪除超過 90 天的日誌
- **清理任務**:
- 可設定為定期執行(建議每天執行一次)
- 執行時間:建議在爬蟲執行後執行
- 記錄清理操作到日誌表
#### 5.3.4 查詢邏輯
- 支援按日期範圍查詢
- 支援按分類查詢
- 支援按標籤查詢(使用 LIKE 查詢)
- 支援付費/非付費文章篩選
- 支援多語言篩選(language 欄位)
- 支援統計查詢(文章數量、分類分布、作者統計等)
---
## 6. 功能模組詳細設計
### 6.1 HBR Spider 設計
#### 6.1.1 起始 URL
```python
start_urls = [
'https://www.hbrtaiwan.com/',
'https://www.hbrtaiwan.com/topic/management',
'https://www.hbrtaiwan.com/topic/leadership',
'https://www.hbrtaiwan.com/topic/strategy',
'https://www.hbrtaiwan.com/topic/innovation',
'https://www.hbrtaiwan.com/topic/technology',
]
```
#### 6.1.2 解析邏輯
- **列表頁解析** (`parse` 方法):
- 使用多種 CSS 選擇器嘗試定位文章元素
- 提取文章連結
- 處理相對路徑轉絕對路徑
- 追蹤分頁連結
- **文章頁解析** (`parse_article` 方法):
- 提取標題(優先順序:h1 → .article-title → title)
- 提取作者(優先順序:.author → meta author)
- 提取發布日期(優先順序:.date → meta published_time)
- 提取摘要(優先順序:.summary → meta description)
- 檢查付費牆標記(.paywall, .premium, .subscription-required)
- 提取分類(優先順序:.category → URL 路徑推斷)
- 提取標籤(.tags a, .tag)
- 提取內容(僅非付費文章,多種選擇器嘗試)
#### 6.1.3 錯誤處理
- 選擇器失敗時使用備用選擇器
- 處理空值情況
- 記錄解析失敗的 URL(可選)
### 6.2 Pipeline 設計
#### 6.2.1 CSV Export Pipeline
- **功能**: 將爬取的資料匯出為 CSV 檔案
- **檔案位置**: 專案根目錄 `hbr_articles.csv`
- **編碼**: UTF-8
- **處理邏輯**:
- 將 tags 列表轉換為逗號分隔字串
- 處理 None 值,轉換為空字串
- 寫入 CSV 標題列
#### 6.2.2 Database Pipeline
- **功能**: 將資料儲存至資料庫
- **處理邏輯**:
- 建立資料庫連線(支援 SSL/TLS 加密)
- 檢查文章是否已存在(依據 URL)
- 執行插入或更新操作(更新所有欄位)
- 處理標籤(以逗號分隔字串儲存)
- 錯誤處理和重試機制
- 記錄爬取次數(crawl_count)
#### 6.2.3 Data Cleanup Pipeline(待實作)
- **功能**: 定期清理舊資料
- **處理邏輯**:
- 刪除超過 30 天的資料(依據 crawled_at)
- 保留最近 30 次爬取記錄
- 記錄清理操作日誌
### 6.3 郵件發送模組設計
#### 6.3.1 功能流程
1. 讀取環境變數(Gmail 帳號、密碼、收件人)
2. 檢查 CSV 檔案是否存在
3. 產生郵件內容(含日期時間)
4. 附加 CSV 檔案
5. 透過 SMTP_SSL 發送郵件
#### 6.3.2 安全性
- 使用 Gmail App Password(非一般密碼)
- 環境變數儲存敏感資訊
- 支援 GitHub Actions Secrets
#### 6.3.3 錯誤處理
- CSV 檔案不存在時跳過寄信(可改為發送通知)
- SMTP 連線失敗時記錄錯誤
- 郵件發送失敗時記錄日誌
- 發送錯誤通知郵件(當爬蟲執行失敗時)
### 6.4 Web 查詢介面設計(待實作)
#### 6.4.1 功能需求
- **查詢功能**:
- 按日期範圍查詢
- 按分類查詢
- 按標籤查詢(使用 LIKE 查詢)
- 按語言查詢
- 付費/非付費文章篩選
- 關鍵字搜尋(標題、內容)
- **統計功能**:
- 文章總數統計
- 分類分布統計
- 作者統計(發文數量)
- 標籤統計(熱門標籤)
- 時間趨勢分析(每日/每週/每月文章數量)
- 語言分布統計
- **匯出功能**:
- CSV 匯出
- Excel 匯出(.xlsx)
- 支援匯出查詢結果
#### 6.4.2 技術架構
- **框架**: Flask 或 FastAPI
- **前端**: HTML + CSS + JavaScript(可選:Vue.js / React)
- **多語言支援**: i18n(繁體中文、英文、韓文)
- **資料庫**: 使用現有 DatabaseManager
#### 6.4.3 頁面設計
- **首頁**: 查詢表單和統計摘要
- **查詢結果頁**: 文章列表(分頁顯示)
- **統計頁**: 圖表和統計數據
- **文章詳情頁**: 單篇文章完整資訊
### 6.5 資料匯出模組設計(待實作)
#### 6.5.1 Excel 匯出功能
- **檔案格式**: .xlsx(使用 openpyxl 或 xlsxwriter)
- **功能**:
- 匯出所有欄位
- 支援多工作表(按分類或日期分組)
- 格式化(標題、日期格式等)
- 支援大量資料匯出
#### 6.5.2 匯出選項
- 匯出所有資料
- 匯出查詢結果
- 匯出特定日期範圍
- 匯出特定分類
---
## 7. 設定檔設計
### 7.1 Scrapy Settings
- **ROBOTSTXT_OBEY**: True(遵守 robots.txt)
- **DOWNLOAD_DELAY**: 2-3(保守模式,較長延遲,避免對伺服器造成負擔)
- **ITEM_PIPELINES**: 啟用 CSV 和資料庫 Pipeline
- **USER_AGENT**: 自訂 User-Agent
- **CONCURRENT_REQUESTS**: 降低並發請求數(保守模式)
### 7.2 環境變數
- `GMAIL_USERNAME`: Gmail 帳號
- `GMAIL_APP_PASSWORD`: Gmail App Password(16 碼)
- `MAIL_TO`: 收件人信箱(預設:kaeruzak@gmail.com)
- `DB_HOST`: 資料庫主機(mysql.theaken.com)
- `DB_PORT`: 資料庫埠號(33306)
- `DB_NAME`: 資料庫名稱(HBR_scraper)
- `DB_USER`: 資料庫使用者(A101)
- `DB_PASSWORD`: 資料庫密碼(透過環境變數設定,不寫入程式碼)
- `DB_SSL`: 是否使用 SSL/TLS 加密(True)
### 7.3 資料庫連線設定
- **連線方式**: 透過環境變數設定(優先使用環境變數,其次使用 settings.py 預設值)
- **SSL/TLS**: 啟用加密連線
- **字元集**: utf8mb4(支援多語言)
- **連線池**: 可選,提升效能
### 7.4 CSV 檔案管理
- **保留策略**: 保留最近 N 個 CSV 檔案作為備份
- **檔案命名**: `hbr_articles_YYYYMMDD_HHMMSS.csv`
- **自動清理**: 刪除超過保留數量的舊檔案
---
## 8. 排程設計
### 8.1 排程設定
- **預設排程**: 每天 08:00 (Asia/Taipei)
- **可設定性**: 支援透過設定檔或環境變數設定排程時間
- **部署環境**: 自有伺服器(使用 Crontab)
### 8.2 Crontab 排程
```bash
# 每天 08:00 執行
0 8 * * * cd /path/to/project && scrapy crawl hbr && python send_mail.py
# 或使用可設定的排程腳本
0 8 * * * cd /path/to/project && python run_crawler.py
```
### 8.3 排程設定檔(可選)
- **檔案**: `schedule_config.json` 或環境變數
- **設定項目**:
- 執行時間(小時、分鐘)
- 執行頻率(每天、每週、每月)
- 是否啟用增量爬取
- 爬取日期範圍
### 8.4 手動觸發
- 支援命令列手動執行爬蟲
- 支援 Web 介面手動觸發(待實作)
---
## 9. 錯誤處理與日誌
### 9.1 錯誤類型
- **網路錯誤**: 連線超時、DNS 解析失敗
- **解析錯誤**: CSS 選擇器失效、網站結構變更
- **資料庫錯誤**: 連線失敗、SQL 語法錯誤
- **郵件錯誤**: SMTP 連線失敗、認證失敗
### 9.2 日誌設計
- **日誌級別**: DEBUG, INFO, WARNING, ERROR
- **日誌輸出**:
- 控制台輸出(開發和除錯用)
- 檔案輸出(`logs/crawler.log`)
- 資料庫儲存(`logs` 表,用於長期追蹤和查詢)
- **日誌內容**:
- 爬蟲啟動和結束時間
- 爬取的文章數量
- 錯誤訊息和堆疊追蹤
- 資料庫操作記錄
- 資料清理操作記錄
- 郵件發送狀態
### 9.3 錯誤通知
- **通知方式**: 發送錯誤通知郵件
- **觸發條件**:
- 爬蟲執行失敗
- 資料庫連線失敗
- 郵件發送失敗
- 資料清理失敗
- **通知內容**:
- 錯誤類型
- 錯誤訊息
- 發生時間
- 相關日誌片段
---
## 10. 安全性設計
### 10.1 資料安全
- 敏感資訊(密碼、API Key)使用環境變數
- 資料庫連線使用 SSL/TLS 加密連線
- 避免在程式碼中硬編碼敏感資訊
- 資料庫使用者具有完整權限(SELECT, INSERT, UPDATE, DELETE, CREATE TABLE)
### 10.2 爬蟲倫理
- 遵守 robots.txt 規則
- 設定合理的下載延遲
- 尊重網站服務條款
- 不爬取付費文章內容
### 10.3 資料保護
- 手動備份資料庫(定期執行)
- CSV 檔案保留作為備份(保留最近 N 個檔案)
- 資料保留政策:
- 自動刪除超過 30 天的資料
- 保留最近 30 次爬取記錄
---
## 11. 擴展性設計
### 11.1 已規劃擴展功能
- **Web 查詢介面**: 提供 Web 介面查詢文章(按日期、分類、標籤)
- **資料統計功能**: 文章數量、分類分布、作者統計等
- **Excel 匯出**: 支援 Excel 格式匯出(.xlsx)
- **多語言支援**: 繁體中文、英文、韓文
- **增量爬取**: 僅爬取新文章,提升效率
- **資料清理**: 自動清理舊資料,保留最近 30 次爬取記錄
### 11.2 未來擴展方向
- 支援多個網站爬取
- 產生報表(週報、月報)
- 視覺化圖表
- 支援即時通知(Slack, Teams)
- 雲端儲存整合(S3, Google Drive)
- API 介面(RESTful API)
### 11.2 模組化設計
- Pipeline 可插拔設計
- 支援自訂資料處理邏輯
- 易於新增新的資料來源
---
## 12. 測試策略
### 12.1 單元測試
- Spider 解析邏輯測試
- Pipeline 處理邏輯測試
- 資料庫操作測試
### 12.2 整合測試
- 完整爬蟲流程測試
- 郵件發送測試
- 資料庫儲存測試
### 12.3 手動測試
- 本地環境測試
- 排程觸發測試
- 錯誤情境測試
---
## 13. 部署與維護
### 13.1 部署步驟
1. 設定環境變數(資料庫連線資訊、Gmail 設定)
2. 安裝依賴套件(`pip install -r requirements.txt`)
3. 測試資料庫連線(`python test_db_connection.py`)
4. 建立資料表結構(執行 `create_tables.sql`)
5. 設定排程(Crontab,預設每天 08:00)
6. 執行測試爬取
7. 設定資料清理排程(可選,定期清理舊資料)
8. 部署 Web 查詢介面(待實作)
### 13.2 維護事項
- 定期檢查爬蟲執行狀態
- 監控資料庫空間使用
- 檢查網站結構變更
- 更新 CSS 選擇器(如需要)
- 手動備份資料庫(定期執行)
- 清理舊 CSV 檔案(保留最近 N 個)
- 檢查日誌檔案大小
- 監控錯誤通知郵件
---
## 14. 附錄
### 14.1 參考資料
- [Scrapy 官方文件](https://docs.scrapy.org/)
- [Python SMTP 文件](https://docs.python.org/3/library/smtplib.html)
- [GitHub Actions 文件](https://docs.github.com/en/actions)
### 14.2 變更記錄
| 版本 | 日期 | 變更內容 | 作者 |
|------|------|---------|------|
| 1.0 | 2024-12-22 | 初始版本 | - |
| 2.0 | 2024-12-22 | 根據需求問卷更新:
- 更新資料庫設計(標籤非正規化、多語言支援)
- 新增增量爬取邏輯
- 新增資料清理機制
- 新增 Web 查詢介面規劃
- 新增統計功能規劃
- 更新排程設計(可設定、每天執行)
- 更新日誌設計(資料庫儲存)
- 更新錯誤通知機制
- 新增 Excel 匯出規劃 | - |
---
**文件結束**