Files
hbr-crawler/SDD.md
DonaldFang 方士碩 f524713cb6 Initial commit: HBR 文章爬蟲專案
- Scrapy 爬蟲框架,爬取 HBR 繁體中文文章
- Flask Web 應用程式,提供文章查詢介面
- SQL Server 資料庫整合
- 自動化排程與郵件通知功能

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 17:19:56 +08:00

655 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 Password16 碼)
- `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 | 根據需求問卷更新:<br>- 更新資料庫設計(標籤非正規化、多語言支援)<br>- 新增增量爬取邏輯<br>- 新增資料清理機制<br>- 新增 Web 查詢介面規劃<br>- 新增統計功能規劃<br>- 更新排程設計(可設定、每天執行)<br>- 更新日誌設計(資料庫儲存)<br>- 更新錯誤通知機制<br>- 新增 Excel 匯出規劃 | - |
---
**文件結束**