免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Python价格监控系统实战:从定时采集到降价提醒的完整实现

Python价格监控系统实战:从定时采集到降价提醒的完整实现 “再降价、20点全友家居 现代简约实木框架科技布沙发 2.24m 直排式一字款”如果只看文字这只是一条电商促销标题。但把它当成一个开发需求来看信息量其实不小“再降价”说明价格不是静态的“20点”说明降价有明确的时间节点。换句话说这个商品页面的价格在一个特定时间点会发生变化而如果恰好错过优惠可能就没了。这种场景放到技术人面前天然对应一个问题能不能写一套自动盯价的程序在指定时间段内轮询商品价格一旦满足“降到目标价以下”就立刻推送提醒这篇文章不是家居导购而是从这条促销标题里提取一个典型的工程需求完整演示如何从 0 到 1 搭建一个价格监控与降价提醒系统。你会看到我如何设计数据表、如何用 Python 定时采集价格、如何做降价判断和通知推送以及真实项目中更容易踩坑的地方在哪里。整个系统跑通之后你可以把它扩展成多商品监控、历史价格曲线、每日降价报表也可以接多个平台。更重要的是这个过程会涉及定时任务、数据建模、幂等推送、异常处理和部署运维是一套很完整的小型后端实践。1. 这个标题背后是一个值得自动化的问题电商平台的价格并不是恒定不变的。同一个商品在不同时间段、不同活动节点、不同账号维度下可能显示完全不同的价格。促销标题里经常出现“再降价”“20点”“限时秒杀”这类关键词本质上是在强调两点价格会变。变化发生在特定时间点。对消费者来说这带来一个真实痛点人不可能 24 小时盯着商品页面。尤其是工作日的 20 点很多人还在通勤、做饭或加班等想起来去看的时候价格可能已经恢复原价。对于同时关注多个商品、多个平台的人来说人工盯价的成本更高几乎不可能持续。对这个场景做抽象它其实是一个典型的事件驱动型信息监控系统定时获取商品价格数据。把价格变化历史保存下来。根据用户设定的目标价或降价幅度做判断。满足条件时把消息推送到手机、钉钉、企业微信或邮箱。这套逻辑用代码实现并不复杂但要做到稳定、可靠、不重复通知需要认真处理几个工程细节。如果你正准备接触 Python 爬虫、定时任务、数据存储或消息通知这个项目是一个很好的练手题目。我的核心判断是这个需求的技术难点不在“请求接口”这一步而在于数据如何组织、判断逻辑如何设计、通知如何防止重复以及程序挂了之后如何自动恢复。2. 价格监控系统的整体架构与核心概念先看整体架构。一个最小可用的价格监控系统可以分成四层层级作用本项目的实现数据采集层获取商品价格Python 脚本通过 HTTP 接口拉取价格数据存储层保存商品信息、价格历史、监控规则SQLite 数据库规则判断层根据目标价或历史价格判断是否降价Python 条件判断通知推送层把降价消息发送给用户钉钉/企业微信机器人 Webhook这个架构和大部分业务系统的分层思路一致。先采集数据再落库再做判断最后触发通知。每一层都可以独立替换比如采集层换成爬虫解析 HTML存储层换成 MySQL通知层换成邮件或短信逻辑都不受影响。这里有必要解释几个容易混淆的概念SKU商品的最小库存单位通常是一个唯一编码。价格监控必须以 SKU 为粒度而不是以商品名为粒度否则同一个商品的不同规格会互相干扰。价格历史每次采集到的价格都应该单独存一条记录。只有存了历史价格才能判断“当前是不是历史最低价”或“较上次采集降了多少”。目标价用户设定的心理价格低于这个价格就通知。也可以用降价幅度比如“低于历史最低价 5% 就通知”。幂等通知同一个 SKU、同一个触发价格只能推送一次不能每隔 5 分钟就重复打扰用户。Webhook一个 HTTP 回调地址。程序把消息 POST 到该地址钉钉、企业微信等平台就会把消息推送到群里。很多人第一次写这类系统时会把重点放在“如何解析商品页面”上结果写完发现页面改版就崩溃了。更合理的设计是先抽象出稳定的商品接口把页面解析细节隔离在一个模块里后续页面变化只需要改这一个模块。这也是我在演示中先用本地模拟接口的原因。3. 环境准备与前置条件这个项目的技术栈非常简单只需要一台能跑 Python 的电脑。以下是我的环境你可以根据自己的实际情况调整版本但思路完全一致。操作系统Windows / macOS / Linux 都可以。Python建议 3.9 或更高版本。数据库SQLite 3Python 内置支持无需额外安装。依赖库Flask、Requests、APScheduler。通知工具钉钉群机器人或企业微信群机器人可选。建议先创建虚拟环境避免依赖污染系统 Pythonmkdir price-monitor cd price-monitor python -m venv venv # Windows venv\Scripts\activate # macOS / Linux source venv/bin/activate然后安装依赖pip install flask requests apscheduler为了方便其他人复现把依赖写进requirements.txtflask3.0 requests2.31 apscheduler3.10项目目录建议如下price-monitor/ ├── app.py # 本地模拟商品价格接口 ├── db.py # 数据库初始化和操作方法 ├── collector.py # 价格采集模块 ├── notifier.py # 降价判断与通知模块 ├── scheduler.py # 定时调度入口 ├── requirements.txt └── data/ └── price_monitor.db # 运行时自动生成注意演示中使用的都是示例代码和本地接口不涉及任何真实电商平台的抓取逻辑。如果你想对接真实平台请优先使用平台官方提供的开放 API。如果没有开放 API也要先确认平台服务条款是否允许自动化访问并严格控制请求频率。4. 搭建本地模拟商品价格接口为什么第一步不是写爬虫而是先搭一个模拟接口因为真实平台的页面结构、接口签名、风控策略都非常复杂把这些因素全部放进初版教程里会淹没核心逻辑。我更推荐先在一个可控的本地环境里把整个监控链路跑通之后再替换数据源。这里用 Flask 写一个非常简单的商品价格接口。它返回一个固定的商品 SKU、商品名称和当前价格并且为了让监控逻辑能观察到变化每次请求时价格会随机小幅波动。# 文件路径price-monitor/app.py from flask import Flask, jsonify import random app Flask(__name__) # 模拟商品数据示例价格仅用于技术演示不代表实际售价 products { P001: { name: 全友家居 现代简约实木框架科技布沙发 2.24m 直排式一字款, price: 3999.0, }, P002: { name: 全友家居 简约布艺单人沙发, price: 1999.0, }, } app.route(/api/product/sku) def get_product(sku): if sku not in products: return jsonify({code: 404, msg: product not found}), 404 product products[sku] # 模拟价格波动每次请求可能降价 0~50 元 current_price round(product[price] - random.randint(0, 50), 2) return jsonify({ code: 0, data: { sku: sku, name: product[name], price: current_price, }, }) if __name__ __main__: app.run(host127.0.0.1, port5000, debugTrue)启动服务python app.py打开另一个终端用 curl 验证接口curl http://127.0.0.1:5000/api/product/P001预期返回结果类似{ code: 0, data: { sku: P001, name: 全友家居 现代简约实木框架科技布沙发 2.24m 直排式一字款, price: 3985.0 } }这个接口返回的数据格式是稳定的外层有code和datadata里有sku、name、price三个字段。这样的设计让采集模块可以忽略页面结构直接按 JSON 解析。在实际项目中如果平台提供了开放 API返回结构通常也是类似的 JSON 格式这一层可以平滑替换。需要注意我在这里没有引入任何登录、Cookie、加密参数等复杂机制。因为学习重点是监控系统的整体流程而不是如何逆向某个平台的签名算法。把数据源做干净后续所有逻辑都能集中在核心业务上。5. 设计数据表商品、价格历史与监控规则一个价格监控系统要长期稳定运行数据模型必须提前设计好。我建议至少准备三张表products商品基础信息表。price_history价格历史表每次采集都插入一条记录。alert_rules监控规则表记录用户目标价和通知开关。创建数据库的脚本放在db.py中# 文件路径price-monitor/db.py import sqlite3 import os DB_PATH os.path.join(data, price_monitor.db) def get_conn(): 获取数据库连接并开启外键约束 os.makedirs(os.path.dirname(DB_PATH), exist_okTrue) conn sqlite3.connect(DB_PATH) conn.row_factory sqlite3.Row conn.execute(PRAGMA journal_modeWAL;) return conn def init_db(): 初始化数据表结构 conn get_conn() try: conn.executescript( CREATE TABLE IF NOT EXISTS products ( sku TEXT PRIMARY KEY, name TEXT NOT NULL, url TEXT, created_at TEXT NOT NULL DEFAULT (datetime(now, localtime)) ); CREATE TABLE IF NOT EXISTS price_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, sku TEXT NOT NULL, price REAL NOT NULL, check_time TEXT NOT NULL DEFAULT (datetime(now, localtime)), UNIQUE(sku, check_time) ); CREATE TABLE IF NOT EXISTS alert_rules ( sku TEXT PRIMARY KEY, target_price REAL, notify_enabled INTEGER NOT NULL DEFAULT 1, last_notify_price REAL ); ) conn.commit() finally: conn.close() def upsert_product(sku, name, url): 写入或更新商品基础信息 conn get_conn() try: conn.execute( INSERT INTO products(sku, name, url) VALUES(?, ?, ?) ON CONFLICT(sku) DO UPDATE SET name excluded.name, url excluded.url , (sku, name, url), ) conn.commit() finally: conn.close() def insert_price(sku, price): 插入一条价格记录同一秒重复采集会忽略 conn get_conn() try: conn.execute( INSERT OR IGNORE INTO price_history(sku, price) VALUES(?, ?) , (sku, price), ) conn.commit() finally: conn.close() def get_latest_price(sku): 查询某个商品最新一次价格 conn get_conn() try: row conn.execute( SELECT price FROM price_history WHERE sku ? ORDER BY check_time DESC, id DESC LIMIT 1 , (sku,), ).fetchone() return row[price] if row else None finally: conn.close() if __name__ __main__: init_db() print(数据库初始化完成)这里有三个设计细节值得展开解释。第一price_history表加了唯一约束UNIQUE(sku, check_time)并且插入时使用INSERT OR IGNORE。这可以避免定时任务被重复触发时写入完全相同的记录属于数据层面的幂等保护。第二alert_rules表中的last_notify_price字段是关键。它记录上一次通知时的价格判断逻辑中用“当前价格是否等于最近一次通知价格”来避免重复推送。这比在内存里保存状态更可靠因为程序重启后也不会丢失。第三写入商品信息使用ON CONFLICT DO UPDATE保证同一个 SKU 不会产生多行数据商品名称更新时也能自动同步。这在商品标题变化时很有用。运行下面的命令完成初始化python db.py你会看到目录data/下生成price_monitor.db文件。SQLite 的好处是单文件即可存储全部数据方便备份和迁移缺点是并发写能力有限但作为个人监控工具完全够用。6. 价格采集模块把接口数据写入数据库有了模拟接口和数据表之后下一步就是写采集模块。采集模块要完成三件事请求商品接口、解析 JSON、把商品信息和价格写入数据库。# 文件路径price-monitor/collector.py import requests from db import upsert_product, insert_price BASE_URL http://127.0.0.1:5000 def fetch_product(sku): 调用商品接口返回解析后的字典 url f{BASE_URL}/api/product/{sku} resp requests.get(url, timeout10) resp.raise_for_status() data resp.json() if data.get(code) ! 0: raise RuntimeError(f接口返回异常: {data}) product_data data[data] return { sku: product_data[sku], name: product_data[name], price: float(product_data[price]), } def collect_price(sku): 采集单个商品价格并入库 product fetch_product(sku) upsert_product(skuproduct[sku], nameproduct[name]) insert_price(skuproduct[sku], priceproduct[price]) print(f[采集完成] {product[sku]} 当前价格: {product[price]}) return product if __name__ __main__: # 单次执行示例 import sys sku sys.argv[1] if len(sys.argv) 1 else P001 collect_price(sku)这段代码的逻辑很清楚但有几个需要特别注意的地方。resp.raise_for_status()会在 HTTP 状态码非 200 时抛出异常。这是最简单的错误处理能避免拿到错误页面后继续解析。实际项目中还应该加上超时后的重试机制比如连续失败 3 次才真正告警因为网络抖动是很常见的问题。解析 JSON 时我判断了最外层code字段。这是很多接口约定俗成的返回格式但不同平台的格式不一定相同。写采集模块时最重要的一步是先确认接口返回结构再针对性地写解析逻辑不要假设所有接口都一样。运行单次采集python collector.py P001预期输出[采集完成] P001 当前价格: 3968.0此时可以查看数据库中的价格记录sqlite3 data/price_monitor.db select * from price_history;如果没有安装 sqlite3 命令行工具也可以写一个简单的查询脚本或者用 DB Browser for SQLite 这类图形化工具查看。看到每次运行都产生一条价格记录说明采集链路已经通了。7. 降价判断与通知模块采集到价格之后还需要判断“要不要提醒用户”。这一步需要同时参考用户设置的目标价和历史价格趋势。我的通知判断逻辑设计如下如果alert_rules中配置了target_price则当前价格低于目标价时触发。如果没有配置目标价则与历史最低价比较当当前价格刷新历史新低时触发。如果last_notify_price等于当前价格说明这个价格已经通知过跳过避免重复打扰。通知方式我选择 Webhook因为钉钉、企业微信、飞书、Server酱等都支持这种推送形式。下面以钉钉群机器人为例展示一个通用实现。# 文件路径price-monitor/notifier.py import os import requests from db import get_conn # 这里只是示例真实使用时请从环境变量读取不要硬编码到代码里 DINGTALK_WEBHOOK os.getenv(DINGTALK_WEBHOOK, https://oapi.dingtalk.com/robot/send?access_tokenyour_token) def get_lowest_price(sku): 查询某个商品历史最低价 conn get_conn() try: row conn.execute( SELECT MIN(price) AS min_price FROM price_history WHERE sku ? , (sku,), ).fetchone() return row[min_price] if row and row[min_price] is not None else None finally: conn.close() def send_dingtalk_message(title, text): 推送消息到钉钉群机器人 if not DINGTALK_WEBHOOK or your_token in DINGTALK_WEBHOOK: print([推送] 未配置有效的 Webhook跳过推送) return payload { msgtype: markdown, markdown: { title: title, text: text, }, } resp requests.post(DINGTALK_WEBHOOK, jsonpayload, timeout10) resp.raise_for_status() print(f[推送成功] {title}) def check_and_notify(sku, current_price, product_name): 根据监控规则判断是否需要推送降价提醒 conn get_conn() try: rule conn.execute( SELECT target_price, notify_enabled, last_notify_price FROM alert_rules WHERE sku ? , (sku,), ).fetchone() finally: conn.close() # 默认开启通知没有规则时也允许用历史最低价兜底 notify_enabled True target_price None last_notify_price None if rule is not None: notify_enabled bool(rule[notify_enabled]) target_price rule[target_price] last_notify_price rule[last_notify_price] if not notify_enabled: return lowest_price get_lowest_price(sku) should_notify False reason if target_price is not None and current_price target_price: should_notify True reason f低于目标价 {target_price} 元 elif lowest_price is not None and current_price lowest_price: should_notify True reason f刷新历史最低价之前最低 {lowest_price} 元 else: # 没有目标价、也没有历史记录的极端情况 if target_price is None and lowest_price is None: should_notify True reason 首次采集到价格 if not should_notify: print(f[无需通知] {sku} 当前价格 {current_price}) return if last_notify_price is not None and abs(last_notify_price - current_price) 0.01: print(f[跳过重复通知] {sku} 当前价格 {current_price} 已通知过) return title f{product_name} 降价提醒 text ( f### {product_name}\n\n f- 当前价格**{current_price}**\n f- 提醒原因{reason}\n f- SKU{sku}\n ) send_dingtalk_message(title, text) # 更新最近一次通知价格防止下次重复推送 conn get_conn() try: conn.execute( INSERT INTO alert_rules(sku, target_price, notify_enabled, last_notify_price) VALUES(?, ?, 1, ?) ON CONFLICT(sku) DO UPDATE SET last_notify_price excluded.last_notify_price , (sku, target_price, current_price), ) conn.commit() finally: conn.close()这段代码的精髓在最后一步无论推送是否真正发出都会更新last_notify_price。这里存在一个取舍如果推送失败但已记录last_notify_price下次就不会再推可能漏掉重要提醒。更严谨的做法是先推送成功后再更新已通知价格或者记录一个notify_status字段由后台重试任务处理失败消息。从工程角度我更推荐把“判断是否触发”和“发送通知”解耦。触发条件成熟后先写入一个notify_tasks表再由单独的工作线程消费并发送。这样即使 Webhook 临时不可用通知任务也不会丢失。在初版设计中为了控制复杂度我暂时把它们放在同一个函数里但你在生产环境中应该考虑拆开。8. 用 APScheduler 实现定时监控采集和通知模块都写好之后还差一个“定时执行”的能力。这里用 APScheduler 是最简单的方案它支持按固定间隔、固定时间点、Cron 表达式等多种调度方式。针对“再降价、20点”这类场景我们可以这样设计调度策略平时每 5 分钟检查一次如果希望在整点更密集地监控可以额外注册一个 cron 任务在每日 19:55 到 20:05 之间每 30 秒检查一次。# 文件路径price-monitor/scheduler.py from apscheduler.schedulers.blocking import BlockingScheduler from collector import collect_price from notifier import check_and_notify SKUS [P001, P002] def monitor_job(): 定时执行价格采集和通知判断 for sku in SKUS: try: product collect_price(sku) check_and_notify( skuproduct[sku], current_priceproduct[price], product_nameproduct[name], ) except Exception as exc: # 单个商品失败不应该影响整个任务 print(f[任务异常] {sku}: {exc}) if __name__ __main__: scheduler BlockingScheduler() # 每 5 分钟执行一次 scheduler.add_job( monitor_job, interval, minutes5, idmonitor_5min, max_instances1, coalesceTrue, ) # 针对活动节点每天 19:50 到 20:10 之间每 30 秒执行一次 scheduler.add_job( monitor_job, cron, hour19, minute50, second*/30, idmonitor_activity, max_instances1, coalesceTrue, ) print(价格监控调度器已启动按 CtrlC 退出) scheduler.start()这里两个参数很关键max_instances1表示同一个任务在上一次未跑完时不允许并发执行第二个实例coalesceTrue表示如果积压了多次执行只合并执行一次。两者都是为了保护系统不受任务堆积影响。启动调度器python scheduler.py运行后你可以同时启动模拟接口观察调度器每 5 分钟自动打印采集信息。如果价格随机波动触发历史新低还会产生推送日志。生产环境不建议直接在前台运行这个进程。更稳定的方式是用 systemd、Docker restart 策略或 Kubernetes CronJob 来托管。下面是一个简单的 Docker 启动思路# 文件路径price-monitor/Dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD [python, scheduler.py]构建并启动docker build -t price-monitor . docker run --name price-monitor --restartalways -d price-monitor这样即使服务器重启容器也会自动恢复。注意容器内需要能访问模拟接口如果模拟接口也运行在宿主机上启动容器时要加--networkhost或用容器名访问。9. 完整运行与效果验证跑通整个系统后你应该验证的不只是“程序能跑”而是“监控链路是否真的闭环”。建议按以下顺序验证。第一步确认模拟接口正常curl http://127.0.0.1:5000/api/product/P001第二步初始化数据库python db.py第三步手动执行一次采集和通知判断python collector.py P001第四步启动定时调度器python scheduler.py第五步等待 5 分钟后查看数据库中的价格记录sqlite3 data/price_monitor.db \ select sku, price, check_time from price_history order by check_time desc limit 10;预期你会看到多条价格记录时间间隔约为 5 分钟。每次价格都来自模拟接口数值会有小幅波动。第六步验证通知逻辑。最简单的方式是把模拟接口的价格波动范围调大例如每次随机降价 0 到 200 元这样更容易触发“刷新历史最低价”条件。在app.py中把random.randint(0, 50)改成random.randint(0, 200)重启服务后再跑调度器观察日志[采集完成] P001 当前价格: 3788.0 [无需通知] P001 当前价格 3788.0 [采集完成] P001 当前价格: 3712.0 [无需通知] P001 当前价格 3712.0 [采集完成] P001 当前价格: 3666.0 [推送成功] 全友家居 现代简约实木框架科技布沙发 2.24m 直排式一字款 降价提醒看到“推送成功”或“无需通知”的轮换输出说明判断逻辑已经生效。如果配置了真实的钉钉 Webhook群里会收到 markdown 消息。第七步验证幂等。连续跑两次采集如果当前价格没有继续降低第二次应该输出[跳过重复通知] P001 当前价格 3666.0 已通知过这说明系统不会对同一价格重复打扰用户。整个验证过程其实就是在回答三个问题数据有没有采到、判断有没有触发、通知有没有投递。任何一个环节失败都先对着这个链路去找问题不要一开始就怀疑底层框架。10. 常见问题与排查思路我在实际写这类监控工具时几乎每跑一段时间都会遇到下面这些问题。这里整理成一张排查表。问题现象可能原因排查方式解决方案调度器启动后没有任何日志Flask 服务未启动或接口地址写错先 curl 接口确认能访问启动app.py检查BASE_URL请求接口超时网络波动或服务响应慢查看异常堆栈确认是否 requests 超时增加 timeout 参数并加指数退避重试SQLite 数据库被锁多任务并发写库看是否出现database is locked改用 WAL 模式或限制调度器max_instances1重复收到降价通知last_notify_price没有正确写入查询alert_rules表看字段值确保通知成功后执行 upsert价格一直不变模拟接口随机波动范围太小多次 curl 查看返回值调大随机波动范围或检查采集模块是否拿到同一份数据程序退出后任务消失前台进程被关闭检查进程状态用 Docker--restartalways或 systemd 托管Webhook 推送失败机器人 token 失效或网络不通手动用 curl POST 测试查看返回错误码重新生成 token接口返回结构变化平台页面或接口改版打印原始响应 body解析前先做格式校验避免 KeyError单商品异常导致整批任务中断没有捕获局部异常看日志是否中断用try/except包裹单个商品处理逻辑这些坑都不是复杂技术但如果不注意会让人花掉大量时间。最有效的排查方式永远是先看日志再复现单次调用最后才去检查配置。11. 安全、合规与工程实践建议关于商品价格监控网上很多教程会把“爬取某个电商网站”作为核心卖点但在实际项目中我强烈建议你遵循几个原则避免把工具变成风险源。第一优先使用官方开放 API。很多平台都有商品信息开放接口只要合法申请就能获得稳定的数据来源。页面解析是最后的选择因为它不仅违反平台服务条款的风险还需要应对反爬机制、页面改版、验证码等问题维护成本极高。第二只采集公开数据不碰账号体系。需要登录才能看到的内容原则上就不适合自动化采集。即使技术上能做到也应该意识到这已经越过了服务边界。如果平台要求登录才能查看价格更合理的做法是放弃监控或者改成手动查看。第三控制请求频率。个人监控建议间隔不低于 5 分钟。频繁请求会给对方服务器带来压力也可能导致自己的 IP 被限制。真正的秒杀抢购类自动化不在本文讨论范围内这类行为既可能违反平台规则也可能涉及不正当交易风险。第四不要在代码中硬编码密钥。Webhook token、数据库密码等敏感信息要放到环境变量或密钥管理服务里。如果代码仓库是公开的硬编码密钥等于把通知渠道彻底暴露。第五做好数据备份。SQLite 数据库就是你的核心资产。可以每天用定时任务把数据库文件复制到备份目录或定期执行 SQL 导出。第六关注日志与监控。采集系统本身也需要被“监控”。建议把每一次采集、每一次通知都记录结构化日志并设置一个“连续多次失败”则告警的兜底策略否则当它静默挂掉时你并不会第一时间知道。第七也是最重要的一点这类工具应该定位为“价格提醒”而不是“价格抢占”。它帮助你在合适的时机看到值得关注的降价信息最终交易仍然应该由你自己判断。12. 总结与后续扩展方向回到最开始那条促销标题“再降价、20点”。如果只看商品页你看到的是一个价格变化结果但如果你把它抽象成一条消息价格是数据20 点是时间触发条件这就是一个信息自动化要解决的基本问题。这篇文章带着你从零搭建了一个价格监控与降价提醒系统先用 Flask 搭建可复现的本地模拟接口再设计 SQLite 数据表随后实现采集、通知、定时调度四个模块最后完成验证和排错。这套代码虽然简朴但架构上是完整的可以迁移到很多实际场景。如果你想继续深入我建议按下面几个方向扩展增加 Web 管理界面用 Flask 展示商品列表、价格曲线和通知记录。用 MySQL 替换 SQLite支持更大的数据量和并发查询。把“采集”和“通知”拆成两个独立服务用 Redis 或消息队列连接提升可靠性。增加用户配置页面让使用者可以自助设置目标价。把历史价格数据导出用来分析商品在不同促销节点的价格规律。最后给你一个实用建议先跑通本文的本地演示理解整个架构后再去考虑接入真实数据源。任何时候都要把合规与安全放在第一位。价格监控本身不是目的帮助你在合适的时间做出合适的选择才是这套系统真正的价值。
返回列表