效果展示:
实现目标:
- 构建一个网页应用将美团美食数据以可视化的形式展示出来:
- 在页面顶部,展示一个标题为“美团成都餐饮店铺分析”的大标题;
- 在页面中央,展示三个列,分别用于显示区域选择框、性价比排行榜和店铺信息;
- 区域选择框位于第一列,用于选择不同的区域,可选项为“成华区”、“金牛区”、“龙泉驿区”、“郫都区”、“青白江区”、“双流区”、“温江区”、“武侯区”、“新都区”和“新津区”;
- 选择不同的区域后,第一列会显示该区域的店铺类型分布饼图,第二列会显示该区域的性价比排行榜,第三列会显示该区域的店铺信息;
- 性价比排行榜和店铺信息都是按照性价比从高到低排序;
- 店铺信息包括店铺名、评分、商圈、人均消费、店铺类型和评论数,并且每个关键字都能单独进行排序;
-
代码_爬虫部分:
- 注意:url内的参数需要自己填充!
-
import requests # 数据请求模块 import csv import time import random areaList = [ '锦江区美食', '青羊区美食', '金牛区美食', '武侯区美食', '成华区美食', '龙泉驿区美食', '青白江区美食', '新都区美食', '温江区美食', '双流区美食', '郫都区美食', '新津区美食', ] areaFileNameList = [ 'meituandata_jinjiangqu.csv', 'meituandata_qingyangqu.csv', 'meituandata_jinniuqu.csv', 'meituandata_wuhouqu.csv', 'meituandata_chenghuaqu.csv', 'meituandata_longquanyiqu.csv', 'meituandata_qingbaijiangqu.csv', 'meituandata_xinduqu.csv', 'meituandata_wenjiangqu.csv', 'meituandata_shuangliuqu.csv', 'meituandata_piduqu.csv', 'meituandata_xinjinqu.csv', ] areaDict = dict(zip(areaList,areaFileNameList)) for areaName,fileName in areaDict.items(): f = open(fileName, mode = 'a+', encoding = 'utf-8-sig', newline = '') csv_write = csv.DictWriter(f, fieldnames = [ '店铺名', '评分', '商圈', '人均消费', '店铺类型', '评论数', '详情页', ]) # 写入表头 csv_write.writeheader() for page in range(0, 96, 32): time.sleep(random.randint(0,10)) # url的?后面的都是请求参数 url = 'https://apimobile.meituan.com/group/v4/poi/pcsearch/59' # url请求参数如下 data = { 'uuid' : '******************.**********.*.*.*', 'userid' : '**********', 'limit' : '32', 'offset' : page, 'cateId' : '-1', 'q' : areaName, 'token' : '*****_********-r4zWDLQIsQKrGXHtsMPkKY_1-0pId9Uq9V4KQN-YAwbULseE39PdnciHejVjMdAAAAADjGAA**********_iXXyJ3C1JqbEAfC8WfQARbM5l3a-g8phAMaWn-DDAiq1kc2oqSd71r' } # 请求头伪装 headers = { 'Referer' : 'https://cd.meituan.com/', # 防盗链 不加这个可能会报403,如果还不能访问,那就还要加上cookie 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36' } # 获取数据 response = requests.get(url=url, params=data, headers=headers) # 解析数据 searchResult = response.json(strict=False)["data"]["searchResult"] for index in searchResult: # 字符串格式化 href = f'https://www.meituan.com/meishi/{index["id"]}/' dit = { '店铺名' : index["title"], '评分' : index["avgscore"], '商圈' : index["areaname"], '人均消费' : index["avgprice"], '店铺类型' : index["backCateName"], '评论数' : index["comments"], '详情页' : href, } # 保存数据 csv_write.writerow(dit)
代码_可视化部分:
- 此部分代码可直接使用!
- 注意:爬取的数据存放的.csv文件要放在代码同级目录下的data文件夹下
-
import streamlit as st import matplotlib.pyplot as plt import pandas as pd st.set_page_config(page_title="myPage", page_icon="🧊", layout="wide") plt.rcParams['font.sans-serif'] = 'SimHei' # 使用SimHei字体显示中文 plt.rcParams['axes.unicode_minus'] = False # 使用 ASCII 中的 '-' 符号来代替unicode中的 '-',防止乱码 file_suffix_dict = { '成华区': 'chenghuaqu', '金牛区': 'jinniuqu', '龙泉驿区': 'longquanyiqu', '郫都区': 'piduqu', '青白江区': 'qingbaijiangqu', '双流区': 'shuangliuqu', '温江区': 'wenjiangqu', '武侯区': 'wuhouqu', '新都区': 'xinduqu', '新津区': 'xinjinqu', } def load_data(area:str): df = pd.read_csv(f'data/meituandata_{file_suffix_dict[area]}.csv',encoding='utf-8') df['性价比']=df['评分']*10+1/df['人均消费']*500 return df if 'curr_df' not in st.session_state: st.session_state['curr_df'] = load_data('成华区') def get_file_path(area:str): return f'data/meituandata_{file_suffix_dict[area]}.csv' data_dir = 'data/' df = pd.read_csv(data_dir+'meituandata_chenghuaqu.csv',encoding='utf-8') def on_select_area(): st.session_state['curr_df'] = load_data(st.session_state['area']) st.title('美团成都餐饮店铺分析') col1,col2,col3= st.columns([1,1,1.5]) with col1: st.selectbox('选择区域',file_suffix_dict.keys(),key='area',on_change=on_select_area) dl = st.session_state['curr_df']['店铺类型'] type_dict = {} for i in dl: type_dict[i] = type_dict.get(i,0)+1 fig = plt.figure() kl = [str(i) for i in type_dict.keys()] print(kl) plt.pie(type_dict.values()) plt.axis('equal') plt.title('店铺类型分布') plt.legend(labels=kl,loc='upper center',bbox_to_anchor=(0.5,-0.1),ncol=4) st.pyplot(fig,use_container_width=True) with col2: tdf = st.session_state['curr_df'][['店铺名','性价比']] tdf.sort_values(by='性价比',ascending=False,inplace=True) st.subheader('性价比排行榜') st.dataframe(tdf,hide_index=True,use_container_width=True) with col3: t2df = st.session_state['curr_df'][['店铺名','评分','商圈','人均消费','店铺类型','评论数']] st.subheader('店铺信息') st.dataframe(t2df,hide_index=True,use_container_width=True)
注意事项:
-
由于使用了streamlit包,由于未知原因,楼主自己也不知道为什么当安装的streamlit版本低于1.23.0时,显示界面将展示不完全,所以最好安装1.23及以上版本(python3.6最高支持1.10)