- 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
129 lines
4.8 KiB
Markdown
129 lines
4.8 KiB
Markdown
# Barron's 股票推薦爬蟲(模組化架構)
|
||
|
||
一個可擴充的爬蟲服務,內建 HTTP API 與多種通知(Email/Webhook/Discord)。
|
||
現已模組化:API 與爬蟲核心分離,便於未來新增其他網站的爬蟲。
|
||
|
||
## 功能
|
||
- 定時抓取 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
|
||
cp .env.template .env
|
||
# 編輯 .env,至少設定你要用到的通知方式(Email/Webhook/Discord 任選)
|
||
```
|
||
|
||
2) 啟動服務
|
||
```bash
|
||
docker-compose up -d
|
||
docker-compose logs -f barrons-crawler
|
||
```
|
||
|
||
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
|
||
```
|
||
|
||
## 本機執行(非 Docker)
|
||
```bash
|
||
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
|
||
docker-compose build
|
||
docker-compose up -d
|
||
docker-compose restart
|
||
docker-compose logs -f barrons-crawler
|
||
docker-compose down
|
||
```
|
||
|
||
## 資料與日誌
|
||
- 預設位置(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 設定、應用程式密碼、連接埠與加密方式
|
||
- 解析不到內容:查看日誌,更新選擇器邏輯
|
||
- 服務無回應:檢查容器日誌與健康檢查狀態
|
||
|
||
## 安全建議
|
||
- 不要把密碼放到版本控制;使用 `.env` 並將其列入 `.gitignore`
|
||
- 適度限制通知頻率與內容,避免濫用
|
||
- 若對外開放 API,建議加上認證與 HTTPS
|
||
|
||
## 版本記事
|
||
- 2025-09:重構為模組化架構,API 與爬蟲邏輯分離,新增擴充範本
|
||
|