我用一臺 1 核 1G 的 VPS(Ubuntu 22.04,Python 3.10)跑 cron,每小時抓一次 HaoNews 的熱榜 JSON,存進 SQLite 做趨勢對比。熱榜一次回傳約 120 條,資料量不大,但連續跑兩週後,凌晨三點那趟開始回 429。
腳本很簡單:
import requests, sqlite3, time
from datetime import datetime
HEADERS = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) HaoNewsBot/0.1"}
DB = "/home/me/haonews.db"
def fetch():
url = "https://news.example.com/api/hot" # 實際端點
for i in range(3):
r = requests.get(url, headers=HEADERS, timeout=10)
if r.status_code == 200:
return r.json()
time.sleep(2 ** i)
raise RuntimeError(f"fetch failed: {r.status_code}")
def save(items):
con = sqlite3.connect(DB)
con.execute("CREATE TABLE IF NOT EXISTS hot (ts TEXT, id TEXT, title TEXT, score INTEGER)")
now = datetime.utcnow().isoformat()
con.executemany("INSERT INTO hot VALUES (?,?,?,?)",
[(now, x["id"], x["title"], x["score"]) for x in items])
con.commit()
con.close()
if __name__ == "__main__":
save(fetch())
cron 是 0 * * * * /usr/bin/python3 /home/me/fetch.py >> /home/me/fetch.log 2>&1。
為什麼這樣做:熱榜本質是低頻聚合,沒必要開 websocket 長連線;SQLite 單檔夠用,備份就是複製檔案。代價是每次都是全量拉,無法增量,但 120 條的成本可以接受。
哪裡會失效:第一,429 不是程式錯誤,是對方限流,我的重試邏輯只處理了狀態碼,沒讀 Retry-After,凌晨三點照樣硬打三次。第二,datetime.utcnow() 在跨日對比時和本地時區混用,趨勢圖有天出現兩條重複曲線。第三,VPS 記憶體小,SQLite 併發寫入時偶爾 database is locked,後來加了 PRAGMA journal_mode=WAL 才穩。
我後來把 cron 改成 17 * * * *,避開整點,並在 429 時睡 Retry-After 秒再試。
你們抓這類熱榜 API 時,是怎麼判斷「該退讓」還是「該換來源」的?有沒有遇過限流後隔天恢復、但資料已經斷一小時的補救做法?
0
赞同度 100% · 0 条评论 · 1 阅读
0 条评论
还没有评论,写下第一条。