Python实现京东手机数据分析系统:爬虫与可视化实战

发布时间:2026/9/24 18:55:08
Python实现京东手机数据分析系统:爬虫与可视化实战 最近看到不少同学在找毕设题目方向都集中在“爬虫可视化”这条线上。今天这套京东手机数据分析系统算是我带过的项目里比较典型的一套技术栈清晰、演示效果好、工作量也容易控制。如果你正在琢磨毕设或者课设选题这个方向可以认真看一下。先交代一下这套东西能做什么用 requests 写爬虫抓取京东手机品类下的商品数据包括名称、价格、店铺、评论数、好评率这些核心字段拿 Flask 搭一个 Web 服务把清洗好的数据通过 pyecharts 渲染成交互式图表最后在浏览器里展示价格分布、品牌份额、评论量排行、价格与评论数的关系这些分析结果。整个链路从数据采集、存储、分析到可视化是完整的这正好是毕业设计里最容易出东西、也最好讲清楚的部分。这套系统的受众也比较明确计算机、大数据、电商相关专业的本科生为主其次是打算走 Python 数据分析方向、想拿真实平台数据练手的初学者。如果你已经会一点 Python 语法但没完整做过项目这套系统是个很合适的一站式练手项目。我看了一下最近的搜索热词有几个很关键的信息最近非常多人搜exceeded retry limit, last status: 429 too many requests这说明爬虫部分大家普遍卡在了反爬上面。这套系统里我也踩过这个问题而且解决思路可以直接复用后面重点讲。1. 毕设选题思路与整体架构这套系统解决什么问题1.1 为什么选京东手机品类而不是整站或别的品类先聊一个很实际的问题为什么爬京东为什么偏偏爬手机。京东整站商品量太大以个人毕设的计算量根本没有必要全爬而且全站爬虫的目标在答辩时很容易被追问“数据量上亿你怎么处理”这问题不好答。反而聚焦单一品类——手机是性价比很高的选择。手机品类有特征很明显品牌集中华为、苹果、小米、OPPO、vivo、荣耀、价格梯度大千元机到万元机、标品属性强参数规格稳定不会像服装那样款式爆炸。这几条特征保证了后续数据分析会呈现清晰的规律比如能明显看到价格区间和评论数量的关系不会像爬食品、日用品那样数据规律模糊复盘困难。给评审老师演示的时候一两个“一眼就能看懂”的趋势比十张复杂的图都管用。另外推荐系统的影子也在手机这个品类上最容易体现。手机商品的连带属性强用户看完一款手机往往会关心同价位竞品、同品牌其他型号、手机配件这些延展商品。这套系统虽然做的是数据分析但数据维度已经为推荐逻辑打好了底——价格、品牌、评论量、好评率、店铺评分这些字段本身就是做商品推荐最常用的特征。1.2 技术栈选型的逻辑为什么是 Python Flask pyecharts requests这套组合放在毕设里是很聪明的选择每一层都有它不可替代的理由。requests是爬虫层的首选库比起 scrapy 学习成本低代码写起来逻辑直观发请求、拿响应、解析字段。毕设答辩的时候你能一行一行讲清楚请求是怎么发出去的、数据是怎么提取出来的。这一点很重要——用 scrapy 虽然也能实现但框架封装太多老师一问细节容易卡住。Flask是轻量级 Web 框架应用代码可以全部写在一个文件里启动也可以按模块拆开。它有完整的路由系统、模板渲染、JSON 响应支持这对一个“数据分析结果展示”的定位来说完全够用。如果上 Django可能把大量时间花在配置学习上而偏离了数据分析主线。pyecharts是百度 ECharts 的 Python 封装。它的核心用法是你在 Python 里配置数据、配置图表类型它生成图表配置 JSON再由前端 ECharts 库负责渲染。这解决了 Flask 模板里手写前端代码的麻烦你基本不用写复杂的 JavaScript又能得到交互效果很好看的图表。而且图表支持鼠标悬停查看数值、点击图例筛选系列答辩演示时非常加分。1.3 系统分层架构从爬虫到可视化的一条完整链路整套系统的研发流程分四层采集层requests BeautifulSoup抓取京东手机品类列表页循环翻页解析商品数据。存储层SQLite数据库小巧、文件型、零配置适合毕设规模的数据后续可平滑迁移到 MySQL。服务层Flask提供 Web 服务和数据查询接口处理前端图表的数据请求。展示层pyecharts生成图表渲染到 Flask 的模板页面中组成完整的可视化 Dashboard。实际项目里我把架构拆得更细一点分为六大模块jd_phone_analysis/ ├── spider/ │ ├── jd_spider.py # 爬虫主体抓列表页、解析字段 │ ├── user_agents.py # UA 池 │ └── proxys.py # IP 资源池可选后面讲 ├── config.py # 数据库路径、爬取URL、请求参数等配置 ├── models.py # 数据库表模型与数据操作封装 ├── service/ │ ├── data_processor.py # 数据清洗与统计聚合 │ └── chart_builder.py # pyecharts 图表生成封装 ├── app.py # Flask 主应用定义路由 ├── templates/ │ └── index.html # Dashboard 页面 └── requirements.txt # 依赖清单这个目录结构的好处是职责边界清晰答辩时候按模块讲思路非常顺。别把所有代码堆在一个main.py里面毕设代码要让人看得出工程化思维。2. 数据采集层requests 爬虫与京东反爬的真实对抗记录2.1 爬虫目标分析与字段设计京东手机品类列表页的 URL 结构相对规则。搜索关键词为“手机”时URL 长这样https://search.jd.com/Search?keyword手机page1页面是服务端渲染加部分异步加载一次请求返回的 HTML 里已经带了大部分商品信息。用同一个 URL 翻页时page参数每翻一页加 2 或者按 2、4、6 递增京东列表页实际上每 2 页对应一次数据刷新处理时要小心亲测 page2 和 page3 的内容是重叠的这个问题我后面详细讲。针对手机这个品类我最终确定采集的字段是字段名类型说明product_idstring商品ID作为主键去重product_namestring商品名称pricefloat当前价格shop_namestring店铺名称comment_countint评论数good_ratefloat好评率brandstring品牌根据商品名预处理归类这些字段基本覆盖了后续分析的所有维度。price 能看价格分布comment_count 能看商品热度good_rate 能看口碑品牌字段能直接做品牌维度聚合。字段不是越多越好每一个都要能对应到你后续要画的某个图上否则就属于采集了用不上的脏数据。2.2 requests 请求头的伪装艺术从裸奔到模拟真人第一次跑这个爬虫时我直接requests.get(url)返回了一个空空如也的响应或者奇怪的验证码页。问题就在于裸请求的 Headers 里没有 User-Agent目标站对无 UA 的请求会直接判定为脚本访问。解决这个问题的第一步是完整模拟浏览器请求头。亲测最关键的三个字段是User-Agent告诉服务端你是什么浏览器、什么系统。Referer来源页京东搜索页的防爬逻辑会校验这个填https://www.jd.com/可以稳定通过。Cookie如果遇到登录墙或额度限制拿浏览器里现成的 Cookie 贴进来是最快解。我最终的请求头模板def build_headers(refererhttps://www.jd.com/): return { User-Agent: random.choice(UA_LIST), Referer: referer, Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en;q0.8, Connection: keep-alive, Cookie: get_cookie_from_config() }UA_LIST 里我会放 20 个左右的主流浏览器 UA覆盖 Chrome、Firefox、Edge、Safari 的近期版本和 macOS/Linux/Windows 三个平台。每次请求前随机取一个别一个 UA 兜到底——同一个 UA 高频请求同样会被盯上。2.3 429 too many requests 的根因分析与完整排查链路这就是热词里那批人集体卡住的问题了。我一开始跑爬虫时也遇到exceeded retry limit, last status: 429 too many requests而且是连续运行几分钟后必现。这个报错的字面含义是“请求太多”但排查下来有三个层面的原因一层层排除才能彻底解决。第一层单 IP 请求频率超限。目标站对一个 IP 在单位时间内的请求次数有阈值。我前期的爬虫没有加任何限速循环翻页时每次请求间隔只有 0.1 秒左右一个 IP 一分钟内打了上百次直接触发限制。这个层级的解法是对请求做主动限速import time import random def fetch_with_pacing(url, session, min_interval2.0, max_interval4.0): time.sleep(random.uniform(min_interval, max_interval)) try: resp session.get(url, headersbuild_headers(), timeout10) resp.raise_for_status() return resp except requests.exceptions.RequestException as e: print(f[{time.strftime(%H:%M:%S)}] 请求失败: {url} - {e}) return None每次请求之间随机等待 2 到 4 秒这个速度爬 200 页大概需要 10 分钟对于毕设的数据量几百条到几千条商品完全够用。这个方案是缓解 429 最有效的手段没有之一。第二层重试策略导致恶性循环。当时我的代码里写了一个自动重试逻辑失败了立刻重试最多重试 3 次。这个设计本身是好的但问题出在重试间隔太短429 出现后服务器已经进入惩罚期你越重试越容易持续触发限制导致每次运行都在反复打同一个状态码。正确的重试应该是指数退避def retry_fetch(url, session, max_retries3): for attempt in range(max_retries): resp fetch_with_pacing(url, session) if resp is not None: return resp wait_time 5 * (2 ** attempt) # 5秒, 10秒, 20秒 print(f等待 {wait_time} 秒后重试 ({attempt 1}/{max_retries})...) time.sleep(wait_time) return None第一次失败等 5 秒第二次 10 秒第三次 20 秒。这样给服务器留出恢复窗口而不是在惩罚期狂撞墙。第三层并发或 Session 复用问题。如果你开了线程池去并发请求429 概率会指数级上升。建议毕设阶段老老实实单线程 限速跑。同时记得用requests.Session()复用连接而不是每次请求创建一个新连接。Session 会维持 Cookie 和连接池更接近浏览器的行为特征也不容易被识别为异常连接。session requests.Session() for page in range(1, total_pages 1): parse_list_page(session, page)这一整套排查流程做完之后429 出现的频率从“每 5 分钟一次”降到“跑一整轮几乎遇不到”。2.4 页面解析BeautifulSoup 提取商品信息的细节拿到 HTML 后解析方式的差异直接决定了数据质量。京东搜索列表页的商品信息在li classgl-item>from bs4 import BeautifulSoup def parse_product_list(html): soup BeautifulSoup(html, html.parser) items soup.select(li.gl-item) products [] for item in items: product {} sku item.get(data-sku) if not sku: continue product[product_id] sku # 商品名称 title_tag item.select_one(.p-name em) if title_tag: product[product_name] title_tag.get_text(stripTrue) # 店铺 shop_tag item.select_one(.p-shop a) if shop_tag: product[shop_name] shop_tag.get_text(stripTrue) # 评论数 comment_tag item.select_one(a.comment) if comment_tag: comment_text comment_tag.get_text(stripTrue) product[comment_count] parse_comment_count(comment_text) # 好评率 rate_tag item.select_one(.p-commit strong a i) if rate_tag: rate_text rate_tag.get_text(stripTrue) product[good_rate] parse_good_rate(rate_text) products.append(product) return products几个容易踩的细节列表页里价格和详情页是异步加载的直接解析 HTML 拿不到价格实际项目的常见做法是在拿到 sku 之后去请求对应的价格接口https://p.3.cn/prices/mgets?skuIdsJ_SKU_ID。这个接口返回的 JSON 里就有价格字段且数据量比详情页小很多。评论数是这样的文本100万或2.3万直接转 int 会报错要先把单位换算出来def parse_comment_count(text): text text.replace(, ).strip() if 万 in text: return int(float(text.replace(万, )) * 10000) return int(text)列表页翻页有重叠实测 page2 和 page3 返回的商品基本一致追查原因是京东列表页的页码参数实际是“每页 30 条翻页步长为 2”。解决方法是把页码换算成真实偏移量real_page start_page (page - 1) * 2 url fhttps://search.jd.com/Search?keyword手机page{real_page}或者更省事的方案不用页码翻页改用商品 ID 去重重复了就跳过直到抓满目标数量为止。两种方案都行但用 ID 去重最稳因为它顺带清理掉了列表页里出现的广告位商品。3. 数据清洗与存储SQLite 在毕设数据量下的合理使用3.1 原始数据长什么样要洗什么爬下来 CSV 里看原始数据那叫一个乱。以我的实际数据为例常见的脏数据有这几类商品名称含大量无关字符【官方正品】华为 HUAWEI Mate 60 Pro 卫星通话 第二代昆仑玻璃 鸿蒙操作系统 12GB512GB 雅丹黑—— 品牌、系列、卖点、配置、颜色全挤在一个字符串里。部分价格字段为None或空字符串通常是商品已下架或价格接口返回异常。评论数字段混入了万等中文单位如50万、2.3万。同一个商品 ID 因为多次爬取可能出现重复记录品牌名一个字段里写了“华为”“HUAWEI”两种形式是的京东商家就这么随性。我在清洗环节做了三件事一是写了一个价格清洗函数遇到空值或异常值直接丢弃这条记录对于分析类项目丢掉几条坏数据对整体结论没有影响但留着一会导致类型转换报错、一会儿出 NaN 值后面画图全是坑。二是评论数统一转成 int单位换算清楚。好评为字符串形式如98%转成浮点数98.0。三是品牌归类。这个逻辑很简单从商品名里匹配已知品牌关键词列表匹配到哪个就标哪个。没匹配到的归为“其他”。BRAND_KEYWORDS [华为, HUAWEI, 小米, Redmi, 苹果, Apple, OPPO, vivo, 荣耀, HONOR, 三星, SAMSUNG, 一加, 魅族, realme] def classify_brand(product_name): for brand in BRAND_KEYWORDS: if brand.lower() in product_name.lower(): return brand return 其他3.2 数据库设计用文件型数据库减少不确定因素毕设阶段数据库选型我强烈建议 SQLite。原因很简单零配置、零依赖不需要像 MySQL 一样单独安装服务打开即用。数据以单个.db文件存在方便备份和迁移。几千条商品数据在这个量级下SQLite 的查询性能完全不用担心。答辩时你可以直接把这个 db 文件拷到任何电脑上演示不用现场配数据库环境——你永远不知道答辩教室的机器上装了什么。建表语句长这样CREATE TABLE IF NOT EXISTS products ( id INTEGER PRIMARY KEY AUTOINCREMENT, product_id TEXT UNIQUE NOT NULL, product_name TEXT NOT NULL, price REAL, shop_name TEXT, comment_count INTEGER DEFAULT 0, good_rate REAL, brand TEXT, crawl_time TEXT DEFAULT (datetime(now, localtime)) );重点说一下这个product_id TEXT UNIQUE的唯一约束它配合INSERT OR IGNORE或者INSERT OR REPLACE使用能把重复保存问题在数据库层面解决掉不需要在代码里写各种 if 判断。3.3 幂等入库重复跑爬虫也不会产生垃圾数据写爬虫的过程中你一定会反复调脚本重新跑。如果入库逻辑不带去重跑三次就有三份重复数据统计图直接爆炸。我用的是INSERT OR IGNORE加update结合的方式import sqlite3 def save_products(products): conn sqlite3.connect(config.DB_PATH) cursor conn.cursor() for p in products: cursor.execute( INSERT OR IGNORE INTO products (product_id, product_name, price, shop_name, comment_count, good_rate, brand) VALUES (?, ?, ?, ?, ?, ?, ?) , (p[product_id], p[product_name], p[price], p[shop_name], p[comment_count], p[good_rate], p[brand])) conn.commit() conn.close()如果同一商品后续爬到了新的价格数据可以再加一条UPDATE products SET price? WHERE product_id?的处理逻辑看你自己要不要保留历史价格轨迹。如果做价格追踪分析可以考虑建一张 price_history 表这是加分项但注意复杂度可控。4. Flask 后端从数据库到 JSON API 的完整链路4.1 Flask 应用结构与路由设计Flask 在这里的角色是“数据展示的桥梁”。它不负责复杂计算核心任务是接收前端请求 → 查询数据库 → 返回数据或页面。这个定位决定了代码结构不用太复杂。我的app.py核心结构如下from flask import Flask, render_template, jsonify import json from service.chart_builder import build_price_histogram, build_brand_bar, build_scatter from service.data_processor import query_stats, query_by_brand app Flask(__name__) app.route(/) def index(): return render_template(index.html) app.route(/api/summary) def api_summary(): data query_stats() return jsonify(data) app.route(/api/charts/price) def api_price_chart(): chart build_price_histogram() return jsonify(chart) app.route(/api/charts/brand) def api_brand_chart(): chart build_brand_bar() return jsonify(chart) app.route(/api/charts/scatter) def api_scatter_chart(): chart build_scatter() return jsonify(chart) if __name__ __main__: app.run(host0.0.0.0, port5000, debugTrue)路由设计上走了两套方案。/渲染整页模板/api/*返回 JSON。这个设计方便你后续做前后端分离也方便老师问你接口设计思路。每个 API 的功能单一一个是汇总统计一个是价格分布一个是品牌分布一个是散点关系各司其职。4.2 pyecharts 图表生成Python 端如何交给前端渲染导出的图表格式是 JSON。build_price_histogram这个函数生成价格分布直方图用 pyecharts 的 Bar 组件数据直接查数据库聚合返回 Python 字典结构Flask 的jsonify自动转成 JSON 字符串。from pyecharts import options as opts from pyecharts.charts import Bar def build_price_histogram(): data query_price_distribution() bins [str(b) for b, _ in data] counts [c for _, c in data] bar ( Bar() .add_xaxis(bins) .add_yaxis(商品数量, counts) .set_global_opts( title_optsopts.TitleOpts(title手机价格区间分布), yaxis_optsopts.AxisOpts(name商品数), xaxis_optsopts.AxisOpts(name价格区间), ) ) return bar.dump_options_with_quotes()dump_options_with_quotes()是 pyecharts 核心方法它把图表配置导出成 JSON 字符串。这个字符串就是 ECharts 渲染所需的 options 对象。前端拿到的不是一张图片而是一段配置所以图表具有完整的交互能力——鼠标悬停显示数据、点击柱状图区域高亮等。4.3 前端模板一个 HTML 搞定图表展示templates/index.html里做的事情非常简单用 ECharts CDN 引入库然后用 fetch 请求/api/charts/*拿到 JSON 直接渲染。!DOCTYPE html html langzh-CN head meta charsetUTF-8 title京东手机数据分析系统/title script srchttps://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.3/echarts.min.js/script style body { background: #f5f6fa; margin: 0; } .header { padding: 20px; background: #2d3436; color: white; text-align: center; } .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; padding: 16px; } .chart-box { background: white; border-radius: 8px; padding: 12px; height: 420px; } h3 { margin-top: 0; font-size: 16px; color: #333; } /style /head body div classheader h1京东手机数据分析系统/h1 p基于 Python Flask pyecharts requests/p /div div classgrid div classchart-boxh3手机价格区间分布/h3div idpriceChart styleheight:380px;/div/div div classchart-boxh3品牌商品数量占比/h3div idbrandChart styleheight:380px;/div/div div classchart-boxh3价格 vs 评论数散点图/h3div idscatterChart styleheight:380px;/div/div div classchart-boxh3好评率 Top 10 商品/h3div idrateChart styleheight:380px;/div/div /div script fetch(/api/charts/price) .then(resp resp.json()) .then(options { const chart echarts.init(document.getElementById(priceChart)); chart.setOption(options); window.addEventListener(resize, () chart.resize()); }); // 其余图表按同样方式加载… /script /body /html注意一点如果你的环境是内网或者离线环境ECharts 的 CDN 可能加载不出来这时把 echarts.min.js 下载后放到项目的static目录里改引本地路径即可。别问我是怎么知道这个教训的。5. 可视化层pyecharts 图表选型与维度对应5.1 每个业务问题对应什么图表图表不是随手画的每一个要能回答一个明确的业务问题。我最终沉淀下来的四张图每一张都对应一个答辩时可以展开讲的点。价格区间直方图Bar手机价格主要集中在哪个段位设置 500 元一个分箱从 0 到 12000 共 24 个区间。实际数据跑出来通常是 1000-1500 元区间峰值1500-2000 和 3000-4000 有次峰呈现三峰分布。这个分布特征可以直接引出“千元机走量、中高端占利润”这类电商分析的经典结论。品牌商品数量柱状图Bar与占比饼图Pie组合头部品牌占了多少用柱状图看绝对量用饼图看占比。这个数据可以验证“市场集中度高”这个判断。价格 vs 评论数散点图Scatter价格越高的手机评论越多还是越少把 price 放 x 轴comment_count 放 y 轴每个点是一个商品。实际跑出来通常是一个长尾分布爆款集中在 1000-3000 元区间评论区明显有两个高密度区。这个图除了用于分析还能向老师展示你对数据的理解。好评率 Top 10BarH横向柱状图哪些手机口碑最好用横向柱状图展示名称长也不会互相遮挡。这个图是给报告增加“人情味”的——观众能从图上找到自己熟悉的机型。5.2 pyecharts 与 ECharts 的版本匹配问题这是 pyecharts 使用中很隐蔽的一个坑。pyecharts 2.x 版本生成的 JSON 结构与 ECharts 5.x 是兼容的但 pyecharts 1.x 和一些旧版 ECharts 混用会出现图表初始化报错、部分组件不显示的问题。我的建议是 pyecharts 直接上最新版pip 安装pyecharts2.0.52024 年这个版本很稳前端 ECharts 用 5.x 版本两者匹配度最好。如果你的 pyecharts 是 1.x需要在dump_options的时候处理一下引号问题否则 JSON 可能带有多余引号导致解析失败。5.3 图表交互与页面布局的优化做可视化不仅要把图画出来还要让页面有“成品感”。我加了几个细节每张图标题明确副标题写“数据采集时间xxxx-xx-xx”显示数据的时效性。图表高度统一设置为 380px布局采用 CSS Grid 两列布局第一行放价格直方图和品牌柱状图第二行放散点图和好评率排行宽屏下视觉效果紧凑整齐。Grid 布局加上gap间距卡片背景白色、圆角 8px、box-shadow 加阴影整体页面有一个“产品感”不是白底裸图。这些都不用写复杂代码但好处是实际演示的时候页面效果好观感会直接影响评分。6. 实际运行与部署踩坑后的可用方案6.1 本地跑通全套系统的完整步骤把整套系统从零跑起来按下面的顺序操作可以少走弯路。第一步安装依赖。pip install flask requests beautifulsoup4 pyecharts pandaspandas 不是必需但如果你要快速处理 CSV 数据pandas 会很方便。建议一起装。第二步先跑爬虫再启动 Web。python spider/jd_spider.py --pages 50 python app.py打开浏览器访问http://127.0.0.1:5000如果看到四张图表正常渲染说明链路已经通了。爬虫一次性爬 50 页大概能拿到 400-600 条商品数据包含去重这个量级足够分析和演示。6.2 服务器部署关键坑位与解决方式如果你想把系统部署到云服务器上有几个坑提前说坑一静态文件和模板路径大小写。Windows 本地开发时路径不区分大小写但 Linux 服务器严格区分。Templates和templates是不一样的Staic和static也不一样。本地跑得好好的一上服务器就 404先检查文件路径大小写。坑二端口和公网访问。云服务器安全组要放行 5000 端口同时 Flask 启动要绑定0.0.0.0而不是默认的 127.0.0.1否则外网访问不到。坑三CDN 资源。如果服务器在校园网环境或者国内云服务器访问外网 CDN 有时会不稳定ECharts 加载不出来页面就是一片空白。直接把 echarts.min.js 下载到本地改引用路径一劳永逸。坑四运行环境。不要用系统自带 Python强烈建议用虚拟环境不然 pip 安装的包和系统包冲突了调试起来很痛苦。python3 -m venv venv source venv/bin/activate pip install -r requirements.txt nohup python app.py app.log 21 6.3 数据更新策略定时任务与增量爬取毕设演示阶段跑一次就够了但如果你希望通过这套系统做持续的数据观察就要考虑数据更新策略。最简单的方案是写一个定时任务每天早上 8 点跑一次爬虫增量更新价格和评论数# cron 表达式每天8点执行 0 8 * * * cd /path/to/jd_phone_analysis /usr/bin/python3 spider/jd_spider.py --pages 20 logs/spider.log 21增量爬取的逻辑商品 ID 已存在且价格没变跳过。商品 ID 已存在但价格变了更新 price 字段并记录一条价格变动日志。商品 ID 不存在作为新品插入。这套逻辑下后续你可以做“商品价格走势”分析甚至做一个简单的“降价提醒”功能——这就有一点推荐系统的味道了可以根据用户关注的商品推送降价信息。这可以作为毕设的加分扩展点二辩或者进阶版的时候用得上。6.4 围绕这套系统还能怎么扩展如果调研时间充裕有几个方向可以试按性价比从高到低排方向一加一个按品牌筛选的联动筛选器。页面顶部分四个按钮全部、华为、苹果、小米点击后所有图表联动刷新只显示该品牌数据。实现逻辑不复杂前端监听点击事件向后端传品牌参数API 查询时加 where 条件。这个功能很能体现你对前后端联动的理解。方向二接入评论数据做情感分析。爬取每个商品的前 100 条评论用简单的情感词典score 表给每条评论打正负分聚合出每个品牌的情感分布。这个方向能引入 NLP 的元素而且只需要简单的分词工具就能出结果。注意京东评论接口的反爬策略比列表页更严格限速要放得更宽。方向三简单推荐系统——同价位竞品推荐。当用户查看某一款手机详情时把价格在正负 10% 区间内、好评率更高的其他商品推荐出来。这个功能兼具分析价值和演示效果而且实现难度不高SQL 一次查询就能完成。我个人最推荐方向三因为它的完成度和演示效果最好而且和标题里的“推荐系统”构成呼应能让项目内容更完整。写在最后这套系统来回调了两周中间踩的坑大部分集中在反爬和图表渲染上。如果你想在一周内把它做完我的建议是爬虫部分用单线程 限速先跑通数据清洗入库后立刻做 Flask pyecharts 的图表展示这两条主线打通后再回头优化反爬细节和页面美观度。理顺这条链路之后你对从数据采集到可视化展示的整个流程都会有真实的体感这也是这个毕设题目的核心价值所在。