refactor: modularize project structure and separate API from crawlers
- Introduce app/ package with config, services (storage, notifications), API server, and crawler modules - Add BaseCrawler and BarronsCrawler; extract notifications and storage - Keep enhanced_crawler.py as back-compat entry delegating to app.runner - Add template crawler for future sites - Update README with new structure and usage - Extend .env.template with DATA_DIR/LOG_DIR options
This commit is contained in:
357
README.md
357
README.md
@@ -1,281 +1,128 @@
|
||||
# Barron's 股票推薦爬蟲 Docker 部署指南
|
||||
# Barron's 股票推薦爬蟲(模組化架構)
|
||||
|
||||
## 🚀 快速開始
|
||||
一個可擴充的爬蟲服務,內建 HTTP API 與多種通知(Email/Webhook/Discord)。
|
||||
現已模組化:API 與爬蟲核心分離,便於未來新增其他網站的爬蟲。
|
||||
|
||||
### 1. 建立專案目錄
|
||||
## 功能
|
||||
- 定時抓取 Barron's 股票推薦頁面
|
||||
- 只在有新內容時發送通知(可設定首次啟動也通知)
|
||||
- 內建 `/health`、`/stats`、`/check` 與 `/notify_test` API
|
||||
- Docker 化部署,資料與日誌可持久化
|
||||
- 架構模組化,易於擴充其他站點
|
||||
|
||||
## 專案結構
|
||||
```
|
||||
app/
|
||||
runner.py # 啟動流程(載入設定、啟動 API 與爬蟲)
|
||||
config.py # 設定載入與 logging
|
||||
api/server.py # Flask API
|
||||
crawlers/base.py # BaseCrawler:通用排程/比對/通知
|
||||
crawlers/barrons.py # Barron’s 爬蟲
|
||||
crawlers/template.py # 新站點範本(複製後改名擴充)
|
||||
services/storage.py # JSON 儲存
|
||||
services/notifications.py # Email/Webhook/Discord
|
||||
enhanced_crawler.py # 舊入口,現委派到 app.runner
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
requirements.txt
|
||||
health_check.py
|
||||
.env / .env.template
|
||||
data/ # 持久化資料(預設)
|
||||
logs/ # 持久化日誌(預設)
|
||||
```
|
||||
|
||||
## 快速開始(Docker)
|
||||
1) 建立環境變數檔
|
||||
```bash
|
||||
mkdir barrons-crawler
|
||||
cd barrons-crawler
|
||||
cp .env.template .env
|
||||
# 編輯 .env,至少設定你要用到的通知方式(Email/Webhook/Discord 任選)
|
||||
```
|
||||
|
||||
### 2. 創建文件結構
|
||||
```
|
||||
barrons-crawler/
|
||||
├── Dockerfile
|
||||
├── docker-compose.yml
|
||||
├── requirements.txt
|
||||
├── enhanced_crawler.py
|
||||
├── health_check.py
|
||||
├── .dockerignore
|
||||
├── .env # 環境變數設定檔
|
||||
├── data/ # 資料持久化目錄
|
||||
└── logs/ # 日誌目錄
|
||||
```
|
||||
|
||||
### 3. 設定環境變數
|
||||
創建 `.env` 檔案:
|
||||
2) 啟動服務
|
||||
```bash
|
||||
# 基本設定
|
||||
CHECK_INTERVAL=300
|
||||
LOG_LEVEL=INFO
|
||||
ALWAYS_NOTIFY_ON_STARTUP=false # 啟動後第一次必定寄當前清單
|
||||
|
||||
# 電子郵件通知設定(SMTP)
|
||||
# 對 Gmail:建議使用應用程式密碼
|
||||
# 對學校/企業信箱:請依管理者提供之 SMTP 主機與加密方式設定
|
||||
EMAIL_SMTP_SERVER=smtp.gmail.com # 例:mail.ntust.edu.tw
|
||||
EMAIL_SMTP_PORT=587 # starttls 常用 587;ssl 常用 465
|
||||
EMAIL_SMTP_SECURITY=starttls # starttls | ssl | none
|
||||
EMAIL_FROM=your_email@gmail.com # 例:m10605505@mail.ntust.edu.tw
|
||||
EMAIL_TO=notification@gmail.com
|
||||
EMAIL_USERNAME=your_email@gmail.com # 有些伺服器需填完整信箱
|
||||
EMAIL_PASSWORD=your_app_specific_password
|
||||
|
||||
# Slack Webhook(可選)
|
||||
WEBHOOK_URL=https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK
|
||||
|
||||
# Discord Webhook(可選)
|
||||
DISCORD_WEBHOOK=https://discord.com/api/webhooks/YOUR/DISCORD/WEBHOOK
|
||||
```
|
||||
|
||||
### 4. 啟動服務
|
||||
```bash
|
||||
# 使用 Docker Compose 啟動
|
||||
docker-compose up -d
|
||||
|
||||
# 查看日誌
|
||||
docker-compose logs -f barrons-crawler
|
||||
```
|
||||
|
||||
## 📋 詳細設定選項
|
||||
|
||||
### 電子郵件設定(SMTP)
|
||||
1. 若使用 Gmail:
|
||||
- 開啟兩步驟驗證
|
||||
- 生成應用程式密碼:https://myaccount.google.com/apppasswords
|
||||
- 在 `.env` 使用應用程式密碼,而非一般密碼
|
||||
2. 若使用學校/企業郵件(如 NTUST):
|
||||
- 向管理者確認 SMTP 主機、連接埠與加密方式(starttls 或 ssl)
|
||||
- `EMAIL_USERNAME` 可能需要填完整信箱(例如 `m10605505@mail.ntust.edu.tw`)
|
||||
|
||||
### 啟動後首次通知行為
|
||||
- 環境變數 `ALWAYS_NOTIFY_ON_STARTUP`
|
||||
- `true/1/yes`:服務啟動完成後,第一次檢查即使沒有新內容也會寄出目前清單;之後只在有更新時寄出
|
||||
- `false`(預設):只有在偵測到新內容時才寄出
|
||||
|
||||
### Slack 通知設定
|
||||
1. 建立 Slack App: https://api.slack.com/apps
|
||||
2. 創建 Incoming Webhook
|
||||
3. 複製 Webhook URL 到 `.env` 檔案
|
||||
|
||||
### Discord 通知設定
|
||||
1. 在 Discord 伺服器創建 Webhook
|
||||
2. 複製 Webhook URL 到 `.env` 檔案
|
||||
|
||||
## 🔧 Docker 指令
|
||||
|
||||
### 基本操作
|
||||
```bash
|
||||
# 建構映像
|
||||
docker-compose build
|
||||
|
||||
# 啟動服務
|
||||
docker-compose up -d
|
||||
|
||||
# 停止服務
|
||||
docker-compose down
|
||||
|
||||
# 重啟服務
|
||||
docker-compose restart
|
||||
|
||||
# 查看日誌
|
||||
docker-compose logs -f
|
||||
|
||||
# 進入容器
|
||||
docker-compose exec barrons-crawler bash
|
||||
```
|
||||
|
||||
### 維護指令
|
||||
```bash
|
||||
# 清理停用的容器
|
||||
docker system prune
|
||||
|
||||
# 更新並重新建構
|
||||
docker-compose down
|
||||
docker-compose build --no-cache
|
||||
docker-compose up -d
|
||||
|
||||
# 備份資料
|
||||
docker cp barrons-crawler:/app/data ./data_backup
|
||||
```
|
||||
|
||||
## 🌐 Web API 端點
|
||||
|
||||
爬蟲提供了以下 HTTP 端點:
|
||||
|
||||
### 健康檢查
|
||||
3) 驗證 API
|
||||
```bash
|
||||
curl http://localhost:8080/health
|
||||
curl http://localhost:8080/stats | jq
|
||||
curl http://localhost:8080/check | jq
|
||||
curl "http://localhost:8080/notify_test?channel=email" # 或 webhook/discord
|
||||
```
|
||||
回應:`{"status": "healthy", "timestamp": "2024-01-15T10:30:00"}`
|
||||
|
||||
### 查看統計資料
|
||||
## 本機執行(非 Docker)
|
||||
```bash
|
||||
curl http://localhost:8080/stats
|
||||
```
|
||||
回應:
|
||||
```json
|
||||
{
|
||||
"start_time": "2024-01-15T10:00:00",
|
||||
"total_checks": 24,
|
||||
"new_picks_found": 3,
|
||||
"last_check": "2024-01-15T10:25:00",
|
||||
"last_notification": "2024-01-15T09:45:00",
|
||||
"errors": 0
|
||||
}
|
||||
pip install -r requirements.txt
|
||||
python enhanced_crawler.py
|
||||
```
|
||||
|
||||
### 手動觸發檢查
|
||||
## 環境變數說明
|
||||
- 基本
|
||||
- `CHECK_INTERVAL`: 檢查間隔(秒),預設 300
|
||||
- `LOG_LEVEL`: 日誌等級,預設 `INFO`(可 `DEBUG`)
|
||||
- `ALWAYS_NOTIFY_ON_STARTUP`: 是否在啟動後第一次就寄出目前清單(true/false),預設 false
|
||||
- Email(可選)
|
||||
- `EMAIL_SMTP_SERVER`、`EMAIL_SMTP_PORT`(587/465/25)
|
||||
- `EMAIL_SMTP_SECURITY`: starttls | ssl | none(預設 starttls)
|
||||
- `EMAIL_FROM`、`EMAIL_TO`、`EMAIL_USERNAME`、`EMAIL_PASSWORD`
|
||||
- Webhook(可選)
|
||||
- `WEBHOOK_URL`: Slack/Teams Incoming Webhook URL
|
||||
- Discord(可選)
|
||||
- `DISCORD_WEBHOOK`: Discord Webhook URL
|
||||
- 進階路徑(可選)
|
||||
- `DATA_DIR`: 資料輸出路徑(Docker 預設 `/app/data`;本機預設 `./data`)
|
||||
- `LOG_DIR`: 日誌輸出路徑(Docker 預設 `/app/logs`;本機預設 `./logs`)
|
||||
|
||||
Email 使用建議:
|
||||
- Gmail 請使用「應用程式密碼」並開啟兩步驟驗證
|
||||
- 校園/企業信箱請向管理者確認 SMTP 主機、連接埠與加密方式
|
||||
|
||||
## Web API 端點
|
||||
- `GET /health`: 健康檢查
|
||||
- `GET /stats`: 目前統計資訊(啟動時間、檢查次數、錯誤數…)
|
||||
- `GET /check`: 立即執行一次檢查
|
||||
- `GET /notify_test?channel=email|webhook|discord`: 測試通知
|
||||
|
||||
## 健康檢查與維運
|
||||
- 容器內建 HEALTHCHECK(每 30 秒檢查一次 `/health`,連續 3 次失敗標記為不健康)
|
||||
- 常用指令
|
||||
```bash
|
||||
curl http://localhost:8080/check
|
||||
```
|
||||
|
||||
## 📊 監控和警報
|
||||
|
||||
### 健康檢查
|
||||
Docker 容器包含自動健康檢查:
|
||||
- 每30秒檢查一次
|
||||
- 3次失敗後標記為不健康
|
||||
- 可用於自動重啟策略
|
||||
|
||||
### 日誌監控
|
||||
```bash
|
||||
# 即時查看日誌
|
||||
docker-compose build
|
||||
docker-compose up -d
|
||||
docker-compose restart
|
||||
docker-compose logs -f barrons-crawler
|
||||
|
||||
# 查看特定時間的日誌
|
||||
docker-compose logs --since "2024-01-15T10:00:00" barrons-crawler
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
### 資料備份
|
||||
```bash
|
||||
# 設定定期備份(加到 crontab)
|
||||
0 2 * * * docker cp barrons-crawler:/app/data /backup/barrons-$(date +\%Y\%m\%d)
|
||||
```
|
||||
## 資料與日誌
|
||||
- 預設位置(Docker):`/app/data`、`/app/logs`(已透過 volume 映射至宿主 `./data`、`./logs`)
|
||||
- 檔案格式(以 Barron’s 為例:`data/barrons_data.json`)
|
||||
- `last_update`: ISO 時間
|
||||
- `stock_picks`: 文章清單(title/link/hash/scraped_at)
|
||||
- `stats`: 執行統計
|
||||
|
||||
## 🐛 故障排除
|
||||
## 擴充新站點(建議流程)
|
||||
1) 複製範本:`app/crawlers/template.py` → `app/crawlers/<your_site>.py`
|
||||
2) 實作兩個方法:
|
||||
- `fetch_page(self) -> Optional[str]`:抓取 HTML
|
||||
- `parse_items(self, html: str) -> List[Dict]`:輸出包含 `title`(必要)、建議 `link`、`hash`、`scraped_at`
|
||||
3) 啟動方式:
|
||||
- 簡單做法:為新站點建立第二個容器(複製服務段落,指定不同資料檔/埠口)
|
||||
- 進階做法:在 `app/runner.py` 啟動多個爬蟲與多站 API(需擴充 API 路由與執行緒管理)
|
||||
|
||||
### 常見問題
|
||||
## 故障排除
|
||||
- 取不到網頁:檢查網路、User-Agent、目標網站是否改版
|
||||
- Email 失敗:確認 SMTP 設定、應用程式密碼、連接埠與加密方式
|
||||
- 解析不到內容:查看日誌,更新選擇器邏輯
|
||||
- 服務無回應:檢查容器日誌與健康檢查狀態
|
||||
|
||||
1. **無法獲取網頁內容**
|
||||
```bash
|
||||
# 檢查網路連線
|
||||
docker-compose exec barrons-crawler curl -I https://www.barrons.com
|
||||
```
|
||||
## 安全建議
|
||||
- 不要把密碼放到版本控制;使用 `.env` 並將其列入 `.gitignore`
|
||||
- 適度限制通知頻率與內容,避免濫用
|
||||
- 若對外開放 API,建議加上認證與 HTTPS
|
||||
|
||||
2. **電子郵件發送失敗**
|
||||
- 檢查 Gmail 應用程式密碼是否正確
|
||||
- 確認兩步驟驗證已開啟
|
||||
- 檢查防火牆設定
|
||||
## 版本記事
|
||||
- 2025-09:重構為模組化架構,API 與爬蟲邏輯分離,新增擴充範本
|
||||
|
||||
3. **解析內容失敗**
|
||||
- 網頁結構可能已變更
|
||||
- 檢查日誌中的錯誤訊息
|
||||
- 可能需要更新解析邏輯
|
||||
|
||||
4. **容器無法啟動**
|
||||
```bash
|
||||
# 檢查詳細錯誤
|
||||
docker-compose logs barrons-crawler
|
||||
|
||||
# 檢查磁碟空間
|
||||
df -h
|
||||
|
||||
# 檢查埠口占用
|
||||
netstat -tlnp | grep 8080
|
||||
```
|
||||
|
||||
### 調試模式
|
||||
```yaml
|
||||
# 在 docker-compose.yml 中添加
|
||||
environment:
|
||||
- LOG_LEVEL=DEBUG
|
||||
|
||||
# 或者進入容器手動執行
|
||||
docker-compose exec barrons-crawler python enhanced_crawler.py
|
||||
```
|
||||
|
||||
## 🔒 安全建議
|
||||
|
||||
1. **不要在代碼中硬編碼密碼**
|
||||
- 使用 `.env` 檔案或 Docker secrets
|
||||
- 將 `.env` 加入 `.gitignore`
|
||||
|
||||
2. **定期更新依賴**
|
||||
```bash
|
||||
# 更新基礎映像
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
3. **監控資源使用**
|
||||
```bash
|
||||
# 查看容器資源使用
|
||||
docker stats barrons-crawler
|
||||
```
|
||||
|
||||
4. **網路安全**
|
||||
- 使用反向代理(如 Nginx)
|
||||
- 設定適當的防火牆規則
|
||||
- 啟用 HTTPS(如果對外開放)
|
||||
|
||||
## 📈 擴展功能
|
||||
|
||||
### 多實例部署
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
barrons-crawler-1:
|
||||
# ... 設定
|
||||
barrons-crawler-2:
|
||||
# ... 設定
|
||||
environment:
|
||||
- CHECK_INTERVAL=600 # 不同檢查間隔
|
||||
```
|
||||
|
||||
### 與其他服務整合
|
||||
```yaml
|
||||
# 加入資料庫
|
||||
postgres:
|
||||
image: postgres:15
|
||||
environment:
|
||||
POSTGRES_DB: barrons
|
||||
POSTGRES_USER: crawler
|
||||
POSTGRES_PASSWORD: password
|
||||
```
|
||||
|
||||
### 定制通知
|
||||
可以擴展 `enhanced_crawler.py` 添加:
|
||||
- Line Notify
|
||||
- Telegram Bot
|
||||
- 推播通知
|
||||
- 簡訊通知
|
||||
|
||||
## 🎯 最佳實踐
|
||||
|
||||
1. **定期監控日誌**
|
||||
2. **設定適當的檢查間隔**(避免過於頻繁)
|
||||
3. **定期備份資料**
|
||||
4. **監控資源使用情況**
|
||||
5. **設定適當的通知渠道**
|
||||
6. **遵守網站使用條款**
|
||||
|
Reference in New Issue
Block a user