做电商比价系统这个想法我一开始以为核心难点在爬虫。等真正动手做完这套基于 Flask 与 Python 的多平台电商比价可视化系统我才反应过来爬数据只是地基真正费精力的是把不同平台千奇百怪的商品信息拉到同一个坐标系里比较再把比较结果用图表和自然语言讲清楚。这篇文章就按我实际开发的顺序把 Selenium 采集、数据对齐、Flask 可视化、以及最后接入 DeepSeek 大模型做智能问答的全过程拆开讲一遍。如果你正准备做类似的毕业设计或者单纯想给自己写一个顺手的价格监控工具这篇文章应该能帮你省掉不少试错时间。1. 为什么做比价系统而不是只想做一个爬虫1.1 这个项目真正要解决的需求很多人在网上看到一个商品习惯性会开两三个平台去搜同款来回切换标签页比价格、比运费、看评价。这个动作看起来很简单但一旦商品数量上去了人就比不过机器了。比价系统的本质是把人肉比价这个重复劳动自动化定时抓取各平台的商品信息统一清洗、对齐、存储最后用可视化看板和自然语言问答把结论推给用户。这套系统的使用场景主要有三个。第一是个人购物决策搜一个商品名立刻能看到各平台价格横评和历史价格曲线判断现在是不是入手的好时机。第二是行情监控比如盯着一款热门电子产品价格跌破某个心理价位自动提示。第三是作为数据展示项目完整跑通采集、存储、分析、可视化、智能问答的链路这比纯写一个增删改查管理系统要有说服力得多也是很多毕业设计选题喜欢往这个方向靠的原因。1.2 技术选型为什么是 Flask Selenium MySQL选型这件事我在动手前花了不少时间权衡最后定下来 Flask、Selenium、MySQL 三者组合理由其实很简单各选各领域里最省心的方案。后端框架没有选 Django也没有追新用 FastAPI。Django 功能全但 ORM、中间件、Admin 后台这些东西对比价系统来说有点重学习成本全堆在框架本身FastAPI 性能好、写起来爽但异步模型对新手不友好而且市面上能找到的参考项目相对少。Flask 刚好卡在中间轻量、灵活、文档多、任何报错基本都能搜到对应解决方案。对一个要写完整论文、又要现场演示的项目来说可维护性和可解释性比极致性能重要得多。爬虫这块没有选 Requests 解析接口的方案而是直接用 Selenium。现在主流电商平台的前端基本都是重度动态渲染接口层普遍有签名加密直接构造 HTTP 请求的维护成本极高一天可能就要改一次参数碰上传参反爬直接卡死。Selenium 模拟的是完整浏览器行为几乎不存在拿不到页面的情况。代价是速度和资源占用但对毕业设计级别的数据量来说每天跑一轮几百个商品完全在可接受范围内。存储用的是 MySQL没有上 MongoDB 或者其他时序数据库。商品信息、价格记录、用户行为这些都是结构化数据用关系型数据库做关联查询很顺手而且后面做历史价格趋势查询时MySQL 的索引优化空间足够不需要额外引入一套大数据组件把架构搞复杂。等数据量真的到了百万级再考虑迁移也不迟。1.3 系统模块划分与数据流整个系统我拆成了五个模块每个模块职责单一、边界清晰采集层Selenium 驱动的多平台爬虫按任务队列抓取商品列表页和详情页信息。数据层MySQL 数据库包含商品表、价格历史表、采集任务表、平台配置表。服务层Flask 提供 RESTful API负责搜索、比价、趋势、排行榜等业务逻辑。展示层基于 ECharts 的可视化看板展示价格对比、历史趋势、平台分布。Agent 层接入 DeepSeek 大模型把自然语言问题转成工具调用返回智能分析结论。数据流是单向的爬虫把各平台原始网页抓回来解析成结构化字段写入原始数据表清洗脚本做规格统一和字段修正进入正式商品表Flask 从库里取数并加工成前端图表需要的 JSON 结构Agent 层则通过 API 把用户的问题路由到对应查询函数拿到结果后交给大模型生成回答。这个架构的好处是每一层都能单独测试和替换比如以后想换个前端框架后端 API 不用动想加一个平台只需要新增一个爬虫模块不用改其他任何地方。2. Selenium采集层的完整链路从环境配置到增量更新2.1 动态页面为什么绕不开 Selenium比价系统的数据源头是各平台的商品页面。很多人会问为什么不用 Requests 直接拿 HTML问题在于现在电商页面基本都是动态渲染的商品价格、促销信息、库存状态这些关键数据很多是通过 JavaScript 在页面加载后才从接口拉到前端渲染出来的。直接请求 HTML 只能拿到一个空壳子关键词和部分静态描述还能看到价格、销量这类核心字段大概率是空的或者占位符。用 Selenium 就绕开了这个问题。它启动一个真实浏览器内核页面里所有 JavaScript 正常执行最终渲染出来的 DOM 树就是用户看到的样子爬虫只需要在正确的时机去提取文本就行。这也是 Selenium 这类浏览器自动化工具在竞对监控、比价采集场景里经久不衰的根本原因——它能模拟最真实的用户访问路径而不是伪造一个简单的 HTTP 请求。2.2 无头浏览器的关键配置与反检测经验Selenium 配置本身不难难的是让它不被检测出来。直接用一个默认配置启动 Chrome明文写着webdrivertrue很多平台识别到自动化特征后会直接弹验证码或者返回一个空列表页。我实际使用的核心配置分三层每一层都有对应的意图第一层是启动参数。强制走无头模式--headlessnew但记得保留 GPU 和沙箱相关设置否则部分页面渲染会异常。设置窗口大小因为有些页面布局会根据视口宽度改变 DOM 结构固定成一个常规笔记本分辨率可以避免解析错位。加上--disable-blink-featuresAutomationControlled这是关闭自动化特征标记的关键参数。第二层是浏览器指纹特征。Selenium 默认的 User-Agent 会带上HeadlessChrome字样一眼假需要手动设置一个常规 Chrome UA。同时固定 viewport 尺寸、时区、语言形成一套前后一致的身份。我自己踩过的一个坑是UA 改成了正常的但时区没改页面上的推荐算法立刻发现异常导致滑动验证码出现频率明显上升。第三层是行为模拟。所有请求之间加随机延时延时范围控制在 2 到 5 秒之间模仿真实用户浏览节奏。鼠标轨迹这个我试过意义不大还拖慢速度最后只做随机滚动页面。这里要特别克制的是请求频率宁可采集速度慢一点也不要让目标平台产生明显的压力。合规、长效地采集远比一次性抓取来得有价值。以下是经过实践验证的核心配置代码from selenium import webdriver from selenium.webdriver.chrome.options import Options import random import time def get_browser(): options Options() options.add_argument(--headlessnew) options.add_argument(--disable-gpu) options.add_argument(--no-sandbox) options.add_argument(--disable-blink-featuresAutomationControlled) options.add_argument( user-agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 ) options.add_argument(--window-size1920,1080) options.add_argument(--langzh-CN) options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) driver webdriver.Chrome(optionsoptions) driver.execute_cdp_cmd(Page.addScriptToEvaluateOnNewDocument, { source: Object.defineProperty(navigator, webdriver, {get: () undefined}) }) return driver def random_delay(): time.sleep(random.uniform(2, 5))这段配置里最容易被忽略的是最后那个execute_cdp_cmd它通过 Chrome DevTools 协议在页面加载前注入脚本把 navigator.webdriver 属性改掉。很多反爬体系就是靠这一个字段区分真人用户和自动化工具的实测加上它之后验证码出现频率降了一个数量级。2.3 每个平台一套解析器多平台采集的架构设计多平台采集最容易犯的错误是想写一个万能解析器一次适配所有平台。实际情况是每个平台的 DOM 结构、类名命名、数据埋点完全不一样甚至同一个平台的不同页面类型搜索页、详情页、活动页之间也没有复用性。我最终采用的架构是按平台建包、按页面类型建类每个平台一个独立解析模块spiders/ ├── base_spider.py # 公共基类URL构建、请求、字段容器 ├── platform_a/ │ ├── search_parser.py # 搜索列表页解析器 │ └── detail_parser.py # 商品详情页解析器 ├── platform_b/ │ ├── search_parser.py │ └── detail_parser.py └── common/ ├── utils.py # 价格解析、时间格式化 └── constants.py # 各平台字段映射常量每个解析器的核心任务就是把页面 DOM 里的文本信息转成统一的字段结构。这里有一个很关键的工程细节不要把解析逻辑和采集逻辑混在一起。采集逻辑打开页面、滚动、等待放在基类或者公共方法里解析逻辑提取标题、价格、销量放在各平台的 Parser 类里。这样某个平台的页面改版了只需要改对应平台的解析器不会影响其他模块。商品详情页解析时还要额外处理几个异常分支价格被隐藏部分平台对未登录用户隐藏价格、促销标签导致价格文本结构变化、商品 SKU 有多个档位。处理方案是先定位主体价格区域再通过区域内的结构化标签区分当前价、原价、促销价拿不到完整 SKU 内容时至少记录默认展示的档位价格并打上标识。2.4 断点续采与增量更新让采集任务跑起来不用管采集任务一旦跑起来中断几乎是必然的网络超时、页面改版、反爬验证码弹出、数据库连接断开、服务器重启。如果每次断掉都要从头开始抓那这套系统就没有实用价值了。我的方案是建一张采集任务表把采集单元从一个平台细化到一个商品在某个平台的某个页面。每次启动采集时优先取状态为失败或者上一次运行时间过久的任务实现断点续采。核心表结构如下字段类型说明idINT 自增任务主键platformVARCHAR平台标识item_keyVARCHAR商品唯一标识page_urlVARCHAR待采集页面链接statusTINYINT0待采集1成功2失败retry_countINT失败重试次数last_attempt_atDATETIME最后尝试时间增量更新策略分两个层次。第一层是定时任务我用系统自带的定时任务每天凌晨跑一轮全量更新重点刷新价格和库存字段。第二层是变化检测对历史价格记录做比对当天价格与上次记录偏差超过阈值时才写入新的价格快照避免每天都存一堆无意义的数据。价格变化检测的代码如下def save_price_snapshot(cursor, product_id, platform, current_price): cursor.execute( SELECT price FROM price_history WHERE product_id %s AND platform %s ORDER BY record_time DESC LIMIT 1, (product_id, platform) ) row cursor.fetchone() if not row or abs(row[price] - current_price) 0.01: cursor.execute( INSERT INTO price_history (product_id, platform, price, record_time) VALUES (%s, %s, %s, NOW()), (product_id, platform, current_price) ) # 价格变化超过5%时记录一条提醒 if row and abs(row[price] - current_price) / row[price] 0.05: insert_price_alert(product_id, row[price], current_price)3. 价格数据和商品对齐比价的真正难点不在爬而在比3.1 数据清洗让人看懂的数据才能让程序看懂爬虫能抓到数据但抓到的原始数据几乎都脏。不同平台的字段格式五花八门不处理干净后面的分析和展示全是错的。第一个要解决的是价格字段。有些平台显示¥1,999.00有些显示1999元起还有一些直接把活动价和划线价渲染在同一个元素里。统一的做法是用正则提取数字和符号再根据平台标识确定是否需要乘 10000有些平台用分做单位最后统一为 Decimal 类型存储。这个坑我在前期栽过跟头默认字符串一路存到 MySQL结果可视化阶段排序全部错乱因为数据库按字典序排列。第二个是标题清洗。电商标题最爱干的事就是堆砌促销前缀比如官方旗舰店、赠品信息、物流说明。要对齐同款商品这些噪声词必须去掉。我的处理方式不是简单替换而是维护一个停用词表做遍历过滤。这里不追求 NLP 级别的分词精度规则过滤基本够用。标题清洗代码片段import re STOP_WORDS [官方, 旗舰店, 赠品, 免运费, 顺丰包邮, 保税仓发货] def clean_title(title): if not title: return for word in STOP_WORDS: title title.replace(word, ) title re.sub(r【.*?】, , title) title re.sub(r\[.*?\], , title) return re.sub(r\s, , title).strip()3.2 同款识别一条商品在三个平台长着三张脸比价系统最核心的难题有两个其一同一个商品在不同平台的标题千差万别其二不同平台的店铺可能给商品起不同的名字。如果只按标题字符串相等匹配那基本什么都匹配不上。我采用的方案是分层的匹配策略先粗后细逐级过滤第一步做品牌级预筛选。维护一份品牌别名词典把常见的别名映射到标准名。比如某个品牌的游戏本系列在平台 A 叫天选在平台 B 叫TUF。同义词映射后通过正则把品牌和型号从清洗后的标题中抽出来作为稳定键值。第二步做配置级确认。笔记本、手机这类商品型号还不算唯一标识同一个型号可能对应不同 CPU、内存、显卡的配置组合一般通过解析标题中的规格关键词来锁定。这一步的召回率做不到 100%但能满足比价场景里 90% 以上的需求。剩下的边缘情况比如只有部分平台标注完整规格我选择保留一条记录并打上规格待确认标记避免错误匹配。第三步如果前两步都失败了再对清洗后的标题做分词计算 Jaccard 相似度设定阈值 0.7。这一步会引入少量误匹配所以还要加一道人工校验手段把模糊匹配结果挂到一个待确认列表页面由用户在后台手动合并合并结果会回写数据库后续采集自动学习。3.3 到手价与价格趋势比价算法的计算口径比价的本质不是比标价而是比到手价。不同平台的定价策略差异很大有的平台标价虚高但优惠券力度大有的平台可以跨店满减有的平台直接显示折后价。如果爬虫只抓挂架价系统报出来的最低价可能和用户最终付款金额差了十万八千里。我在系统中定义了一个统一的到手价计算模型到手价 挂牌价 - 店铺券优惠 - 平台券优惠 运费问题在于怎样获取优惠券信息。有些平台的优惠券是页面加载后异步请求得到的在 DOM 上不一定直接可见。我的处理策略是优先解析详情页内已展示的优惠标签例如满减、立减取最大值作为预估优惠没有展示优惠标签的商品默认不估计还是用挂牌价参与比价但会打上优惠未核算的标签。这样系统给出的比价结果能保证下限同时提醒用户部分数据可能存在偏差。历史价格趋势是比价系统里最容易被低估的模块。用户买一件高价商品往往不是要看今天谁便宜而是想知道现在是价格高点还是低点。为此设计了价格历史表每次采集都追加一条记录。趋势图展示近 30 天、90 天、180 天的价格曲线同时标注出历史最低价和当前价相对低点的偏离比例。这部分在论文里的价值很高因为它是纯采集数据展示层面之外真正体现数据分析能力的地方。4. Flask后端与可视化把数据库里的数字变成一张图4.1 API接口设计给前端和Agent准备数据系统后端采用 Flask 蓝图模式所有业务都通过 RESTful API 暴露。好看的页面只是一个壳核心要把接口设计得整洁、语义清晰方便前端页面和后面的大模型 Agent 调用。我最终保留了四个核心接口功能划分如下GET /api/search?keyword笔记本platformall符合关键词的商品列表支持平台筛选和排序。GET /api/compare?id1001指定商品在各平台的比价结果返回各平台价格、优惠信息、近 7 天最低价。GET /api/trend?id1001range30指定商品的历史价格趋势数据返回按天的价格序列。GET /api/rank?categorycomputersortprice_desc类目排行榜供首页展示。Flask 接口实现需要注意一个细节数据库返回的 Decimal 类型不能直接做 jsonify 序列化会报类型错误。我统一封装了一个序列化工具把 Decimal 转成浮点字符串同时把 datetime 格式化好。这个小坑很容易让第一次跑通后端的人卡个十分钟。from decimal import Decimal from datetime import datetime import json class ApiEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, Decimal): return float(obj) if isinstance(obj, datetime): return obj.strftime(%Y-%m-%d %H:%M:%S) return super().default(obj) app.json_encoder ApiEncoder4.2 可视化组件选型为什么选 ECharts可视化方案方面我对比过 ECharts 和 Plotly最终确定 ECharts原因是它在毕业设计场景里几乎是最优解。ECharts 由国内团队维护中文文档完善典型图表的官方示例非常丰富折线图、柱状图、雷达图都只需要几十行配置而且可以选用按需引入的 minimal 包前端加载体积可以控制在合理范围内。Plotly 的交互能力更强但图表样式偏重而且每次渲染都会携带较大的 JS 文件页面首屏速度不快。可视化页面总共需要四个图表模块价格对比柱状图同一商品在各平台的到手价横评柱子颜色按平台区分。历史趋势折线图近 N 天价格走势标出当前价和历史最低价。平台价格分布散点图某个类目下所有商品在不同平台的价格分布一眼看出版本差价。降价提醒列表一个低成本实现直接在页面上渲染变化率超过阈值的商品。前端页面用的是原生 HTML JavaScript ECharts通过 fetch 调用 Flask 接口拿到 JSON 后渲染。没有引入 Vue 或 React因为系统本身的数据展示逻辑不复杂引入前端框架反而让项目体积变大、答辩时解释起来更费劲。4.3 查询性能与缓存优化比价系统的数据量虽然不大但趋势图查询这类高频接口如果没有正确的索引和缓存策略响应时间会肉眼可见地变长。一个常见现象是页面加载速度从 100 毫秒上升到 5 秒原因是每次刷新都全表扫描价格历史表。优化分两层。第一层是数据库索引优化这是最关键的price_history表的product_id加索引product_id和record_time建联合索引搜索接口的keyword字段在前端做分词后生成搜索条件配合 MySQL 的全文索引或 LIKE 前缀查询。加了联合索引之后趋势查询的响应时间从 800 毫秒降到了 20 毫秒以内这个优化幅度非常明显。第二层是缓存。我用了 Flask-Caching 的简单配置给搜索结果和排行榜数据加了 5 分钟缓存。理由很简单比价数据来自定时采集不是实时产生5 分钟内数据的准确率几乎没变化但能让高并发访问时后端承受的压力大幅下降。生产部署时我也建议再加一层 Nginx 缓存静态资源不过后端缓存已经足够支撑演示场景了。from flask_caching import Cache cache Cache(app, config{ CACHE_TYPE: simple, CACHE_DEFAULT_TIMEOUT: 300 }) app.route(/api/rank) cache.cached(timeout300, query_stringTrue) def rank(): # 查询逻辑 ...5. DeepSeek大模型与Agent从看数据到问数据5.1 大模型能解决哪些传统查询解决不了的问题可视化看板把数据摆在了用户面前但用户面对一堆折线和柱状图脑海里往往还是带着具体问题来的这台电脑最近价格怎么样我要不要等一等再买传统的搜索接口只能做精确匹配它无法理解性价比高一点、预算六千以内、适合编程这种带有模糊语义和多重条件的复杂问题。大模型的价值在于把自然语言转成系统内的确定性操作再把结构化的查询结果转成用户能直接理解的答案。这个翻译过程正是 Agent 层的核心价值。传统接口解决怎么查大模型介入后解决的是怎么问——用户无需学习任何查询语法用自己的话就能获得和人工分析几乎一致的结论。我在实际测试中试过一句典型问题这个牌子的游戏本四个平台哪家便宜未来一个月适合入手吗这个问题放在传统搜索框里基本无法处理。但经过 Agent 拆解它被路由成两个工具调用一个查当前各平台到手价一个查近 90 天价格趋势然后把结果交给大模型撰写结论。5.2 Agent工作流与工具调用的设计Agent 的设计核心是能调用工具而不是直接生成答案。这样既能保证回答有实时数据支撑也能避免大模型编造不存在的价格信息。我采用的模式是经典的工具调用Function Calling方式整体工作流如下用户输入自然语言问题发送到 DeepSeek API附带一份可用工具列表的说明。模型判断需要调用哪些工具返回结构化的工具调用参数例如调用search_product参数是关键词和平台。后端拿到参数后实际执行查询代码从 MySQL 取出真实数据。把查询结果作为上下文连同用户的原问题一起再次提交给大模型。模型综合上下文生成自然语言回答附上数据来源和时间戳。这个流程里最关键的设计点大模型永远看不到真正的数据库它只能通过工具间接获取数据因此不存在幻觉污染数据库的风险。同时每一次回答都附带了数据生成时间用户能判断信息的时效性。5.3 集成DeepSeek的具体步骤与提示词要点接入 DeepSeek 比想象中简单因为它的 API 兼容当下主流的接口格式直接用 HTTP 请求就能跑通。在这里我用了一个比较直观的示例来展示工具调用的完整流程import json from openai import OpenAI client OpenAI( api_key你的APIKey, base_urlhttps://api.deepseek.com/v1 ) tools [ { type: function, function: { name: search_product, description: 根据商品关键词搜索平台在售商品, parameters: { type: object, properties: { keyword: {type: string, description: 商品关键词}, platform: {type: string, description: 平台标识} }, required: [keyword] } } } ] messages [{role: user, content: 华硕天选5在各平台多少钱}] response client.chat.completions.create( modeldeepseek-chat, messagesmessages, toolstools, tool_choiceauto ) # 解析模型返回的工具调用 tool_calls response.choices[0].message.tool_calls if tool_calls: for call in tool_calls: arguments json.loads(call.function.arguments) print(arguments) # 拿到参数后去数据库查询提示词设计是这套系统里最值得打磨的地方。我给系统的系统提示词System Prompt定了三条铁律第一所有价格数据必须引用查询结果没有查到就明确说未找到绝不猜测第二回答要分点列出各平台对比最后给一个明确的建议第三涉及趋势说明时必须引用趋势数据中的最低点和最高点日期让用户自己校验。另一个容易踩坑的地方是 token 控制。工具调用阶段的输入包含工具定义和对话历史长度一变长成本就上去了。我的对策是只保留最近两轮对话历史工具定义只保留当前会话用到的几个这样单次请求的 token 消耗可以压在一个很低的水平。5.4 一个小场景演示从提问到回答的完整链路用一个真实问题来把链路串一遍。假设用户输入我想在 618 买一台轻薄本预算 5500 左右主要用于写代码偶尔打打游戏推荐哪款什么平台买便宜系统处理过程如下大模型判断这个问题应该调用工具search_product参数为关键词轻薄本、平台all。后端查询数据库返回符合条件的所有商品和各平台到手价、近 30 天价格趋势。大模型将这批数据整理成表格要点和文字建议最终输出类似这样的一段话在您预算区间内推荐关注 A 平台的某型号比 B 平台低 320 元该型号近 30 天最低价出现在 5 天前目前价格处于中位水平若不急可以等 618 当天的活动价历史规律显示大促首日降幅通常在 8% 左右。这个回答结合了实时数据、历史趋势和常识规律已经超过了一堆图表能提供的价值。实际上我在演示环节最常收到的反馈就是这个功能比光看图直观多了——这其实就是 Agent 层最大的意义。6. 项目后记哪些地方值得重做哪些坑不必再踩6.1 高频踩坑清单做完整套系统我把自己踩过、也看到周围同学踩过的坑整理成了一张表按触及频率排序。这些坑非常真实几乎每个人都会遇到问题现象根因解决思路爬虫跑一段时间后价格抓不到页面请求被风控拦截或前端价格结构变更检查反爬特征设置动态调整解析策略数据库 Decimal 字段写入报错爬虫返回的价格字符串未清洗含逗号和货币符号统一价格解析工具入库前强制类型转换前端图表数据为空Flask 返回的 JSON 缺失字段或者字段类型不对统一使用 ApiEncoder前后端字段名保持一致定时采集任务莫名中断服务器休眠、内存不足导致 Chrome 进程被杀使用稳定运行环境定期重启浏览器实例DeepSeek 回答中价格与图表不一致模型未走工具调用直接生成了常识性回答在提示词中强制要求引用搜索结果忽略直接生成其中第一个坑是最容易反复出现的。平台页面每隔几个月会改版一次但在毕业设计的时间尺度里通常只会在初采和答辩前各遇到一次。我的经验是把解析器的容错能力做强当某平台连续失败超过 5 次自动禁用该平台并给运维页面发标记而不是让整个采集流程卡死。6.2 给后来者的三条建议项目收尾之后回头看有三条建议我觉得无论对毕业设计还是个人练手项目都适用。第一爬虫部分不要过度追求数据量。很多同学一上来就想抓几十万条数据结果把时间全耗在处理反爬、绕过限制上。对毕设来说抓取几千条覆盖多个类目的干净数据足以支撑全部功能演示。数据质量远比数据量重要宁可花时间打磨清洗和比价逻辑也不要陷入违规采集的泥潭。第二一定要保留历史价格数据。答辩时展示一个折线趋势图和展示一张静态表格效果天差地别。趋势图能证明系统在持续运行、持续采集能讲出数据积累的故事。从项目第一天开始就让定时采集跑起来哪怕一开始只监控 20 个商品积累三周后图表就会很饱满。第三大模型 Agent 是低成本亮点。很多比价系统都停在图表展示这一步只要你接入了 DeepSeek 做自然语言问答就天然多了一个有区分度的功能点。而且现在各大模型的 API 文档都很清晰照着官方示例跑通一个工具调用只用半天时间投入产出比非常高。6.3 系统还能怎么扩展这套比价系统目前的边界很清楚采集频率受限于平台风控比价范围限于已入库平台的商品Agent 能力只覆盖了工具调用这一种大模型集成方式。如果想继续扩展有三个方向可以做一是增加价格预测模块。基于历史趋势数据用简单的时间序列模型预测未来一周的价格区间让什么时候买这个问题从经验判断变成数据驱动。二是引入用户订阅机制允许用户关注商品并设置目标价触发降价提醒通过页面通知推送。三是把 Agent 升级成多轮对话让用户能连续追问比如先问推荐一款手机再问那它能玩原神吗系统需要维护多轮对话状态并持续调用工具。这些都是可以逐步迭代的方向核心的框架已经打好了。我自己的体会是这套系统最有价值的地方不是某个单点功能而是把前端、后端、爬虫、数据库、大模型这五个环节完整串了起来。做完它你对一个真实业务系统从数据采集到智能交互的整个链路会有真正的体感这是任何单一技术栈练习都给不了的。