admin管理员组文章数量:1794759
大众点评餐厅数据分析(上海去哪吃)
作为标准的社畜吃货,一直有想着做一篇关于美食的数分内容,看看哪里工作的社畜最可怜,连吃美食的地方都没有,直到看到数据后我就又迷茫了,几百块的人均价堪比米其林,身边再多餐厅又有何用(手动狗头)。
言归正传,分析的第一步是数据的获取,在爬大众点评的餐厅的时候我差点就放弃了这个项目,他们的反爬真的很厉害(丧心病狂的那种),字符偏移、SVG、文字随机图片化(具体的问题大家可以参考git、csdn等),代理IP都没用,在手机流量超了1个G后,终于搞到了5000+数据。
大众美食首页美食里面的分类都对应着网址上的g**值,每个类别最多可以显示50页,最下面上代码。
因为不是每个菜系都是50页,所以最后的数据在5500家餐厅左右
共爬取:店铺名、店铺星级(空)、评论数、均价、店铺类型、商圈、地址、口味|服务|环境的评分共计10个字段。基于个人习惯,一般看到有详细地址的数据,我都会用百度地图api转换一下,最下面放转换地址的代码,篇幅原因,后续的分析代码就不上了,虾子的做法如果后续有需要我私发或者补上都可以。
调取百度地图的api,通过详细地址去获取经纬度。普通用户每天的逆向地理信调用是6千次,调试几次就用完了,建议感兴趣的童鞋可以注册为开发者(身份证认证),每天有30万的额度,基本够用了。这里获取店铺的经纬度、所属区和门址信,同大众点评上的商圈字段不同的是,百度的门址信是划分信,如(门牌号、车站、机场、商务楼……):
接下来就是一堆数据预处理的骚操作,删除重复数据、转变类型、填充或者删除无效信……
然后,然我们看现货黄金交易所一下大众点评的餐厅都分布在哪里吧:
如图下图所示,基本上分布在以“人民广场”为中心的辐射半径为6公里的区域内(蓝色圆圈),各行政区内的店铺用不同颜色的店标记出来了,果然市区贵是有原因的稀疏密集程度和上海的房价几乎一致,难道是餐厅导致的上海高房价?大家赶紧去抵制吃饭,饭店关门了上海房价就跌了(再次狗头),黄浦和徐汇几乎是全区高密。
市区范围外,还有些零散的聚地点,基本在川沙(张江码农集聚地)、紫藤路(高新科技园)、车站、机场(虹桥的聚集效果更强)、迪士尼(景区):
五角场上海各区域内的商圈数量,金山、青浦和奉贤这样的大郊区的商圈真的是屈指可数,市区虽然面积小但是商圈数据碾压郊区(浦东除外,浦东实在是太大了,还有陆家嘴这样的金融区),市区的商务办公地也多,办公——人多——商圈多——人多 大家互相成就,正向相关。
上海各区商圈数浦东的餐厅最多,黄浦其次,但想想两者的面积差,真的是恐怖(黄浦有226家咖啡店,小资情调MAX)
各区各类型餐厅数餐厅类型有日料、烧烤、咖啡厅等,我们探究下各个商圈下,每个商圈的餐厅类型有多少(该商圈所拥有的餐厅类型占整个上海餐厅类型的百分比),该指标反映商圈的繁荣度,餐厅类型越繁多,该商圈的人流量越大、越是繁华。
前六名分别是:淮海路(8.25%)、静安寺(5.39%)、人民广场(4.87%)、陆家嘴(4.64%)、虹桥(4.33%)、徐家汇(4.24%),的确是大家耳熟能详的地标商圈。敲下黑板,外地来旅游的朋友可以去这几个地点,繁华热闹,饮食上也绝对能满足您的口味。
各商圈内各类型餐厅的占比各个商圈的店铺数,各商圈数据均由下滑。但比较恐怖的是淮海路商圈,一条淮海路拥有整个上海地区5.12%的餐厅,一骑绝尘。怕不是整条路上全是餐厅?可怜我从小在淮海中路长大,也没吃几口好的(穷人在家吃)
各区商圈店铺数根据50以下、50-100、100-150这样的逻辑对人均消费分段,商圈大致以低价段-高价段递减的趋势,且淮海路商圈的100以下的人均店铺最多。值得一提的是陆家嘴商圈,其500以上人均消费的店铺比50-100人均的店铺还要多,不愧是金融凤凰男,我发四,以后再也不敢叫他们金融民工了。
综上:从商圈角度而言,如果想吃的好、选择多,那么淮海路你一定不能错过,但您要是为了见识“魔都”,体验番一掷千金的“壕爽”,看看这灯红酒绿的十里洋场,那么2号线陆家嘴站欢迎您(呸,劳斯莱斯幻影、迈巴赫去接您)。
说了那么久,那么大众上到底哪些餐厅收录最多呢?
东北菜占有量接近5%,说明不少同学来自东北,可以想象下,海南的东北菜占比会不会高达50%(手动狗头)。
咖啡厅占比12.73%,面馆占比7.43%,难道大家都是吃饭时扒拉两口面,然后赶紧买杯咖啡继续加班么?果然上海是座工作型城市。为了验证设想,我们通过商圈对比面馆和咖啡馆的数量,两者成完美的正相关
从百度的地址分类来看,收录的这五千多家餐厅,多以门址、购物、商务大厦和宾馆为主(依次递降)。
门址和购物的对比,基本分布一致,比较有意思的是门址的500+人家的餐厅远远大于其他类型地址。证明门址地点比较特殊,两级分化严重,要么是低端低消费的苍蝇馆子,要么就是高逼格、豪装的特色餐厅和外国料理。
购物地址和门址地址的人均价格段商务大空调箱厦和宾馆的对比同上图的人均分布比较大体一致,比较特殊的是,商务大厦人均最多的在50-100的价格段,宾馆人均消费最短的价格段在150-200。以写字楼白领为主商务大厦主打中低端商务餐,而宾馆的住宿人群出手较为豪气(无论出差还是旅游,肯定是舍得花钱的)。
商务大厦十三行地址和宾馆地址的人均价格段而餐厅类型最多的咖啡厅和面馆在百度地址上却无明显差役,分布几乎一致(在此不套路较小餐厅类型,烧烤餐饮肯定在商场的少啊)
大众点评上对于餐厅有三个关键的评分指标: 服务、环境、口味,我们将每家店铺的三个指标分想加求平均分,获取店铺的平均分,较为平均:
各类型餐厅评分各家店铺都会有大众劵、买单打折活动,但是不是每个人都会去写点评。无论好坏,评论数能够代表一家店铺的人气,而高评论店铺一定是优质店铺,不然差评会让店铺没有人气,同时高评也能够代表该类型的店铺人均消费较低,以实惠著称。
人均消费和评论的对比南京菜、烤鸭、粤式茶点、火锅、日式自助是评论均榜的前五,基本以本地菜系为主,唯一入选的日料还是自助餐。南京菜的评论多,让我再次明白一个道理:没有一个鸭子能活着游过秦淮河,没有一个人能错过南京大牌档……
各类型餐厅评论数食品保健类餐厅的人均价遥遥领先,人均价要到3000元,抛掉保健特色不谈,人均价从高到低依次为:特色菜、寿司、法国菜、日本铁板烧、江湖河海鲜。印象中奢华的法国菜反倒只排到了第三(671元/人),就是没有想到寿司人均能到达795,不都是几十块一盒么。。。
各类型餐厅均价(前20)写了很多,对于我们这样想尝鲜的小伙伴来说,选择什么类型的餐厅最不容易采坑呢?
此处通过人均得分+餐厅评论得分+三指标(环境、服务、口味)得分【对各类型餐厅均分排序,赋予1-n分,然后三项指喜临门床垫标得分累计计算出总分】,计算出更优质的餐厅类型,不易让大家采坑。
日料、粤菜馆、自助餐、西餐的综合评分最高,口味也更能迎合大部分人,也不易踩坑,本帮菜的得分也较高,外地朋友也值得一尝。
再次长痘痘怎么办对人均消费价进行划段,100元以内为经济型餐厅(应该去除咖啡厅的),100-150为普好看的古代言情小说推荐通型餐厅,150-250为小资型餐厅、250-350为轻奢类餐厅、350-500为昂贵型餐厅,500元以上为奢侈型餐厅。如下图所示,各区域内基本低消到高消递降,无论哪个城市,普罗大众才是最广泛的群体,最值得敬佩的群体。
这是第二次追加文章了,数据表、图太多,细分下来篇幅实在恐怖。毕竟兴趣使然,没有确切分析目标,文章到此告一段落,代码下复。
爬虫代码:
import requestsfrom requests.exceptions import RequestExceptionfrom bs4 import BeautifulSoupimport jsonimport timeimport randomfrom numba import jit#获取一页内容def get_one_page(url): headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Cache-Control': 'max-age=0', 'Connection': 'keep-alive', 'Cookie': '你的浏览器cookie', 'Host': 'www.dianping', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36' } proxiess=['39.105.104.1:3128', 核酸外切酶9;47.113.121.239:3128', '58.220.95.54:9400', '61.135.185.92:80', '163.177.151.76:80', '210.26.49.89:3128', '117.185.17.151:80', '117.185.17.177:80', '111.13.100.91:80', '47.98.162.91:6666', '117.57.85.249:4216'] print(random.choice(proxiess)) try: response = requests.get(url, headers=headers,proxies={'http':random.choice(proxiess)}) if response.status_code == 200: return response.text return None except RequestException: return None#解析一页内容def parse_one_page(html): soup = BeautifulSoup(html生活像一把无情刻刀, 'lxml') infos = soup.select('#shop-all-list ul li div.txt') print(info汽车空滤s) # time.sleep(random.uniform(1,3)) for info in infos: yield { '商铺': info.h4.get_text(), '星级': info.find(class_="comment").span.get('title'), '评论数': info.select('.review-num b')[0].string if info.select('.review-num b') else None, '均价': info.select('.mean-price b')[0].string if info.select('.mean-price b') else None, '类型': info.select('.tag')[0].string if info.select('.tag') else None, '商区': info.select('.tag')[1].婚庆一条龙string if info.select('.tag') else None, '地址': info.find(class_="addr").string, '口味': info.select('图片文字识别软件;ment-list b')[0].string if info.select('ment-list b') else None, '环境': info.select('ment-list b')[1].string if info.select('ment-list b') else None, '服务': info.select('ment-list b')[2].string if info.select('ment-list b') else None, }#保存结果数据def write_to_file(content): with open('result_shop.txt', 'a', encoding='utf-8') as f: f.write(json.dumps(content, ensure_ascii=False) + '\\n') 金融学考研 f.close()def main(start): http = { 'www.dianping/shanghai/ch10/g101p', 'www.dianping/shanghai/ch10/g113p', 'www.dianping/shanghai/ch10/g112p', 'www.dianping/shanghai/ch10/g117p', 'www.dianping/shanghai/ch10/g110p', 'www.dianping/shanghai/ch10/g116p', 'www.dianping/shanghai/ch10/g111p', 'www.dianping/shanghai/ch10/g103p', '留学生机票www.dianping/shanghai/ch10/g114p', 'www.dianping/shanghai/ch10/g102p', 'www.dianping/shanghai/ch10/g118p', 'www.dianpin视频语音g/shangahi/ch10/g132p', 'www.dianping/shanghai/ch10/g219p', 'w高档私人会所ww.dianping/shanghai/ch10/g508p', 'www.dianping/shanghai/ch10/g115p', 'www.dianping/shanghai/ch10/g34236p', 'www.dianping/shanghai/ch10/g34014p', 'www.dianping/shanghai/ch10/g215p', 'www.dianping/shanghai/ch10/g106p', } for url in http: time.sleep(random.uniform(1,2)) html = get_one_page(url + str(start)) for data in parse_one_page(html): print(data) write_to_file(data)if __name__ == '__main__': for i in range(50): time.sleep(random.uniform(5,10)) main(i + 1)经纬度地址转换代码:
import pandas as pdimport jsonimport requestsimport jsonimport mathimport collectionsimport openpyxlfrom pyecharts.charts import *from pyechartsponents import Tablefrom pyecharts import options as optsfrom pyechartsmons.utils import JsCodeimport randomimport datetimefrom numba import jitfrom pyecharts.globals import CurrentConfigCurrentConfig.ONLINE_HOST = "cdn.kesci/lib/pyecharts_assets/" # pyecharts的js动态有些问题,有时图显现不出来,加上面两行代码# 读取文章,存贮的数据是txt文件里的json,使用过read_json方法,并不可以,遂在此逐行读存papers=[]file = open('result_shanghai.txt', 'r',encoding='utf-8')for lin in file.readlines(): dic = json.loads(lin) papers.append(dic) print(papers)df = pd.DataFrame(papers)# 因为详细地址的数据是路名,为了能够精确定位经纬度,需要在地址前加上上海市,不然无法识别list3=[]for i in df['地址'].values: i=i.replace('地址:','') print(i) if i.startswith('上海') : i=i else: i="上海市"+i list3.append(i)print(list3)list2=[]list4=[]list5=[]list6=[]for line in list3: # 去除换行符 line = line.strip('\\n').replace('#',' ') # 去除特殊字符 line1 = line.replace('#', ' ').replace('/',' ').replace("'",'"') try: # 地址获取经纬度 baiduUrl="api.map.baidu/geocoding/v3/?address=%s&output=json&ak=kuRGjpEIfmc5qt8gKQjI5EwLSEzcKkB3&callback=showLocation"% ( line1) req = requests.get(baiduUrl) # print(req) content = req.text # print(content) content = content.replace("showLocation&&showLocation(", "") # print(content) content = content[:-1] baiduAddr = json.loads(content) # print(baiduAddr) level=baiduAddr["result"]["level"] print(level) 南宁富士康 list4.append(level) except: level='无数据' list4.append(level) print(level) try: lng = baiduAddr["result"]["location"]["lng"] lat = baiduAddr["result"]["location"]["lat"] list5.append(lng) list6.append(lat) # 经纬度获取城市 baiduUrl="api.map.baidu/reverse_geocoding/v3/?ak=你的ak&output=json&coordtype=wgs84ll&location=%s,%s"% ( lat, lng) req = requests.get(baiduUrl) content = req.text print(&德语德国#39;hahahhahahah') print(content) 笔记本电脑性价比 baiduAddr = json.loads(content) print('hehehhehehehhe') 张辽威震逍遥津 print(baiduAddr) province = baiduAddr["result"]["addressComponent"]["province"] city = baiduAddr["result"]["addressComponent"]["city"] district = baiduAddr["result"]["addressComponent"]["district"] print(district) list2.append(district) except: district='无法解析' print(district) list2.append(district) list5.append('无') list6.append('无')# print(district)print(list2)print(list4)print(list5)print(list6)df['区']=list2df['level']=list4df['经度']=list5df['维度']=list6df版权声明:本文标题:大众点评餐厅数据分析(上海去哪吃) 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1685913258a10110.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论