找回密码
 立即注册
搜索
查看: 10|回复: 0

厨房菜品十不出-厨房菜品出品标准口诀-厨房菜品的出菜流程

[复制链接]

2万

主题

0

回帖

6万

积分

管理员

积分
65081
发表于 2025-4-8 16:13:52 | 显示全部楼层 |阅读模式
目录

概要

本文的主题是获取下厨房网站月度最佳栏目近十年的数据,接着进行数据清洗和处理,之后生成所需的数据库表,最后进行数据可视化。所用到的技术栈包含网络爬虫、数据分析、Scala 引擎以及 Flask 框架等,在这些技术中,会着重讲解使用 Scala 进行数据处理的过程,而其他步骤则只是简单提及。

源数据获取

可以看见,本次的数据源来自下厨房网站的月度最佳栏目。这个栏目拥有 2011 年 3 月至 2023 年 10 月的连续数据。其中每个月有 50 道当月最受欢迎的菜品。每个菜谱被点击后,不但有菜名和详细用料,还贴出了具体步骤。

如图,运用所学知识,编写爬虫代码来对网站进行解析以及爬取数据。接着,经过简单的处理后,将数据存储到 MySQL 数据库中,并另存为 csv 表格以便留档。本次仅仅获取了 2015 年 5 月到 2023 年 10 月这近 10 年的数据。

可以看见获取的数据包含十个字段,这些字段包含菜名、链接、做法等信息。在这些字段中,收藏人数字段和最佳年月字段是整型,而其余的字段都是文本类型。

Scala介绍与数据处理 1.Sacla介绍

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

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

2.Scala数据处理流程

现在数据库中已经存在源数据,接着就要开展数据处理工作。在此,我所选用的技术是 Scala 引擎。对于不熟悉的小伙伴,你们可以上网去查看该技术的语法格式以及注意事项,我就不再做过多的阐述,而是直接进行代码解读。首先,必须明确处理的目标以及步骤,通过对数据进行查看,我设定了 5 个指标,并附上了指标说明和相关代码。

这里先对去重后的数据按照作者 id 进行分组,接着聚合行数从而得到菜品数量,再聚合收藏人数以得到收藏数量,最后调用 write 方法把处理后的数据存储到新的数据表以及集群的 hdfs 组件中。

<p><pre>    <code class="language-Scala">查询数据源中属于某一个作者的菜品以及其总收藏量分别是多少,将前 100 个作者保存下来并进行存储。
通过“作者 id”对 de_Data 进行分组,得到的结果记为 num_foods 。
      .agg(functions.count("*")
        .alias("菜品数量"),
      functions.sum("收藏人数")
        .alias("总收藏数量"))
按照“菜品数量”进行降序排序,然后限制结果为 100 条。
    //打印看看结果是否出来
    num_foods.show();
System 输出了 "*************菜谱数量 top100*********"
    //存储至本地数据库
num_foods.write.mode为 SaveMode.Overwrite ,然后通过 jdbc 连接到 url ,将数据写入到 "foods_num" 表中,同时使用 prop 进行相关配置。
    //存储到hdfs
num_foods 以 parquet 格式进行写入操作。
      .option("header", "true")
      .option("encoding", "UTF-8")
      .mode("overwrite")
将数据保存到“hdfs://20210322045-master:9000/term_data/foods_num”这个路径中。</code></pre></p>
首先,对最佳年月字段进行处理,把它转换成年份,然后创建临时视图。接着,运用 SQL 语句去查询不同年份里收藏人数最多的前 10 道菜,进而生成临时视图。最后,从这个临时视图中选取字段,按照年份升序以及收藏人数降序来进行排序,并且展示前 100 行的结果。将所得的结果数据保存到本地数据库以及 HDFS 中。

<p><pre>    <code class="language-Scala">    //2 查询数据里面不同年份最多收藏人数的前10菜品
    // 将最佳年月字段转换为年份
    System.out.println("做到第二题了")
val de_year 对 de_Data 进行了重命名操作,将其中的“收藏人数”重命名为“sl”。
创建或替换临时视图 foods,其名称为 de_year
spark 执行 SQL 语句“SELECT *, 将`最佳年月`字段的从第 1 个字符开始到第 4 个字符截取出来并转换为整数类型作为 year 字段 FROM foods”
创建或替换临时视图("foods_with_year")
    // 查询不同年份中收藏人数最多的前10道菜
通过 spark.sql 执行查询,查询语句为“SELECT * FROM (SELECT *, row_number()”,从中选取相关内容,这里选取了年份相关的数据,具体来说就是获取了特定的年份信息。
在按照 year 进行分区并且按照 sl 降序排序的情况下,通过 OVER 函数得到的结果作为 rank_no,然后从 foods_with_year 这个表中选择出满足 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)
    //存储到hdfs
    foods_year.write.format("parquet")
      .option("header", "true")
      .option("encoding", "UTF-8")
      .mode("overwrite")
      .save("hdfs://20210322045-master:9000/term_data/foods_year")</code></pre></p>
<p><pre>    <code class="language-Scala">根据创建时间添加一个字段叫季节,3 月到 5 月属于春季,6 月到 8 月属于夏季。
根据季节进行分组计数,算出每个季节收藏数量的情况,然后找出每个季节收藏数量排名前 5 的菜品。
    // 添加季节字段
使用`de_Data`并通过`withColumn`方法添加“季节”列,在添加过程中使用`when`函数根据“创建时间”的月份来确定季节。具体来说,就是通过`month(col("创建时间"))`获取创建时间的月份,然后根据月份的不同来设置“季节”的值。
在 3 和 5 之间,“春季”。当月份为创建时间的列时
在 6 到 8 之间,是“夏季”。当月份为创建时间这一列的月份时
如果在 9 到 11 之间,就是“秋季”,否则就是“冬季”。
    // 把季节改成英文方便开窗函数运行
data_jj 把“季节”这个列名重命名为“season”
data_jj 对列名进行了重命名操作,将原来的“收藏人数”重命名为“sl”。
创建临时视图,名称为"data_jj",由"data_jj"创建。
窗口规格为通过“season”进行分区,并按照“sl”的降序进行排序,即 Window.partitionBy("season").orderBy(functions.desc("sl")) 。
data_jj1 这个数据通过 withColumn 方法添加了一个名为“rank_no”的列,这个列的值是通过 row_number.over(windowSpec)计算得到的。
按照表达式“CASE season”进行排序,具体情况如下:如果 season 为“winter”,则按照相应的规则进行排序;如果 season 为“spring”,则按照相应的规则进行排序;如果 season 为“summer”,则按照相应的规则进行排序;如果 season 为“autumn”,则按照相应的规则进行排序。
        "WHEN &#39;春季&#39; THEN 1 " +
        "WHEN &#39;夏季&#39; THEN 2 " +
        "WHEN &#39;秋季&#39; THEN 3 " +
        "WHEN &#39;冬季&#39; THEN 4 " +
("ELSE 5 " + "END"), 然后是 col("rank_no")
使用 filter 函数,筛选出 rank_no 小于等于 5 的数据。
System.out.println("每个季节收藏数量排名前 5 的菜品")
    //       将数据存储到本地数据库和hdfs集群
    //保存模式为覆盖
data_jj1 以覆盖模式写入。通过 jdbc 连接到指定的 url,将数据写入到 "foods_season" 表中,并使用 prop 进行相关配置。
    //存储到hdfs
data_jj 以 parquet 的格式进行写入。
      .option("header", "true")
      .option("encoding", "UTF-8")
      .mode("overwrite")
将数据保存到“hdfs://20210322045-master:9000/term_data/foods_season”这个路径中。</code></pre></p>
先将数据加载至临时视图中,以便后续进行查询操作。接着使用 SQL 语句进行查询,依据年份对每个作者的收藏数量进行汇总,然后按收藏数量降序进行排名。再取每年收藏数量位居前 3 的作者以及总收藏量数据,把结果保存在名为特定名称的临时视图里。之后从该临时视图中查询结果并展示出来。最后将结果数据保存到本地数据库中,且使用覆盖的保存模式。把结果数据保存在 HDFS 里,其数据格式是[具体格式],并且采用覆盖的保存模式。

<p><pre>    <code class="language-Scala">    //4每年收藏数量前3的作者和总收藏量
mysql_da 创建了临时视图“ws_data”。
spark 执行 SQL 语句,选择“最佳年月”、“作者 id”以及“年收藏量”。
ROW_NUMBER() 按照 `最佳年月` 除以 100 取整进行分区,再按照 `收藏人数` 的最大值降序排序,所得结果作为 `排名` 。
最后在子查询中添加条件“排名”。<= 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)
    //存储到hdfs
    fsj.write.format("parquet")
      .option("header", "true")
      .option("encoding", "UTF-8")
      .mode("overwrite")
      .save("hdfs://20210322045-master:9000/term_data/foods_nscl")</code></pre></p>
先将数据加载至临时视图"",以准备后续查询。接着通过 SQL 语句查询每个最佳年月的作者的年收藏量,并依排名排序,将结果保存在""临时视图中。然后从""视图中提取出年份、作者 ID 和年收藏量的数据。最后计算每年的总收藏人数增长趋势,包含计算增长率并展示结果。把结果数据保存在本地数据库里,采用覆盖的保存模式。把结果数据保存在 HDFS 中,数据格式为(此处未提及具体数据格式),同样使用覆盖的保存模式。

<p><pre>    <code class="language-Scala">    //5.每年的收藏率趋势
mysql_da 创建了一个临时视图,名为 "ws_data1"。
    // 查询每个最佳年月的作者的年收藏量,并按照排名进行排序
spark 执行 SQL 语句“SELECT `最佳年月`, `作者 id`, SUM(`收藏人数`) AS `年收藏量`”,然后在查询结果中,对于每一行数据,将`最佳年月`、`作者 id`以及`收藏人数`的总和(即`年收藏量`)进行计算和汇总。
ROW_NUMBER() 按照 `最佳年月` 除以 100 取整进行分区,再按照 `收藏人数` 的最大值降序排序,得到的结果作为 `排名` 。
按照`最佳年月`和`排名`进行排序。
创建或替换临时视图“foods_zly”。
    // 提取年份、作者ID和年收藏量
使用 Spark 的 SQL 语句进行查询,从 foods_zly 表中选择将`最佳年月`字段的前 4 个字符转换为整数类型并命名为`年份`,同时选择`作者id`和`年收藏量`字段。具体的 SQL 语句为:SELECT CAST(SUBSTRING(`最佳年月`, 1, 4) AS int) AS `年份`, `作者id`, `年收藏量` FROM foods_zly;
    // 计算每年的总收藏人数增长趋势
趋势是通过 zzl 按照“年份”进行分组得到的。
      .agg(sum("`年收藏量`")
        .as("总收藏人数")).orderBy("`年份`")
    // 计算增长率
窗口规格 1 是按照“年份”进行排序的窗口
趋势等于趋势加上带有“前一年收藏人数”列的操作,该列是对“总收藏人数”列进行滞后 1 步的操作。
在 windowSpec1 上进行操作后,接着使用 withColumn 方法添加一个名为“增长率”的列。
先将`总收藏人数`转换为 double 类型,再将`前一年收藏人数`转换为 double 类型,接着用`总收藏人数`除以`前一年收藏人数`,得到的结果再减去 1,最后对这个结果进行四舍五入,保留两位小数。
      .drop("前一年收藏人数")
    trend.show()
趋势将写入模式设置为覆盖模式,并通过 JDBC 连接到指定的 URL("foods_zzl"),同时使用指定的属性 prop 进行连接操作。
    //存储到hdfs
    trend.write.format("parquet")
使用了.option("header", "true")和.option("encoding", "UTF-8")这两个设置。
      .mode("overwrite")
将数据保存到“hdfs://20210322045-master:9000/term_data/foods_zzl”这个路径中。</code></pre></p>
查看处理后的数据

数据可视化

首先进行数据可视化展示,通过读取 Spark 处理并存储到数据库的数据,接着将其加工成所需类型,然后转成 json 格式,以便后面大屏读取。下面是部分处理代码:

随后新建html文件,在里面添加各项依赖后,在
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|【宏智网络】 ( 京ICP备20013102号 )

GMT+8, 2025-5-15 02:21 , Processed in 0.122886 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表