【Python爬虫课程设计】下厨房网站-数据爬取+可视化
一、选题的背景
下厨房是一个美食社区网站,提供了海量的菜谱,菜系,饮食行业信息。这些数据反映了用户的饮食偏好、烹饪习惯、口味需求等,具有很高的研究价值。通过对下厨房网站的数据爬取和可视化分析;分析不同菜系的受欢迎程度,找出最受用户喜爱的菜系和菜品。从多个角度探索和挖掘美食的规律和趋势,为相关行业提供有用的参考。从社会上,可以增进对美食文化的了解和认识,提高生活品质和幸福感;从经济上,可以为美食行业提供市场分析和预测,帮助美食企业和个人提升竞争力和创新能力;从技术上,可以锻炼和提高Python网络爬虫和数据可视化的技能和水平培养数据思维和创造力。
二、主题式网络爬虫设计方案
1.主题式网络爬虫名称:爬取下厨房网站数据( https://www.xiachufang.com/ )
2.主题式网络爬虫爬取的内容与数据特征分析:
通过request爬取下厨房网站的信息,BeautifulSoup分析网页结构获取数据。内容为各菜系菜品名,食材菜料以及菜品评分和使用量信息。然后对数据进行可视化展示,根据数据的特点和分析的目的,绘制柱状图、折线图、饼图、散点图、词云图等,使用Python的可视化工具matplotlib对数据进行绘图使数据的特征更直观和清晰。
3.主题式网络爬虫设计方案概述:
实现思路
(1)使用Python的requests库和BeautifulSoup库,对下厨房网站的首页和各个分类页面进行请求和解析,获取菜谱的基本信息,如菜名、材料、评分、菜系,使用量等;
(2)对每个菜谱的详情链接,再次使用requests库和BeautifulSoup库,获取菜谱的具体做法、图片、视频等信息,并保存到本地或数据库中;
(3)使用pandas库,对爬取的数据进行清洗和处理,删除重复、缺失、错误的数据,转换数据的格式、类型、单位等,使数据符合分析的要求;
使用matplotlib库,对数据进行可视化分析,绘制各种图表,如柱状图、折线图、饼图、散点图、词云图等,展示数据的特征和规律,得到一些有意义的结论和发现。
技术难点:
(1)如何有效地爬取下厨房网站的数据,避免被反爬机制拦截或封禁,需要设置合理的请求头、请求间隔、代理IP;
(2)如何合理地选择和使用数据可视化的工具和图表,使数据分析的结果更直观和清晰,需要根据数据的特点和分析的目的,选择合适的图表类型、颜色、美化;
(3)如何深入地分析和解读数据,发现数据背后的逻辑和规律,提出有价值的建议和意见。
三、主题页面的结构特征分析
1.主题页面的结构与特征分析

从首页导航栏点击“菜单”进入“月度最佳”页面,页面侧边有其他排行分类以及流行搜索栏。内容为图片和菜名以及评分构成,可以让人一目了然的看清菜品,但页面的视觉效果美感还有待优化。
2.Htmls 页面解析

3.节点(标签)查找方法与遍历方法
使用 BeautifulSoup 库进行网页元素选择的代码。它通过 CSS 选择器来选取特定的 HTML 元素。
四、网络爬虫程序设计
爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后
面提供输出结果的截图。
- 数据爬取与采集,对数据进行清洗和处理



爬取和导入的代码:
import re
import pandas as pd
import xlrd
from lxml import etree
import requests
from bs4 import BeautifulSoup
from openpyxl.reader.excel import load_workbook
arr = ['30042', '30043', '30044', '52333', '1012138']
file_path = "score_ex.xlsx"
list_year = {"2012":0, "2013":300, "2014":600, "2015":900, "2016":1200, "2017":1500, "2018":1800, "2019":2100,"2020": 2400, "2021":2700, "2022":3000, "2023":3300,}
def xcf_zg():
headers = {
# 设置浏览器查看的设备名称
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.200',
# 从哪个网页跳转的
'Referer': 'https://www.btnull.org/',
# 该网页需要登录才可以访问
'Cookie': 'PHPSESSID=ht819kc7ult6uhe2sn4tql76ev; BT_auth=2ccfOD45gks8PbL9tpXGvwfqCiksaQzCfSGK0TMcBfR7ISTfS7TYIC3iLWDd6SiJfbRm6Ctaj-d0zgyJLVJ1K7KA0iZfzN34bpBkboj595gG3gMovOpifLGMpQ5Hpz5S96RzxF72fPZf-emB4iX50pcWIpH9VnYDLap0x0o; BT_cookietime=796aIRXeQPGo_yaLjgKXbjCGTXAroEFUz-L-v955kpdn7PNqG1Sg'
}
for year in range(2012, 2024):
# 读取 Excel 文件
df = pd.read_excel('score_ex.xlsx')
# 获取最大行数
max_rows = df.shape[0]
print("最大行数:", max_rows)
print(year)
for month in range(1, 13):
date_str = f'{year}{month:02d}'
url = 'https://www.xiachufang.com/explore/monthhonor/' + date_str
# requests 库发送一个 GET 请求到指定的 URL,并将响应结果存储在变量 req 中。
req = requests.get(url, headers=headers)
# 手动设置编码格式
req.encoding = 'utf-8'
# 使用 BeautifulSoup 解析响应
soup = BeautifulSoup(req.text, 'html.parser')
# 做过的人数
use_xcf = soup.select(
'body > div.page-outer > div > div > div.pure-u-2-3.main-panel > div.white-bg.block > div > div.pure-u-3-4.search-result-list > div.normal-recipe-list.honor-recipe-list > ul > li > div.pure-u-11-12 > div > div > p.stats > span:nth-child(2)')
# 过滤后的人数
use_xcf = [i.get_text() for i in use_xcf]
xcf_ex('peop_ex.xlsx', use_xcf)
# 评分
pf_xcf = soup.select(
'body > div.page-outer > div > div > div.pure-u-2-3.main-panel > div.white-bg.block > div > div.pure-u-3-4.search-result-list > div.normal-recipe-list.honor-recipe-list > ul > li > div.pure-u-11-12 > div > div > p.stats > span.score.bold.green-font')
pf_xcf = [i.get_text() for i in pf_xcf]
xcf_ex('score_ex.xlsx',pf_xcf,)
# 名称
name_xcf = soup.select(
'body > div.page-outer > div > div > div.pure-u-2-3.main-panel > div.white-bg.block > div > div.pure-u-3-4.search-result-list > div.normal-recipe-list.honor-recipe-list > ul > li > div.pure-u-11-12 > div > div > p.name > a')
name_xcf = [i.get_text() for i in name_xcf]
name_xcf = [i.replace('\n', ' ') for i in name_xcf]
xcf_ex('mz_ex.xlsx', name_xcf)
xcf_zg()
# # 定义函数 xcf_ex,接受两个参数:path(路径)和 data(数据)
def xcf_ex(path, data):
# 读取指定路径的 Excel 文件,将其存储在 DataFrame 对象 df 中
df = pd.read_excel(path)
# 将传入的数据转换为 DataFrame 对象 new_df
new_df = pd.DataFrame(data)
# 将 new_df 追加到 df 中,忽略索引
df = df._append(new_df, ignore_index=True)
# 将修改后的 df 保存回指定路径的 Excel 文件中,不包含索引
df.to_excel(path, index=False)
- 文本分析(可选):jieba 分词、wordcloud 的分词可视化
读取excel表中的菜名进行拼接处理,设置禁止词及最大生成数量生成词云图
![]()
词云图代码:
import jieba
import pandas as pd
from matplotlib import pyplot as plt
from wordcloud import WordCloud, wordcloud
#字体
font_path="Arial Unicode.ttf"
# 宽度
width=500
# 高度
height=700
# 颜色
background_color='white'
# 查询字的数量
max_words=2000
# 读取 Excel 文件
pf = pd.read_excel('mz_ex.xlsx', usecols=[0])
list = []
# 遍历表格内容,将每行数据添加到列表中
for item in pf.values:
list.append(item[0])
r_data = ''.join(list)
# 将列表转换为字符串
data = list
# 连接成字符串
str_list = ''.join(list)
# 生成分词列表
ls = jieba.lcut(r_data)
# 连接成字符串
text = ' '.join(ls)
# 设置停止词
stopwords = ["之","你","在","不"]
# 创建词云对象
wc = wordcloud.WordCloud(font_path=font_path,
width=width,
height=height,
background_color=background_color,
max_words=max_words,
stopwords=stopwords,)
# 生成词云
wc.generate(text)
# 保存词云文件
wc.to_file("wordcloud.png")
- 数据分析与可视化
饼图:
先对菜名进行菜系分类处理,在对各个菜系的使用人数进行统计计算后算平均值
![]()
饼图代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager
# 地址
path="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf"
# 设置字体路径
my_font = font_manager.FontProperties(fname=path)
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 打开 Excel 文件,需要将 score.xlsx 替换为正确的路径
pf = pd.read_excel('score_ex.xlsx')
# 每一块的颜色
colors = ['#FFCC00', '#FFB200','#FF9900', '#FF8000','#FF6600','#DD5300','#CC4000','#BB3300']
#平均各菜系使用人数
def calculate_average2(lst):
if len(lst) % 430 != 0:
# 如果列表长度不能被 430 整除,最后一个分组不足 430 个元素
lst = lst[:len(lst) - len(lst) % 430]
averages = []
for i in range(0, len(lst), 430):
# 每次循环处理 430 个元素
group = lst[i:i + 430]
average = sum(group) / len(group)
# 计算平均值并添加到平均值列表中
averages.append(average)
return averages
# 读取 Excel 文件
peop = pd.read_excel('peop_ex.xlsx')
score_avg = calculate_average2(peop.values)
list_sc = []
for i in score_avg:
list_sc.append(float(i[0]))
labels = ['清真菜','川菜','湘菜','粤菜','浙菜','东北菜','湖北菜','徽菜']
# 绘制饼图
plt.pie(list_sc, labels=labels, autopct='%1.1f%%',colors=colors)
# 添加标题
plt.title('各菜系使用热度饼图')
# 显示图形
plt.show()
柱形图和折线图:
对每年菜系评分进行统计计算平均值,得出每年评分平均热度并做柱形图和折线图

柱形图和折线图代码:
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib import font_manager
from pylab import mpl
import seaborn as sns
# 每月平均评分
# 设置字体路径
my_font = font_manager.FontProperties(fname="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf")
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
color = 'red'
#
def calculate_average(lst):
if len(lst) % 300 != 0:
# 如果列表长度不能被 300 整除,最后一个分组不足 300 个元素
lst = lst[:len(lst) - len(lst) % 300]
averages = []
for i in range(0, len(lst), 300):
# 每次循环处理 300 个元素
group = lst[i:i + 300]
average = sum(group) / len(group)
# 计算平均值并添加到平均值列表中
averages.append(average)
return averages
# 读取 Excel 文件
score = pd.read_excel('score_ex.xlsx')
score_avg = calculate_average(score.values)
list_sc = []
for i in score_avg:
list_sc.append(float(i[0]))
print(list_sc)
name = ['2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022', '2023']
# 创建图表
plt.figure(figsize=(10, 6))
plt.bar(name,list_sc, color='r')
plt.xlabel('年份')
plt.ylabel('热度')
plt.title('各年度菜谱平均热度')
# # 添加评分的折线图
plt.plot(name, list_sc, color='b', linestyle='--')
plt.show()
- 根据数据之间的关系,分析两个变量之间的相关系数,画出散点图,并建立变量之间的回归方程(一元或多元)。
取菜谱的评分和使用人数做散点图和回归线
![]()
散点图和回归线代码:
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib import font_manager
# 统计各个食材数量
ingredient_counts = {}
# 颜色
colors = 'red'
# 设置字体路径
path="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf"
my_font = font_manager.FontProperties(fname=path)
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 读取 Excel 文件
peop = pd.read_excel('peop_ex.xlsx')
score = pd.read_excel('score_ex.xlsx')
plt.scatter(score,
peop,
c = colors,
)
# 计算回归线
# 将 pay_money 的值转换为二维数组
X = score.values.reshape(-1, 1)
# 将 buy_count 的值转换为二维数组
y = peop.values.reshape(-1, 1)
# 创建 LinearRegression 模型
reg = LinearRegression()
# 使用数据进行拟合
reg.fit(X,y)
# 使用拟合得到的模型 reg 对 X 进行预测,并且设置线条颜色
plt.plot(X, reg.predict(X), color='green')
# 设置 X轴注解
plt.xlabel('评分')
# 设置 Y轴注解
plt.ylabel('使用人数')
# 设置 标题
plt.title('散点图 和 回归线')
# 显示图形
plt.show()
- 将以上各部分的代码汇总,附上完整程序代码
import re
import pandas as pd
import xlrd
from lxml import etree
import requests
from bs4 import BeautifulSoup
from openpyxl.reader.excel import load_workbook
from 下厨房.xcc_excel import xcf_ex
arr = ['30042', '30043', '30044', '52333', '1012138']
file_path = "score_ex.xlsx"
list_year = {"2012":0, "2013":300, "2014":600, "2015":900, "2016":1200, "2017":1500, "2018":1800, "2019":2100,"2020": 2400, "2021":2700, "2022":3000, "2023":3300,}
def xcf_zg():
headers = {
# 设置浏览器查看的设备名称
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.200',
# 从哪个网页跳转的
'Referer': 'https://www.btnull.org/',
# 该网页需要登录才可以访问
'Cookie': 'PHPSESSID=ht819kc7ult6uhe2sn4tql76ev; BT_auth=2ccfOD45gks8PbL9tpXGvwfqCiksaQzCfSGK0TMcBfR7ISTfS7TYIC3iLWDd6SiJfbRm6Ctaj-d0zgyJLVJ1K7KA0iZfzN34bpBkboj595gG3gMovOpifLGMpQ5Hpz5S96RzxF72fPZf-emB4iX50pcWIpH9VnYDLap0x0o; BT_cookietime=796aIRXeQPGo_yaLjgKXbjCGTXAroEFUz-L-v955kpdn7PNqG1Sg'
}
for year in range(2012, 2024):
# 读取 Excel 文件
df = pd.read_excel('score_ex.xlsx')
# 获取最大行数
max_rows = df.shape[0]
print("最大行数:", max_rows)
print(year)
for month in range(1, 13):
date_str = f'{year}{month:02d}'
url = 'https://www.xiachufang.com/explore/monthhonor/' + date_str
# requests 库发送一个 GET 请求到指定的 URL,并将响应结果存储在变量 req 中。
req = requests.get(url, headers=headers)
# 手动设置编码格式
req.encoding = 'utf-8'
# 使用 BeautifulSoup 解析响应
soup = BeautifulSoup(req.text, 'html.parser')
# 做过的人数
use_xcf = soup.select(
'body > div.page-outer > div > div > div.pure-u-2-3.main-panel > div.white-bg.block > div > div.pure-u-3-4.search-result-list > div.normal-recipe-list.honor-recipe-list > ul > li > div.pure-u-11-12 > div > div > p.stats > span:nth-child(2)')
# 过滤后的人数
use_xcf = [i.get_text() for i in use_xcf]
# xcf_ex('peop_ex.xlsx', use_xcf)
# 评分
pf_xcf = soup.select(
'body > div.page-outer > div > div > div.pure-u-2-3.main-panel > div.white-bg.block > div > div.pure-u-3-4.search-result-list > div.normal-recipe-list.honor-recipe-list > ul > li > div.pure-u-11-12 > div > div > p.stats > span.score.bold.green-font')
pf_xcf = [i.get_text() for i in pf_xcf]
xcf_ex('score_ex.xlsx',pf_xcf,)
# 名称
name_xcf = soup.select(
'body > div.page-outer > div > div > div.pure-u-2-3.main-panel > div.white-bg.block > div > div.pure-u-3-4.search-result-list > div.normal-recipe-list.honor-recipe-list > ul > li > div.pure-u-11-12 > div > div > p.name > a')
name_xcf = [i.get_text() for i in name_xcf]
name_xcf = [i.replace('\n', ' ') for i in name_xcf]
# xcf_ex('mz_ex.xlsx', name_xcf)
xcf_zg()
import pandas as pd
# # 定义函数 xcf_ex,接受两个参数:path(路径)和 data(数据)
def xcf_ex(path, data):
# 读取指定路径的 Excel 文件,将其存储在 DataFrame 对象 df 中
df = pd.read_excel(path)
# 将传入的数据转换为 DataFrame 对象 new_df
new_df = pd.DataFrame(data)
# 将 new_df 追加到 df 中,忽略索引
df = df._append(new_df, ignore_index=True)
# 将修改后的 df 保存回指定路径的 Excel 文件中,不包含索引
df.to_excel(path, index=False)
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib import font_manager
from pylab import mpl
import seaborn as sns
# 每月平均评分
# 设置字体路径
my_font = font_manager.FontProperties(fname="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf")
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
color = 'red'
#
def calculate_average(lst):
if len(lst) % 300 != 0:
# 如果列表长度不能被 300 整除,最后一个分组不足 300 个元素
lst = lst[:len(lst) - len(lst) % 300]
averages = []
for i in range(0, len(lst), 300):
# 每次循环处理 300 个元素
group = lst[i:i + 300]
average = sum(group) / len(group)
# 计算平均值并添加到平均值列表中
averages.append(average)
return averages
# 读取 Excel 文件
score = pd.read_excel('score_ex.xlsx')
score_avg = calculate_average(score.values)
list_sc = []
for i in score_avg:
list_sc.append(float(i[0]))
print(list_sc)
name = ['2013', '2014', '2015', '2016', '2017', '2018', '2019', '2020', '2021', '2022', '2023']
# 创建图表
plt.figure(figsize=(10, 6))
plt.bar(name,list_sc, color='r')
plt.xlabel('年份')
plt.ylabel('热度')
plt.title('各年度菜谱平均热度')
# # 添加评分的折线图
plt.plot(name, list_sc, color='b', linestyle='--')
plt.show()
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import font_manager
# 地址
path="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf"
# 设置字体路径
my_font = font_manager.FontProperties(fname=path)
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 打开 Excel 文件,需要将 score.xlsx 替换为正确的路径
pf = pd.read_excel('score_ex.xlsx')
# 每一块的颜色
colors = ['#FFCC00', '#FFB200','#FF9900', '#FF8000','#FF6600','#DD5300','#CC4000','#BB3300']
#平均各菜系使用人数
def calculate_average2(lst):
if len(lst) % 430 != 0:
# 如果列表长度不能被 430 整除,最后一个分组不足 430 个元素
lst = lst[:len(lst) - len(lst) % 430]
averages = []
for i in range(0, len(lst), 430):
# 每次循环处理 430 个元素
group = lst[i:i + 430]
average = sum(group) / len(group)
# 计算平均值并添加到平均值列表中
averages.append(average)
return averages
# 读取 Excel 文件
peop = pd.read_excel('peop_ex.xlsx')
score_avg = calculate_average2(peop.values)
list_sc = []
for i in score_avg:
list_sc.append(float(i[0]))
labels = ['清真菜','川菜','湘菜','粤菜','浙菜','东北菜','湖北菜','徽菜']
# 绘制饼图
plt.pie(list_sc, labels=labels, autopct='%1.1f%%',colors=colors)
# 添加标题
plt.title('各菜系使用热度饼图')
# 显示图形
plt.show()
import jieba
import pandas as pd
from matplotlib import pyplot as plt
from wordcloud import WordCloud, wordcloud
#字体
font_path="Arial Unicode.ttf"
# 宽度
width=500
# 高度
height=700
# 颜色
background_color='white'
# 查询字的数量
max_words=2000
# 读取 Excel 文件
pf = pd.read_excel('mz_ex.xlsx', usecols=[0])
list = []
# 遍历表格内容,将每行数据添加到列表中
for item in pf.values:
list.append(item[0])
r_data = ''.join(list)
# 将列表转换为字符串
data = list
# 连接成字符串
str_list = ''.join(list)
# 生成分词列表
ls = jieba.lcut(r_data)
# 连接成字符串
text = ' '.join(ls)
# 设置停止词
stopwords = ["之","你","在","不"]
# 创建词云对象
wc = wordcloud.WordCloud(font_path=font_path,
width=width,
height=height,
background_color=background_color,
max_words=max_words,
stopwords=stopwords,)
# 生成词云
wc.generate(text)
# 保存词云文件
wc.to_file("wordcloud.png")
from sklearn.linear_model import LinearRegression
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib import font_manager
# 统计各个食材数量
ingredient_counts = {}
# 颜色
colors = 'red'
# 设置字体路径
path="/Users/yukezhen/PycharmProjects/pythonProject1/动漫/Arial Unicode.ttf"
my_font = font_manager.FontProperties(fname=path)
# 应用字体到图形对象
plt.rcParams['font.family'] = my_font.get_name()
# 读取 Excel 文件
peop = pd.read_excel('peop_ex.xlsx')
score = pd.read_excel('score_ex.xlsx')
plt.scatter(score,
peop,
c = colors,
)
# 计算回归线
# 将 pay_money 的值转换为二维数组
X = score.values.reshape(-1, 1)
# 将 buy_count 的值转换为二维数组
y = peop.values.reshape(-1, 1)
# 创建 LinearRegression 模型
reg = LinearRegression()
# 使用数据进行拟合
reg.fit(X,y)
# 使用拟合得到的模型 reg 对 X 进行预测,并且设置线条颜色
plt.plot(X, reg.predict(X), color='green')
# 设置 X轴注解
plt.xlabel('评分')
# 设置 Y轴注解
plt.ylabel('使用人数')
# 设置 标题
plt.title('散点图 和 回归线')
# 显示图形
plt.show()
五、总结
川菜和湘菜是最受欢迎的菜系,菜谱使用量远超其他菜系,显示出它们在中国美食文化中的重要地位;不同菜系使用的材料差别也是很大的,生姜,蚝油出现的频率较高;不同月份的美食需求有所不同,例如春节期间,饺子、年糕、汤圆等菜谱的使用量和评分较高。这些结论基本达到了预期的目标,能够反映出中国菜系的特色和趋势,为美食爱好者和相关行业提供有用的参考和指导。
学习了Python网络爬虫的基本原理和技术,如requests、BeautifulSoup、pandas、matplotlib等库的使用方法。学习和掌握了数据清洗和处理的基本方法和技巧,以及数据可视化的基本方法和技巧,如选择合适的图表类型、颜色、美化,使数据分析的结果更直观和清晰;在爬取数据的过程中,要尽量遵守网站的robots协议,尊重网站的版权和隐私,不要对网站造成过大的负担和影响;在清洗和处理数据的过程中,要注意数据的完整性和一致性,避免数据的丢失和错误。




浙公网安备 33010602011771号