ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python+Hadoop+Spark+协同过滤:闲鱼二手大数据分析毕设全复盘

Python+Hadoop+Spark+协同过滤:闲鱼二手大数据分析毕设全复盘 每年到了毕业设计窗口期我都会在后台收到同一类问题题目里堆了一大串技术名词看起来像个大工程到底该从哪里下手就拿这个题目来说——基于Python的闲鱼二手商品大数据分析系统后面还跟着Spark、Hadoop、Vue、协同过滤推荐算法、可视化、大模型乍一看像是要做一个万人团队的产品。实际上拆开来看这类题目恰恰是毕业设计里最典型、也最容易被讲砸的类型技术栈覆盖广但每一层都可以控制在一个能跑通、能讲清、能抗住答辩追问的深度。这篇文章就把我当时做完这套系统后的完整复盘写出来从需求拆解、技术选型理由到Hadoop和Spark到底各自干什么活、协同过滤在二手场景里怎么落地、Vue大屏怎么搭、以及最后答辩时评委最爱追问的那几个坑一条线讲清楚。1. 题目拆解这份技术栈清单到底在考什么很多人拿到这种题目第一反应是全栈大数据算法我是不是得先把所有技术都学一遍。我的建议恰恰相反先把每个技术名词在系统里的位置画出来你会发现它根本不是一个需要精通的项目而是一个需要串起来的项目。题目表面上是六七个技术点实际对应的是四层核心能力数据怎么拿、数据怎么存怎么算、推荐怎么做、结果怎么展示。先说数据获取层。二手电商数据和普通电商有个本质区别它的商品生命周期极短一台手机挂出去可能三天就卖掉下架了所以数据天然有时效性、稀疏性和强烈的价格波动。这一层用Python写采集脚本重点不是爬得多快而是把字段设计得够用——后续做统计分析、做推荐算法、做可视化全靠这批原始数据的质量。然后是存储与计算层。Hadoop和Spark在这里的分工非常明确Hadoop的HDFS负责存原始数据Spark负责在内存里做计算。为什么不是只装一个Spark单机跑因为题目里有大数据三个字答辩时你需要能说清楚数据量大到一定程度后单机Pandas扛不住需要分布式存储和分布式计算。即使你实际数据只有几万条架构逻辑要完整。再往上是算法层。协同过滤推荐算法是整套系统里最容易被追问的地方也是拉开档次的地方。二手场景下没有用户评分只有浏览、收藏、留言、成交这类隐式行为怎么把这些行为变成可计算的评分怎么解决新用户冷启动都是可以讲出深度的点。最后是展示层。Vue在这里的价值是做一个看得见的大屏让评委一眼看到你的分析结论。图表选什么类型、数据从哪来、接口怎么对接这一层不需要炫技但必须完整。把这四层拆完你会发现这套系统的本质就是一条数据流水线采集层喂数据存储计算层出指标算法层做推荐展示层讲结论。每层选成熟方案控制好量级就能成为一个合格的毕设项目。2. 数据从哪来二手商品的数据字段设计与清洗策略做这套系统的第一个坑不是代码而是数据。很多同学一上来就写爬虫去抓闲鱼结果没抓几条就被风控拦了或者抓下来的字段乱七八糟没法用。我的做法是先明确要分析什么再反推需要什么字段最后才决定怎么采集。2.1 核心字段设计二手商品分析的维度结合标题里电商商品这个大方向通常要覆盖价格、品类、地域、时间、买卖热度这几条线。我当时设计的字段表大概长这样字段名含义用途是否必须item_id商品唯一ID去重、关联行为数据必须title商品标题文本分析、关键词提取必须price标价价格分布、价格区间统计必须category商品品类品类热度、占比分析必须location卖家所在城市地域分布、大屏地图必须release_time发布时间时效性分析、趋势分析必须view_count浏览量商品热度指标建议favor_count收藏量隐式反馈、评分矩阵建议deal_flag是否成交真实需求判断可选seller_credit卖家信用信任度分析可选这套字段有个好处它既能支撑Hadoop和Spark阶段的统计分析又能直接为协同过滤算法提供行为数据。收藏量、浏览量、成交标志这三个字段在评分矩阵里会变成非常关键的隐式反馈信号。如果采集时没有留这些字段后面做推荐算法时会非常被动只能靠商品之间的文本相似度硬凑效果会很差。2.2 采集方式的选择与合规边界技术选型上的一个实操建议是没必要只用一套采集脚本硬刚。分析类项目对数据的实时性要求不高完全可以采用公开数据集补充采集的组合。公开的二手交易数据集、电商公开数据集可以先把流水线跑通然后再用Python脚本对公开页面信息做补充采集。这里面必须说实话对线上服务做大规模采集既不稳定也在合规上有风险尤其是涉及用户行为、卖家信息这类数据毕设项目完全没必要去碰。我当时用的是公开数据集做主体用少量自己构造的模拟数据补充冷启动场景整个流程照样完整答辩时也没有任何数据合规方面的隐患。如果真的需要写采集脚本建议重点掌握两个Python基础能力请求头伪装和解析。用requests拿到页面后用BeautifulSoup或lxml解析提取出上面表格里的字段清洗后存成CSV或JSON。这里有一个小经验标题文本里藏着大量信息比如95新国行过保自提这些词直接决定商品价值判定清洗时不要丢掉。2.3 清洗规则的几个细节清洗是决定分析结果好不好看的关键步骤。二手数据有几个非常典型的脏数据场景第一类是价格异常。有人挂1元引流有人标99999元其实是想以物换物所以价格上下限要过滤通常保留1到100000之间的正常区间再用分位数检测极端离群值。第二类是重复商品。同一件商品可能被卖家重复发布或者同一商品在不同页面被抓了多次要用item_id做主键去重同时结合标题相似度做一轮近似去重。第三类是地域字段归一化。二手平台的地址信息五花八门有写徐汇的有写上海市徐汇区的还有写漕河泾开发区的。地图可视化之前必须统一成省市两级推荐用行政区域字典做映射这一步不做好大屏地图上会出现一堆无法定位的点。整个数据预处理环节我建议都用Python的Pandas完成处理完的数据分两份一份存成CSV用于后续导入HDFS一份存入MySQL用于后端接口查询。这一步听起来简单但很多项目后面跑不通问题就出在数据源不统一。3. Hadoop与Spark从环境搭建到真正跑起离线统计这套系统里最容易让人半途放弃的就是Hadoop和Spark环境。网上教程一大堆但很多教程默认你有一台8核16G的服务器而实际上大多数学生只有一台8G内存的笔记本。我的经验是不要盲目跟教程先想清楚你到底需要Hadoop和Spark帮你做什么。3.1 伪分布式毕设阶段的务实选择Hadoop在这里的核心职责是提供HDFS也就是把数据分布地存起来。一个完整的集群需要至少三台机器但毕业设计阶段完全可以跑伪分布式模式——也就是在一台机器上同时启动NameNode、DataNode、SecondaryNameNode这些进程模拟一个单节点集群。我当时的使用流程是这样的先用Linux虚拟机或云服务器装好Hadoop配置core-site.xml和hdfs-site.xml把NameNode的端口设为9000这是默认RPC端口后续Spark连接要用。然后启动HDFS把清洗好的CSV文件通过命令行上传到HDFS指定目录。# 启动HDFS伪分布式模式 hadoop namenode -format start-dfs.sh # 查看进程是否启动成功 jps # 正确输出应该包含 NameNode、DataNode、SecondaryNameNode # 建目录并上传数据 hdfs dfs -mkdir -p /user/demo/input hdfs dfs -put items_clean.csv /user/demo/input/这里的核心逻辑要理清HDFS负责存Spark负责算。数据放上去之后统计分析的任务全部交给Spark而不是用MapReduce手写作业——因为MapReduce的代码量非常大而Spark可以用类似DataFrame的方式处理代码简洁得多答辩时也容易讲清楚。伪分布式模式跑在单机上性能有限但它完整保留了数据入HDFS、Spark从HDFS读取这一条真实链路这在大数据相关的项目中是重点加分项。3.2 Spark在这个项目里到底算什么Spark在这里解决的核心问题是当数据量超过单机Pandas能处理的范围时用分布式内存计算来完成统计分析。毕设阶段你的数据量可能只有几万到几十万条但流程必须遵守标准范式。我从HDFS读取数据后直接用Spark DataFrame做以下分析from pyspark.sql import SparkSession spark SparkSession.builder.appName(ItemAnalysis).getOrCreate() # 从HDFS读取CSV指定表头行 df spark.read.csv( hdfs://localhost:9000/user/demo/input/items_clean.csv, headerTrue, inferSchemaTrue ) # 计算各品类平均价格 category_stats df.groupBy(category).agg( {price: avg, item_id: count} ).orderBy(count(item_id), ascendingFalse) category_stats.show(10)实际开发中要注意一个小问题inferSchemaTrue在数据量大时会影响性能如果你的字段类型很明确更推荐自己写schema而不是让Spark猜。另外一个常见坑是中文字段名或中文路径Spark在Windows环境下读中文路径偶尔会乱码建议所有字段名统一用英文字母展示层再映射成中文。统计分析的核心指标我建议围绕四块做价格分布直方图、品类热度TopN、地域分布省份聚合、时间趋势按周或按月聚合。这四个指标分别对应可视化大屏上的核心图表也是答辩时最直观的分析结论。3.3 环境搭建的常见坑这块我也踩过几次坑尤其这几个问题出现的频率非常高第一个是Hadoop启动后打不开管理界面。原因大多是NameNode没格式化或者格式化之后又重复格式化导致clusterID不一致。解决办法是把logs目录清掉重新格式化再启动注意格式化前确认数据不需要保留。第二个是Spark连接HDFS时出现Connection refused。排查思路是先确认HDFS真的是启动状态然后确认core-site.xml里的fs.defaultFS是不是hdfs://localhost:9000Spark代码里用的地址必须和它完全一致只要写成localhost:9000和localhost:9000之间有任何端口不一致就会报这个错。第三个坑是内存问题。Spark默认会吃大量内存8G的笔记本经常卡死。调参的话把executor内存和driver内存都调到不超过2G本地模式用local[2]两个线程通常就能稳定运行。这些参数写清楚答辩时还能作为我对Spark资源调度有了解的佐证。4. 协同过滤推荐二手场景下怎么把评分算出来到了这个系统最有含金量的模块。题目里明确写了协同过滤推荐算法这也是很多同学最心虚的地方——因为教材里的协同过滤都是基于用户对物品的评分比如电影1到5星但二手平台根本没有评分功能。怎么把一个没有评分的场景改造成能做协同过滤的数据形态是这里最大的考点。4.1 隐式反馈打分规则的设计我当时的做法是把用户的所有行为转化为一个加权的综合评分。二手场景下用户行为从轻到重大概是这样浏览是了解、收藏是有意向、留言是进一步沟通、成交是真实购买。根据这个逻辑定义每条行为记录的评分权重行为类型权重说明浏览1.0基础曝光说明用户关注到此商品收藏3.0明确的兴趣信号留言/咨询4.0高意向行为成交5.0最强的正向反馈每条行为记录对应一个(user_id, item_id, rating)其中user_id可以从浏览记录中关联获得rating按上表计算。如果用户对同一商品有多种行为取最高权重或累加后再归一化。这里有一个实操细节二手商品时效性强浏览行为可能集中在某几天所以评分计算时不要做长时间跨度的累加一般只看最近30天否则推荐结果会包含大量已经下架的商品。4.2 用Spark实现ItemCF的计算流程协同过滤分两种基于用户的UserCF和基于物品的ItemCF。在这个项目中我强烈建议用ItemCF原因有二第一二手商品数量远小于用户数量物品之间的相似度矩阵比较小计算量可控第二用户兴趣在二手场景下波动很大今天看手机明天看相机基于用户相似度的推荐解释性比较差而基于物品相似度可以给出因为你看过这款手机所以推荐类似的手机这种逻辑演示效果也更直观。ItemCF的完整计算链路分三步每一步在Spark里都对应清晰的操作# 第一步构造评分数据 (user_id, item_id, rating) rating_df spark.createDataFrame([ (u_001, i_101, 5.0), (u_001, i_102, 3.0), (u_002, i_101, 4.0), # ...更多数据 ], [user_id, item_id, rating]) # 第二步按物品聚合用户行为列表并两两计算物品间的基础共现权重 # 这一步通常用自连接实现 item_pairs rating_df.alias(a) \ .join(rating_df.alias(b), col(a.user_id) col(b.user_id)) \ .filter(col(a.item_id) ! col(b.item_id)) \ .groupBy(col(a.item_id).alias(item_a), col(b.item_id).alias(item_b)) \ .count() # 第三步叠加评分权重计算加权相似度 item_pairs item_pairs.join( rating_df.alias(ra), col(item_a) col(ra.item_id) ).join( rating_df.alias(rb), col(item_b) col(rb.item_id) )如果想降低成本走通全流程直接用Spark MLlib里的ALS交替最小二乘也是可行的代码更短from pyspark.ml.recommendation import ALS als ALS( userColuser_id, itemColitem_id, ratingColrating, coldStartStrategydrop, maxIter10, regParam0.1 ) model als.fit(rating_df) recommendations model.recommendForAllUsers(5)但要注意用ALS有一个明显的短板它把用户和物品都映射到隐因子空间结果是一个黑盒评委让你解释为什么推荐这个商品时很难回答。手写ItemCF的相似度计算虽然代码多一些但每一步都能讲清楚答辩时的底气完全不一样。我的建议是代码教材用ALS跑通拿结果但在论文和答辩PPT里以ItemCF逻辑为主线讲解这样既有工程实现又有算法深度。4.3 冷启动问题的兜底方案协同过滤的一个致命弱点是冷启动新用户没有任何行为记录新商品没有任何销量数据算法直接失效。我当时的处理方案是两层针对新用户用热门商品TopN兜底也就是把全站收藏量和浏览量最高的20个商品直接推荐出来这在二手平台里其实就是首页运营逻辑针对新商品则用文本相似度把商品标题分词后用TF-IDF向量计算余弦相似度找出内容最接近的在售商品作为替代推荐。这两个方案加在一起冷启动的问题基本就圆上了而且答辩时这个点几乎是必问的。5. Vue可视化大屏把分析结果变成评委看得懂的图数据算出来、推荐结果做出来之后如果只给评委看表格整个项目的表现力会大打折扣。Vue在这套系统里的任务就是把统计分析结果和推荐结果变成一个大屏页面我用了大概一周时间完成这部分。5.1 页面结构与技术选型我采用的组合是Vue3 Element Plus ECharts组件库负责页面布局ECharts负责图表渲染。后端直接用Flask或FastAPI起一个轻量接口服务从MySQL里读汇总结果返回JSON。前后端分离开前端页面跑在8080端口后端接口跑在5000端口中间通过vue.config.js的proxy配置解决跨域问题。// vue.config.js 关键配置 module.exports { devServer: { port: 8080, proxy: { /api: { target: http://localhost:5000, changeOrigin: true } } } }这样配置之后前端请求/api/price_distribution就会自动转发到后端的Flask服务不需要在后端额外处理CORS整体开发体验干净很多。5.2 图表选型不是随便放的每个图表都要能对应到一个分析结论这是做可视化最重要的原则。我当时的大屏布局分四个区域每个区域都绑定一个统计指标大屏区域图表类型对应分析结论中央总览区数据指标卡商品总量、平均价格、热门品类Top3左侧价格分析区直方图/箱线图价格分布形态二手商品价格集中区间右侧品类分析区玫瑰饼图品类集中度头部品类占全站比例底部地域分布区中国地图热力图二手交易的地域特征活跃城市排名这里有个容易被忽略的细节二手商品的价格分布通常是长尾的大部分商品集中在几百到几千元区间如果直接用普通饼图头部品类会占掉半个圆看起来很单调。改用玫瑰饼图同时映射品类占比观感会好很多。价格分布用直方图结合箱线图既能看出峰值区间又能看到异常高价商品的存在。地图热力那块因为前面已经做了地域字段归一化这里直接按省聚合就能展示不需要额外处理。5.3 后端接口的职责边界后端接口的设计不要做重活它只做三件事从MySQL读聚合结果、组装JSON结构、返回给前端。所有复杂的计算价格分位数、品类占比、相似度推荐都已经在批量任务里预先算好存进MySQL了。我在Flask里写的接口大概是这样的app.route(/api/price_distribution) def price_distribution(): # 从MySQL读取价格区间聚合结果 rows query_db(SELECT price_bucket, COUNT(*) as cnt FROM item_stats GROUP BY price_bucket) return {buckets: [r[0] for r in rows], counts: [r[1] for r in rows]}这个小设计让前后端联调非常顺畅前端改图表样式的时候根本不用动后端。还有一个容易被忽视的点所有从后端返回的字段名建议用英文前端渲染时再映射成中文避免JSON里直接塞中文key导致编码或兼容性问题。6. 从开发到答辩完整链路复盘与高频追问的应答口径项目开发完只是第一步这类毕业设计大部分分数在答辩环节。评委看的不只是你做了什么更重要的是你知不知道自己在做什么。我把自己做这个项目的完整链路以及踩过的坑整理一下同时也总结一下那些最容易被问到的问题应该怎么答。6.1 建议的开发顺序与版本管理整套系统建议按这样的顺序推进先做数据清洗和MySQL建表再做Hadoop伪分布式环境和HDFS数据导入然后做Spark统计分析脚本把统计结果写回MySQL表再做Flask后端接口做Vue可视化页面最后做协同过滤推荐模块。这个顺序的好处是每一阶段都有可见的产出数据库里有表了、HDFS里有文件了、指标表有数据了、网页能出图了、推荐结果能显示了。每一步有一个阶段成果心态上不容易崩进度也容易控制。版本管理方面强烈建议用Git从第一天就建立仓库。每个小阶段提交一次提交信息写清楚做了什么改动比如feat: add price distribution stats不需要多规范但一定要有。这样做有两个好处一是万一改挂了随时能回滚二是答辩前整理项目日志、写论文的系统实现章节时直接翻commit记录就能把所有细节还原出来非常省时间。6.2 答辩高频问题清单根据我当时被问到的以及身边同学被问到的问题以下几个出现频率最高Q1你的数据量有多大就这个量级用得着Spark吗这个问题如果不准备会直接被问翻。标准应答思路是分两层先说实话毕设阶段演示数据量在几万到几十万条单机Pandas确实能处理再讲架构设计的考虑整套系统是按照数据量增长到千万级别去设计存储和计算链路的之所以选择Spark是因为它提供了从单机到集群无缝扩展的能力当数据量增长时只需增加计算节点代码不用重写。最重要的是补一句系统里Spark计算部分已经和HDFS打通证明的不是数据量本身而是这条分布式处理链路是完整的。这个答法既诚实又展示了你对技术选型的思考。Q2为什么推荐算法选协同过滤为什么不选其他算法这个问题的核心是要展示你真的比较过方案。我的答案逻辑是协同过滤的核心优势是不需要对商品做任何内容理解只需要用户历史行为数据而二手商品标题、描述个性化极强内容特征难抽取所以协同过滤是合适的基线方案同时因为数据里只有隐式反馈没有显式评分所以需要在评分矩阵构造阶段做加权设计这也是本文章节4里的核心内容。如果继续追问你可以补充说如果想进一步提升可以引入商品文本向量做混合推荐大模型在这里也有发挥空间比如用文本嵌入模型把商品标题向量化用向量相似度做内容召回再让协同过滤做精排。这一句不仅回答了问题还顺势展示了题目里大模型这个关键词的思考。Q3推荐效果怎么评估你的推荐准不准二手场景下没有标准的测试集我当时用的方式是把用户行为数据按时间切分前80%做训练后20%做验证对用户实际产生的行为商品做命中率统计计算PrecisionK和RecallK。你可以说自己在离线阶段用这种方式给出一个基本评估同时补充说明在真实场景中更关注的是点击率和转化率由于没有线上环境所以以离线指标为准。另外我还会用几个具体case做演示比如找某个用户的历史浏览记录再展示系统推荐的Top5商品看品类是否一致这样演讲时更有说服力。6.3 可扩展的方向这套系统的架子搭完之后扩展方向其实很清晰一是把大模型接进来做商品描述摘要和自动问答让用户输入我想找一台两千左右、成色好的备用机系统用文本匹配加推荐召回给出一批候选再让大模型生成解释性推荐理由——这会是一个非常有亮点的加分项二是引入Kafka做实时数据流把用户点击行为实时写入消息队列再进Spark Streaming做实时统计整个系统就从离线分析升级到了准实时三是把推荐模块从离线批量计算改成在线服务用Redis缓存相似度矩阵用户请求时实时计算TopN。这些扩展不用在毕设里全部落地但写进展望章节会让论文和答辩的深度上一个台阶。7. 最后一点实操体会把这个项目从零到一完整做完我的感悟是这类全栈毕设题目真正的难点不在于某一个技术点有多深而在于怎么让六个技术栈协同工作形成完整闭环。最容易被卡住的地方往往不是算法而是环境配置、中文编码、端口冲突这种不起眼的细节。如果你正在做或准备做这个题目我的建议是先把整条数据链路跑通——哪怕先用十行假数据走一遍全流程确认HDFS能存、Spark能读、MySQL能回写、前端能出图再回头去填充数据和优化细节。这个顺序能帮你省掉大量的内耗时间。遇到问题的时候优先看日志不要瞎猜Hadoop的logs目录、Spark的报错堆栈、Vue的浏览器控制台都是帮你定位问题的第一现场。做完之后你会发现这个题目虽然看起来什么都要会但每一层能讲到什么程度主动权完全在你手里。
返回列表