# 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 匯出規劃 | - | --- **文件結束**