- Prefix titles and email lines with normalized trade tag (BUY/SALE/...)\n- Include amount as absolute value in lines; keep threshold logic unchanged
股票爬蟲服務(模組化架構)
可擴充的股票爬蟲服務,內建 HTTP API 與多種通知(Email/Webhook/Discord)。 目前提供三類爬蟲:
- Barron's 股票推薦
- OpenInsider 內部人交易(支援多標的)
- OpenInsider 當日大額內部人交易(跨三頁合併、金額過濾)
功能
- 定時抓取(支援每 N 秒或每日固定時間)
- 只在有新內容時發送通知(可設定首次啟動也通知)
- 內建
/health
、/info
、/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/openinsider.py # OpenInsider 內部人交易爬蟲(多標的)
crawlers/template.py # 新站點範本(複製後改名擴充)
services/storage.py # JSON 儲存
services/notifications.py # Email/Webhook/Discord
main.py # 入口點,委派到 app.runner
Dockerfile
docker-compose.yml
requirements.txt
health_check.py
.env / .env.template
data/ # 持久化資料(預設)
logs/ # 持久化日誌(預設)
快速開始(Docker)
- 建立環境變數檔
cp .env.template .env
# 編輯 .env,至少設定你要用到的通知方式(Email/Webhook/Discord 任選)
- 啟動服務
docker-compose up -d
docker-compose logs -f barrons-crawler
- 驗證 API
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)
pip install -r requirements.txt
python main.py
環境變數說明
-
基本
CHECK_INTERVAL
: 檢查間隔(秒),預設 300(若設定了RUN_DAILY_AT
則忽略)RUN_DAILY_AT
: 每天固定時間(例如12:00
),使用容器本機時區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
)
-
爬蟲選擇與參數
CRAWLER_TYPE
:barrons
|openinsider
|openinsider_top
(可用逗號同時啟多種,例如:openinsider_top,openinsider
)- Barron's:無額外參數
- OpenInsider(依個別股票查詢):
- 單一標的:
SYMBOL=PLTR
- 多個標的:
SYMBOLS=PLTR,NVDA,TSLA
- 單一標的:
- OpenInsider 當日大額(跨頁合併):
- 來源頁面:
http://openinsider.com/top-insider-sales-of-the-day
http://openinsider.com/top-insider-purchases-of-the-day
http://openinsider.com/top-officer-purchases-of-the-day
- 金額門檻(含千分位、自動去
$
):INSIDER_MIN_AMOUNT
,預設1000000
- 來源頁面:
Email 使用建議:
- Gmail 請使用「應用程式密碼」並開啟兩步驟驗證
- 校園/企業信箱請向管理者確認 SMTP 主機、連接埠與加密方式
Web API 端點
GET /health
: 健康檢查GET /info
: 當前爬蟲資訊(多實例時回傳陣列)GET /stats
: 目前統計資訊(單實例為物件,多實例為 map)GET /check
: 立即執行一次檢查(多實例會對每個爬蟲都執行)GET /notify_test?channel=email|webhook|discord
: 測試通知
健康檢查與維運
- 容器內建 HEALTHCHECK(每 30 秒檢查一次
/health
,連續 3 次失敗標記為不健康) - 常用指令
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
: 執行統計
- OpenInsider 多標的:
data/openinsider_<SYMBOL>.json
擴充新站點(建議流程)
- 複製範本:
app/crawlers/template.py
→app/crawlers/<your_site>.py
- 實作兩個方法:
fetch_page(self) -> Optional[str]
:抓取 HTMLparse_items(self, html: str) -> List[Dict]
:輸出包含title
(必要)、建議link
、hash
、scraped_at
- 啟動方式:
- 簡單做法:為新站點建立第二個容器(複製服務段落,指定不同資料檔/埠口)
- 進階做法:在
app/runner.py
啟動多個爬蟲與多站 API(需擴充 API 路由與執行緒管理)
故障排除
- 取不到網頁:檢查網路、User-Agent、目標網站是否改版
- Email 失敗:確認 SMTP 設定、應用程式密碼、連接埠與加密方式
- Barron's 解析不到內容:查看日誌,更新選擇器邏輯
- OpenInsider 解析不到內容:檢查
SYMBOL/SYMBOLS
是否正確,觀察是否被站方限流 - 服務無回應:檢查容器日誌與健康檢查狀態
安全建議
- 不要把密碼放到版本控制;使用
.env
並將其列入.gitignore
- 適度限制通知頻率與內容,避免濫用
- 若對外開放 API,建議加上認證與 HTTPS
版本記事
- 2025-09:
- 重構為模組化架構,API 與爬蟲邏輯分離
- 新增 OpenInsider 內部人交易爬蟲與多標的支援
- 新增 OpenInsider 當日大額內部人交易(≥$1,000,000)爬蟲
Description
Languages
Python
98.4%
Dockerfile
1.6%