下厨房网站月度最佳栏目菜谱数据获取及分析PLus

 目录

概要

源数据获取

写Python代码爬取数据

Scala介绍与数据处理

1.Sacla介绍

 2.Scala数据处理流程

数据可视化

最终大屏效果

小结


概要

        本文的主题是获取下厨房网站月度最佳栏目近十年数据,最终进行数据清洗、处理后生成所需的数据库表,最终进行数据可视化。用到的技术栈有Python网络爬虫、数据分析、Scala引擎、Flask框架等,其中会重点讲解使用Scala数据处理的过程,其他步骤则是一笔带过。

源数据获取

  •         首先是源数据地址,网站来源于下厨房 (xiachufang.com),查看网站情况如下:

        可以看见,本次的数据源是下厨房网站里面的月度最佳栏目,该栏目有2011年3月到至今2023年10月的连续数据,其中每个月有50道当月最受欢迎菜品,每个菜谱点进去后,不仅有菜名、详细用料等,还贴出具体步骤。

  • 写Python代码爬取数据

        如图,利用所学知识,编写爬虫代码对网站进行解析并爬取数据,最后经过简单处理后存储至MySQL数据库并另存为csv表格留档,本次只获取了2015年5月至2023年10月近10年的数据

      可以看见获取的数据总共有十个字段,有菜名、链接、做法等信息,其中foods_id、收藏人数、最佳年月字段是整型,其余字段都是文本类型

Scala介绍与数据处理

        1.Sacla介绍

  • Scala是一种通用的编程语言,它结合了面向对象编程和函数式编程的特点,并且在大数据处理领域被广泛使用。

    Scala最初于2003年由Martin Odersky教授开发,并于2004年首次发布。Scala在Java虚拟机(JVM)上运行,可以与Java互操作,并且可以直接使用Java的库和工具。

    Scala的主要特点包括:

  • 静态类型系统:Scala是一种静态类型的语言,这意味着在编译时会进行类型检查,减少运行时错误。

  • 面向对象和函数式编程:Scala支持面向对象编程,可以使用类、继承和多态等概念。同时,Scala也支持函数式编程,提供了高阶函数、匿名函数和不可变数据结构等特性。

  • 表达力强大:Scala具有强大而灵活的语法,可以用更少的代码实现复杂的任务。它提供了模式匹配、高级类型推断和代数数据类型等功能,使编程变得更加简洁和易读。

  • 并发编程支持:Scala内置了并发编程库,提供了可以简化并发编程的抽象和工具。其中,最著名的是Akka框架,它提供了基于消息传递的并发模型。

在大数据处理领域,Scala通常与Apache Spark搭配使用。Spark是一个快速、通用的大数据处理引擎,Scala是其主要支持的编程语言之一。借助Scala的强大特性和Spark的分布式计算能力,开发人员可以编写高效、可扩展的大数据处理应用程序。

总而言之,Scala是一种强大的编程语言,特别适用于大数据处理和并发编程。它结合了面向对象和函数式编程的优点,并且在大数据处理领域有着广泛的应用和影响。

        2.Scala数据处理流程

        现在数据库已经有了源数据,接下来就是进行数据处理了。这里我选择的技术是Scala引擎,不熟悉的小伙伴可以上网查看该技术的语法格式和注意事项,我就不进行过多描述,直接进行代码解读。首先,要明确处理的目标和步骤,通过查看数据,我设立了5个指标,附上指标说明和代码:

  • 代码前文:mysql_da是数据库源数据,de_Data是根据菜名去重后的数据

  • 1 作者菜谱及收藏总量

        这里对去重后的数据,根据作者id进行分组,然后聚合行数即为菜品数量、聚合收藏人数即为中收藏数量,最后调用write方法将处理后的数据存储到新的数据表和Hadoop集群的hdfs组件

    //1 查询数据源里面属于一个作者的菜品和总收藏量有多少,保存前100个作者,存储下来val num_foods = de_Data.groupBy("作者id").agg(functions.count("*").alias("菜品数量"),functions.sum("收藏人数").alias("总收藏数量")).sort(functions.desc("菜品数量")).limit(100)//打印看看结果是否出来num_foods.show();System.out.println("*************菜谱数量top100*********")//存储至本地数据库num_foods.write.mode(SaveMode.Overwrite).jdbc(url, "foods_num", prop)//存储到hdfsnum_foods.write.format("parquet").option("header", "true").option("encoding", "UTF-8").mode("overwrite").save("hdfs://20210322045-master:9000/term_data/foods_num")
  • 2 历年收藏Top10
  1. 首先,对最佳年月字段进行处理,将其转换为年份,并创建临时视图"foods_with_year"。
  2. 接着,使用SQL语句查询不同年份中收藏人数最多的前10道菜,并生成临时视图"year_tab1"。
  3. 最后,从临时视图"year_tab1"中选取字段,并按年份升序、收藏人数降序排序,并展示前100行结果。
  4. 将结果数据保存至本地数据库和HDFS中。
    //2 查询数据里面不同年份最多收藏人数的前10菜品// 将最佳年月字段转换为年份System.out.println("做到第二题了")val de_year = de_Data.withColumnRenamed("收藏人数", "sl")de_year.createOrReplaceTempView("foods")spark.sql("SELECT *, CAST(SUBSTRING(`最佳年月`, 1, 4) AS int) as year FROM foods").createOrReplaceTempView("foods_with_year")// 查询不同年份中收藏人数最多的前10道菜val year = spark.sql("SELECT * FROM (SELECT *, row_number() " +"OVER (PARTITION BY year ORDER BY sl desc ) AS rank_no FROM foods_with_year ) tmp WHERE rank_no <= 10 ")//分两步进行sql查询,第一步是开窗函数进行分组统计,第二步是根据年份和收藏人数排序year.createOrReplaceTempView("year_tab1")val foods_year = spark.sql("select `year`, `菜名`,`用料食材和数量`, `链接地址`, `作者id`, `sl`,`rank_no` " +"from year_tab1 order by `year` asc, `sl` desc")foods_year.show(100, false)//存储至本地数据库foods_year.write.mode(SaveMode.Overwrite).jdbc(url, "foods_year", prop)//存储到hdfsfoods_year.write.format("parquet").option("header", "true").option("encoding", "UTF-8").mode("overwrite").save("hdfs://20210322045-master:9000/term_data/foods_year")
  •  3 历年收藏Top10
  • 首先,根据创建时间添加了一个名为“季节”的字段,根据不同的月份范围为每个菜品添加上了对应的季节信息,然后修改了字段名为“season”以方便后续处理。

  • 使用窗口函数,在每个季节内按收藏人数进行降序排名,并取出每个季节收藏数量排名前5的菜品,将结果存储在名为“data_jj1”的DataFrame中。

  • 将结果数据分别保存至本地数据库和HDFS中。在保存至本地数据库时,使用了覆盖的保存模式。

    //3 根据创建时间再添加一个字段:季节,比如3-5月是春季,6-8是夏季~//根据季节来进行分组计数,计算出每个季节收藏数量排名前5的菜品// 添加季节字段var data_jj = de_Data.withColumn("季节", functions.when(month(col("创建时间")).between(3, 5), "春季").when(month(col("创建时间")).between(6, 8), "夏季").when(month(col("创建时间")).between(9, 11), "秋季").otherwise("冬季"))// 把季节改成英文方便开窗函数运行data_jj = data_jj.withColumnRenamed("季节", "season")data_jj = data_jj.withColumnRenamed("收藏人数", "sl")data_jj.createTempView("data_jj")val windowSpec = Window.partitionBy("season").orderBy(functions.desc("sl"))val data_jj1 = data_jj.withColumn("rank_no", row_number.over(windowSpec)).orderBy(expr("CASE season " +"WHEN '春季' THEN 1 " +"WHEN '夏季' THEN 2 " +"WHEN '秋季' THEN 3 " +"WHEN '冬季' THEN 4 " +"ELSE 5 " + "END"), col("rank_no")).filter(col("rank_no").leq(5))System.out.println("*************每个季节收藏数量排名前5的菜品*********")//       将数据存储到本地数据库和hdfs集群//保存模式为覆盖data_jj1.write.mode(SaveMode.Overwrite).jdbc(url, "foods_season", prop)//存储到hdfsdata_jj.write.format("parquet").option("header", "true").option("encoding", "UTF-8").mode("overwrite").save("hdfs://20210322045-master:9000/term_data/foods_season")
  •  4 历年收藏Top10
  1. 将数据加载到临时视图"ws_data"中,以便后续查询操作。
  2. 使用SQL语句进行查询,按照年份对每个作者的收藏数量进行汇总,并按收藏数量降序排名。取每年收藏数量前3的作者和总收藏量数据,将结果保存在名为"foods_with_year"的临时视图中。
  3. 从"foods_with_year"视图中查询结果并展示。
  4. 将结果数据保存至本地数据库,并使用覆盖的保存模式。
  5. 将结果数据保存至HDFS中,数据格式为parquet,并使用覆盖的保存模式。
    //4每年收藏数量前3的作者和总收藏量mysql_da.createTempView("ws_data")spark.sql("SELECT `最佳年月`, `作者id`, `年收藏量`\n" +"FROM (\n" + "  SELECT `最佳年月`, `作者id`, SUM(`收藏人数`) AS `年收藏量`,\n" +"ROW_NUMBER() OVER(PARTITION BY FLOOR(`最佳年月` / 100) ORDER BY Max(`收藏人数`) DESC) AS `排名`\n" + "  " +"FROM ws_data\n" + "  GROUP BY `最佳年月`, `作者id`\n" + ") AS subquery\n" + "WHERE `排名` <= 3\n" + "ORDER BY `最佳年月`,`排名`").createOrReplaceTempView("foods_with_year")val fsj = spark.sql("SELECT CAST(SUBSTRING(`最佳年月`, 1, 4) AS int) as `年份` ,`作者id`, `年收藏量` FROM foods_with_year")fsj.show()//存储至本地数据库fsj.write.mode(SaveMode.Overwrite).jdbc(url, "foods_nszl", prop)//存储到hdfsfsj.write.format("parquet").option("header", "true").option("encoding", "UTF-8").mode("overwrite").save("hdfs://20210322045-master:9000/term_data/foods_nscl")

  •  5 历年收藏Top10
  1. 将数据加载到临时视图"ws_data1"中,为后续查询做准备。
  2. 使用SQL语句查询每个最佳年月的作者的年收藏量,并按照排名进行排序,将结果保存在名为"foods_zly"的临时视图中。
  3. 从"foods_zly"视图中提取年份、作者ID和年收藏量的数据。
  4. 计算每年的总收藏人数增长趋势,包括计算增长率,并展示结果。
  5. 将结果数据保存至本地数据库中,并使用覆盖的保存模式。
  6. 将结果数据保存至HDFS中,数据格式为parquet,并使用覆盖的保存模式。
    //5.每年的收藏率趋势mysql_da.createTempView("ws_data1")// 查询每个最佳年月的作者的年收藏量,并按照排名进行排序spark.sql("SELECT `最佳年月`, `作者id`, SUM(`收藏人数`) AS `年收藏量`,\n" + "" +"ROW_NUMBER() OVER(PARTITION BY FLOOR(`最佳年月` / 100) ORDER BY MAX(`收藏人数`) DESC) AS `排名`\n" +"FROM ws_data1\n" + "GROUP BY `最佳年月`, `作者id`\n" + "ORDER BY `最佳年月`,`排名`").createOrReplaceTempView("foods_zly")// 提取年份、作者ID和年收藏量val zzl = spark.sql("SELECT CAST(SUBSTRING(`最佳年月`, 1, 4) AS int) AS `年份`, `作者id`, `年收藏量` FROM foods_zly")// 计算每年的总收藏人数增长趋势var trend = zzl.groupBy("`年份`").agg(sum("`年收藏量`").as("总收藏人数")).orderBy("`年份`")// 计算增长率val windowSpec1 = Window.orderBy("年份")trend = trend.withColumn("前一年收藏人数", lag("`总收藏人数`", 1).over(windowSpec1)).withColumn("增长率",round(expr("(cast(`总收藏人数` as double) / cast(`前一年收藏人数` as double)) - 1"), 2)).drop("前一年收藏人数")trend.show()trend.write.mode(SaveMode.Overwrite).jdbc(url, "foods_zzl", prop)//存储到hdfstrend.write.format("parquet").option("header", "true").option("encoding", "UTF-8").mode("overwrite").save("hdfs://20210322045-master:9000/term_data/foods_zzl")

查看处理后的数据

 foods_year

 foods_season

foods_num

foods_zzl

foods_nszl

数据可视化

        最后是数据可视化展示,用python将Spark处理存储到数据库的数据读取,并且将其加工成所需类型后转成json格式,供后面大屏读取用,下面是部分处理代码:

        随后新建html文件,在里面添加各项依赖后,在<script>标签里面添加一下Echarts的配置项,并用Ajax技术读取刚才处理好的json文件传入给配置项后,即可在通过Flask框架在网页上渲染出数据大屏

最终大屏效果

小结

        项目到这里就算是完成了,做的时候其实涉及到的技术栈还是蛮多的,虽然都不是很深,但是途中也遇到了各种各样的困难。特别是用Scala技术进行数据处理时,由于对语法的不熟悉报了很多错、还有数据库数据的格式和提取转换难点等问题。后面都一一解决了,

这次的项目让我得到了成长和提升,让我也对所学知识进行了学以致用,融会贯通。

        最后感谢给我传授知识的广林哥、川哥等老师,祝你们家庭和睦,工作顺利。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/151183.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JPA整合Sqlite解决Dialect报错问题, 最新版Hibernate6

前言 我个人项目中&#xff0c;不想使用太重的数据库&#xff0c;而内嵌数据库中SQLite又是最受欢迎的&#xff0c; 因此决定采用这个数据库。 可是JPA并不支持Sqlite&#xff0c;这篇文章就是记录如何解决这个问题的。 原因 JPA屏蔽了底层的各个数据库差异&#xff0c; 但是…

竞赛 题目:基于深度学习的中文对话问答机器人

文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分&#xff1a;4.2 损失函数&#xff1a;4.3 搭建seq2seq框架&#xff1a;4.4 测试部分&#xff1a;4.5 评价NLP测试效果&#xff1a;4.6 梯度截断…

亚马逊第二个大语言模型 Olympus 即将上线

据外媒爆料&#xff0c;亚马逊正在训练他的第二个大语言模型——Olympus&#xff0c;很有可能在今年12月份上线。亚马逊计划将Olympus接入在线零售商店、Echo等设备上的Alexa语音助手&#xff0c;并为AWS平台提供新的功能。据说这个大语言模型规模达到2万亿&#xff08;2000B&a…

读《Segment Anything in Defect Detection》

摘要 (好像只是说把SAM应用到了红外缺陷分割领域) 引言 无损检测得到红外图像&#xff0c;根据热能观察异常 贡献&#xff1a; •从两个光学脉冲热成像系统构建广泛的缺陷热数据库&#xff0c;包括各种材料并释放它们。 • 开发DefectSAM&#xff0c;这是第一个用于缺陷检测…

MAC地址注册的网络安全影响和措施分析

MAC地址注册对网络安全具有重要影响&#xff0c;同时也需要采取相应的措施来应对潜在的安全风险。以下是有关MAC地址注册的网络安全影响和应对措施的分析&#xff1a; 影响&#xff1a; 1. 身份验证&#xff1a;MAC地址注册可用于设备的身份验证&#xff0c;但MAC地址本身并不…

不标年份的葡萄酒质量好吗?

我们在葡萄酒标上经常看到生产年份&#xff0c;也就是指全部葡萄采摘的年份。旧世界葡萄酒产国认为葡萄酒年份对他们的影响较大&#xff0c;而新世界葡萄酒&#xff0c;年份的意义就稍微小些。甚至有一部分葡萄酒酒标上没有年份。在酒标上没有标注年份的葡萄酒&#xff0c;被称…

学习无人机代码框架【第一天】---VMware 安装Ubuntu16.04时显示不全的解决方法

ros环境配置篇 环境配置在vmware上安装ubantu16.04操作系统安装完成后显示界面太小解决办法其他遇到的一些ubantu问题最后一步是在ubantu16上安装ros-kinetic其他很重要的一个工具是安装vmware-tool&#xff0c;可以支持把外部的文件或文字传入到虚拟机中管理不同的终端的软件代…

[C/C++] 数据结构 LeetCode:用队列实现栈

题目描述: 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压入栈顶。int pop() 移除并返回栈顶元…

kubernetes集群编排——etcd

备份 从镜像中拷贝etcdctl二进制命令 [rootk8s1 ~]# docker run -it --rm reg.westos.org/k8s/etcd:3.5.6-0 sh 输入ctrlpq快捷键&#xff0c;把容器打入后台 获取容器id [rootk8s1 ~]# docker ps 从容器拷贝命令到本机 docker container cp c7e28b381f07:/usr/local/bin/etcdc…

最大子段和(分治法+动态规划法)

求最大子段和 此类问题通常是求数列中连续子段和的最大值&#xff0c;经典的股票问题就是考察的这个思想及拓展。 例题&#xff1a; AcWing:1054. 股票买卖 Leetcode:53. 最大子数组和 分治法O(nlogn) 此类问题时分适合采用分治思想&#xff0c;因为所有子区间 [ s t a r t …

要事第一:如何通过6个步骤确定项目的优先级

当收到很多项目请求并且每个请求都是重中之重时&#xff0c;该怎么办&#xff1f;从最易完成的开始&#xff1f;还是先解决最大的问题&#xff1f; 实际上两种做法都不对。确定项目优先级的更好方法是评估以下内容&#xff0c;而不是关注项目规模或完成时长&#xff1a; ● 每…

DBeaver连接本地MySQL

原文&#xff1a; DBeaver21.3.0安装与连接本地MySQL_dbeaver创建本地数据库_傅大胖的博客-CSDN博客 其他&#xff1a; mysql 的驱动下载地址&#xff1a; Central Repository: mysql/mysql-connector-java ​​​​​​​

三相异步电机动态数学模型及矢量控制仿真

文章目录 三相异步电机动态数学模型及矢量控制仿真1、异步电机三相方程2、坐标变换3、磁链3/2变换推导4、两相静止坐标系下的方程5、两相旋转坐标系下的方程6、以 ω-is-Ψr 为状态变量的状态方程7、矢量控制及 matlab 仿真 原文链接需要仿真的同学请关注【Qin的学习营地】 三相…

百云齐鲁 | 云轴科技ZStack成功实践精选(山东)

山东省作为我国重要的工业基地和北方地区经济发展的战略支点&#xff0c;在“十四五”规划中将数字强省建设分为数字基础设施、数字科技、数字经济、数字政府、数字社会、数字生态六大部分&#xff0c;涵盖政治、经济、民生等多个方面&#xff0c;并将大数据、云计算、人工智能…

统一身份认证平台之SSO建设

前言 上篇说道Passwordless无密码技术&#xff0c;也提到了数字时代密码管理的难度&#xff0c;其实在日常的生活中&#xff0c;很多用户也会因为忘记某些网站的登录密码而烦恼。为了方便记忆&#xff0c;很多人都在不同的站点使用相同的用户名和密码&#xff0c;虽然也可以减少…

uvm环境获取系统时间的方法和使用案例

背景&#xff1a; 有时候我们想统计一下验证环境中某个步骤总共花费了多少时间&#xff0c;有什么比较方便的方法呢&#xff0c;利用$realtime理论上也是能做到的&#xff0c;不过这个和timescale绑定起来了&#xff0c;需要手动换算成单位是秒的数&#xff0c;现在提供一种利用…

未来之路:互联网技术驱动汽车行业的创新浪潮

在互联网迅猛发展的今天&#xff0c;它的触角已延伸至各行各业&#xff0c;其中最引人注目的莫过于汽车行业。随着互联网技术的融合&#xff0c;汽车正变得越来越智能&#xff0c;预示着一场关于出行方式的革命。 首先&#xff0c;自动驾驶技术的发展正日益成熟。依托先进的传感…

josef约瑟 闭锁继电器 LB-7DG 100V 50HZ 导轨安装

LB-7型闭锁继电器 闭锁继电器LB-7导轨安装 一、用途 LB-7型闭锁继电器(以下简称继电器)用于发电厂及变电所内高压母线带电时防止和接地刀闸。 二、结构和工作原理 1、继电器按整流式原理构成&#xff0c;该继电器由变压器、电阻器、整流桥、滤波电容、极化继电器及指示灯组…

【C++初阶】STL详解(四)vector的模拟实现

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…

使用Lychee搭建个人图片存储系统并进行远程访问设置实现公网访问本地私人图床

文章目录 1.前言2. Lychee网站搭建2.1. Lychee下载和安装2.2 Lychee网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 图床作为图片集中存放的服务网站&#xff0c;可以看做是云存储的一部分&#xff0c;既可…