本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。

今天带着大家用python分析一下美团上的按摩项目,看看老司机都喜欢玩什么服务。
本文主要分为两部分:
- 一是数据爬取
- 二是数据可视化
一、爬取数据
1.抓包获取数据接口
打开美团,搜索“按摩”关键词,用火狐浏览器抓包
美团这个反爬很有意思,如果单纯刷新网页,数据显示不全,“更多优惠”的内容不显示,如下图:

但是点击智能排序等排序方式时就会显示出来,如下图:

数据接口url为:
https://apimobile.meituan.com/group/v4/poi/pcsearch/1?uuid=86d6fed675bd4d2eb544.1600266551.1.0.0&userid=-1&limit=32&offset=0&cateId=-1&q=按摩&sort=default
用limit和offfset控制页码,limit表示返回数据条数,offfset代表数据返回起点,经过分析,总共大概有1000条数据。
2.爬虫爬取数据并保存为csv
经过测试发现,该url连续请求会被服务器拒绝,于是只能设置间隔时间,并且limit可以更改,最大能设置到150,也就是说我们最多1次可获取150条数据,代码如下:
url='https://apimobile.meituan.com/group/v4/poi/pcsearch/1?uuid=86d6fed675bd4d2eb544.1600266551.1.0.0&userid=92855137&limit=150&offset=1050&cateId=-1&q=按摩&sort=default' response=requests.get(url, headers=headers) datas=json.loads(response.text)['data']['searchResult'] print(len(datas)) for data in datas: if data['deals']!=None: title=data['title'] #名字 address=data['address'] #地址 lowestprice=data['lowestprice'] #最低价 avgprice=data['avgprice'] #平均价格 latitude=data['latitude'] longitude = data['longitude'] avgscore = data['avgscore'] comments = data['comments'] historyCouponCount = data['historyCouponCount'] areaname = data['areaname'] backCateName = data['backCateName'] deals = data['deals'] for deal in deals: title_deal=deal['title'] #项目名字 price_deal = deal['price'] #项目团购价格 value_deal = deal['value'] #项目原价 sales_deal = deal['sales'] #项目已售次数 result=[title, address, lowestprice, avgprice,latitude,longitude,avgscore,comments, historyCouponCount,areaname,backCateName,title_deal,price_deal,value_deal,sales_deal] with open('1.csv', 'a+', newline='',encoding='gb18030') as f: f_csv = csv.writer(f) f_csv.writerow(result)
基本把有用的数据都保存了,数据展示如下:


二、数据可视化
先用pandas读取数据
import pandas as pd data=pd.read_csv('美团按摩.csv',encoding='gb18030')
1.价格分布极坐标系
我们先来看看所有按摩项目价格的分布情况
price_dict={} for i in list(set(list(data['price_deal']))): price_dict[i]=list(data['price_deal']).count(i) prices=[(i,price_dict[i]) for i in list(price_dict.keys())] c = ( Polar({"theme": ThemeType.PURPLE_PASSION}) .add_schema(angleaxis_opts=opts.AngleAxisOpts(start_angle=0, min_=0,type_="value", is_clockwise=True)) .add("", prices, type_="scatter", label_opts=opts.LabelOpts(is_show=False)) .set_global_opts( tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"), title_opts=opts.TitleOpts(title="按摩价格分布极坐标图",pos_right='40%'), ) ) c.render_notebook()

不是很明显,再对价格划分区间,看一下饼状图
price_range=['0-200元','200-500元','500-1000元','1000-2000元','2000元以上'] price_dict={} price_dict[price_range[0]]=len(list(data[data['price_deal']<=200]['price_deal'])) price_dict[price_range[1]]=len(list(data[data['price_deal']<=500]['price_deal']))-price_dict[price_range[0]] price_dict[price_range[2]]=len(list(data[data['price_deal']<=1000]['price_deal']))-price_dict[price_range[1]] price_dict[price_range[3]]=len(list(data[data['price_deal']<=2000]['price_deal']))-price_dict[price_range[2]] price_dict[price_range[4]]=len(list(data[data['price_deal']>=1000]['price_deal'])) from pyecharts import options as opts from pyecharts.charts import Pie pie = ( Pie() .add( "", [(i,price_dict[i])for i in list(price_dict.keys())], radius=["30%", "75%"], center=["50%", "50%"], rosetype="radius", label_opts=opts.LabelOpts(is_show=False), ) .set_global_opts(title_opts=opts.TitleOpts(title="Pie-玫瑰图示例")) .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%")) ) pie.render_notebook()

从价格分布图上来看,大概200元以内的项目占31.58%,200-500元以内的占15.59,500-1000元以内的占35.95%,1000-2000元以内的占16.22%,2000元以上0.86%。商家侧重的价格区间在500-1000元。
2.价格最贵的20个项目
price_rank=data.sort_values(by='price_deal',ascending=False).head(20) bar = ( Bar(init_opts=opts.InitOpts(width=1200,height=900)) .add_xaxis(list(price_rank['title_deal'])[::-1]) .add_yaxis("", [float(i) for i in list(price_rank['price_deal'])[::-1]],color='#2F4F4F') .reversal_axis() .set_global_opts( title_opts=opts.TitleOpts("最贵按摩服务排行",pos_right='40%',pos_top='0%'), xaxis_opts=opts.AxisOpts( splitline_opts=opts.SplitLineOpts(is_show=True),name="价格"), yaxis_opts=opts.AxisOpts(splitline_opts=opts.SplitLineOpts(is_show=True), axislabel_opts=opts.LabelOpts(color='#FF6347'),name="项目"), ) .set_series_opts(label_opts=opts.LabelOpts(position="right",color='#006400')) ) grid = ( Grid() .add(bar, grid_opts=opts.GridOpts(pos_left="25%",pos_right="5%")) ) grid.render_notebook()

看起来都好高大上,你中意哪一个?
3.销量最高的项目(老司机最喜欢的)
bar = ( Bar({"theme": ThemeType.DARK}) .add_xaxis(list(price_rank['title_deal'])[::-1]) .add_yaxis("", [float(i) for i in list(price_rank['sales_deal'])[::-1]]) .reversal_axis() .set_global_opts( title_opts=opts.TitleOpts("最受喜爱服务项目排行",pos_right='40%',pos_top='0%'), xaxis_opts=opts.AxisOpts( splitline_opts=opts.SplitLineOpts(is_show=True)), yaxis_opts=opts.AxisOpts(splitline_opts=opts.SplitLineOpts(is_show=True), axislabel_opts=opts.LabelOpts(color='#FFD700')),) .set_series_opts(label_opts=opts.LabelOpts(position="right",color='#FF1493')) ) grid = ( Grid({"theme": ThemeType.DARK}) .add(bar, grid_opts=opts.GridOpts(pos_left="25%",pos_right="0%")) ) grid.render_notebook()

这是什么鬼,九阳神功足疗?明显已经超出我的认知范围了
初步观察,应该是美团连锁店,销量都是共享的,或者是刷销量的,咱也不懂,咱也不敢问
于是我决定对项目列进行去重,再把价格加上
price_rank=data_quchong.sort_values(by='sales_deal',ascending=False).head(10) bar = ( Bar({"theme": ThemeType.DARK}) .add_xaxis(['{0}: {1}元'.format(str(i),j) for i,j in zip(list(price_rank['title_deal'])[::-1],list(price_rank['price_deal'])[::-1])]) .add_yaxis("", [float(i) for i in list(price_rank['sales_deal'])[::-1]]) .reversal_axis() .set_global_opts( title_opts=opts.TitleOpts("最受喜爱服务项目排行",pos_right='40%',pos_top='0%'), xaxis_opts=opts.AxisOpts( splitline_opts=opts.SplitLineOpts(is_show=True)), yaxis_opts=opts.AxisOpts(splitline_opts=opts.SplitLineOpts(is_show=True), axislabel_opts=opts.LabelOpts(color='#FFD700')),) .set_series_opts(label_opts=opts.LabelOpts(position="right",color='#FF1493')) ) grid = ( Grid({"theme": ThemeType.DARK}) .add(bar, grid_opts=opts.GridOpts(pos_left="30%",pos_right="5%")) ) grid.render_notebook()

看的我激动的直搓手,泡脚足浴毫无悬念排第一,老司机的最爱,价格实惠效果好!
但是我就是想知道排第二的九阳神功足疗到时是什么奇特的效果
于是我特意查了一下

感觉还不错哈!
以下文章来源于python数据分析之禅 ,作者小dull鸟
转载地址
https://blog.csdn.net/fei347795790?t=1