黑五季捡漏实战:30 分钟写一个 Python 促销价格监控脚本

黑五季捡漏实战:30 分钟写一个 Python 促销价格监控脚本

为什么需要价格监控

促销季(VPS 行业的黑五、万圣节、双十一都是)有个共同特点:价格和库存一天能变好几次。商家先放出一批特价款,卖完下架;半夜悄悄补货;临近大促又调一波价格。靠人肉刷页面,要么错过、要么把时间全搭进去。

解决办法是写个小脚本替你盯:定时抓取目标页面,提取出价格数字,跟上一次的快照比对,有涨跌就告警。原理只有四步——抓取、提取、比对、通知,全文代码 70 行左右,我在本地真实跑通过,输出原样贴出。

前置知识:会用 pip 装包、知道 cron 是定时任务;Python 3.10 以上。

设计思路

  1. 抓取:用 requests 把促销页 HTML 拿下来;
  2. 提取:用正则从 HTML 里抠出价格数字(比如 USD 16.99);
  3. 比对:把每次的价格存进一个 JSON 快照文件,下次运行时对比;
  4. 告警:降价/涨价打印 [ALERT] 行并返回退出码 1,方便定时任务和外部监控对接。

三个细节:目标之间加 1 秒礼貌间隔,别把人家站点当压测靶;正则匹配失败单独报 [WARN](往往是页面改版了);--reset 参数可清空快照重建基线。

环境准备

pip install requests

官方文档:requests 官方文档。

完整代码

把下面代码存为 price_watcher.py,把 TARGETS 换成你真正想盯的促销页 URL 和对应的价格正则:

#!/usr/bin/env python3
"""促销价格变动监控:抓取目标页面 -> 提取价格 -> 与上次快照比对 -> 有变动输出告警。
依赖:pip install requests
用法:python3 price_watcher.py            # 正常检查
     python3 price_watcher.py --reset    # 清空快照重新建基线
退出码:0=正常或首次建基线,1=检测到价格变动
"""
import json, re, sys, time
from pathlib import Path
import requests

# ---------------- 配置区 ----------------
TARGETS = [
    # name: 别名; url: 监控的页面; pattern: 提取价格的正则(第一个捕获组为价格)
    {"name": "万圣节特价款", "url": "https://example.com/halloween-sale",
     "pattern": r"USD\s*([\d.]+)"},
    {"name": "闪购专区", "url": "https://example.com/flash-sale",
     "pattern": r"\$\s*([\d.]+)"},
]
STATE_FILE = Path("state.json")          # 快照存档,跟脚本放同一目录
TIMEOUT = 15                              # 单次请求超时(秒)
HEADERS = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) price-watcher/1.0"}
# ----------------------------------------

def fetch_price(t):
    r = requests.get(t["url"], headers=HEADERS, timeout=TIMEOUT)
    r.raise_for_status()
    m = re.search(t["pattern"], r.text)
    if not m:
        return None, "页面抓到了,但正则没匹配到价格(页面结构可能变了)"
    return float(m.group(1)), None

def load_state():
    if STATE_FILE.exists():
        return json.loads(STATE_FILE.read_text(encoding="utf-8"))
    return {}

def main():
    if "--reset" in sys.argv and STATE_FILE.exists():
        STATE_FILE.unlink()
    state = load_state()
    changed = False
    lines = []
    for t in TARGETS:
        price, err = fetch_price(t)
        if err:
            lines.append(f"[WARN] {t['name']}: {err}")
            continue
        old = state.get(t["name"])
        if old is None:
            lines.append(f"[INIT] {t['name']}: 首次记录, 基线价格 {price}")
        elif abs(price - old) > 1e-9:
            arrow = "降价" if price < old else "涨价"
            pct = (price - old) / old * 100
            lines.append(f"[ALERT] {t['name']}: {arrow}! {old} -> {price} ({pct:+.1f}%)")
            changed = True
        else:
            lines.append(f"[OK] {t['name']}: 无变动 ({price})")
        state[t["name"]] = price
        time.sleep(1)  # 礼貌间隔
    STATE_FILE.write_text(json.dumps(state, ensure_ascii=False, indent=2), encoding="utf-8")
    print("\n".join(lines))
    return 1 if changed else 0

if __name__ == "__main__":
    sys.exit(main())

真实运行输出

我在本地搭了两个模拟促销页做验证。第一次运行建基线:

[INIT] 示例促销页A: 首次记录, 基线价格 16.99
[INIT] 示例促销页B: 首次记录, 基线价格 49.0

接着把两个页面的价格分别改成降价和涨价,再跑一次:

[ALERT] 示例促销页A: 降价! 16.99 -> 12.99 (-23.5%)
[ALERT] 示例促销页B: 涨价! 49.0 -> 59.0 (+20.4%)

退出码为 1。无变动时输出 [OK]、退出码 0。--reset 可清空快照重新建基线,四条路径全部实测通过。

定时运行:每 30 分钟查一轮

Linux 上用 cron 就够了。crontab -e 加一行:

*/30 * * * * cd /path/to/script && /usr/bin/python3 price_watcher.py >> watcher.log 2>&1

想收到即时提醒,可以把告警行接出去:最省事的是 Telegram Bot API 发一条消息(建个 bot、拿到 token,给自己发 sendMessage 请求只需几行代码);不讲究实时性的话,[ALERT] 行写进日志、每天扫一眼也行。退出码为 1 的设计就是为了方便接 Uptime Kuma 这类外部监控——把它当成一次"检查",非 0 即告警。

同系列:买到机器之后,可以再看一台 VPS 自己管:用 60 行 Python 写个巡检脚本,磁盘内存端口全盯住,把"盯价格"和"盯机器"配成一套。促销季的时间线和避坑点,参考黑五季 VPS 促销全时间线。

三个坑,提前说

  1. 正则写死价格格式:商家页面一改版,正则就失效——这就是 [WARN] 分支存在的意义,收到它先去人工看一眼页面,而不是怀疑脚本坏了。
  2. 频率别太高:30 分钟一轮足够,促销页不是股票行情;5 分钟一轮容易被当成爬虫封 IP。
  3. 只盯公开促销页:需要登录、带反爬验证的页面别硬上,换个思路——很多商家有公开的促销 RSS 或邮件订阅,盯那些更稳。

结语

这个脚本的价值不在代码量,而在"把人从刷页面里解放出来"。黑五季真正的好价往往只存活几小时,有个不知疲倦的盯盘员,捡漏概率完全不一样。代码拿去改吧,TARGETS 里换上你自己的目标,今晚就能跑起来。