【情人節特別篇】想知道玫瑰在哪些城市最暢銷嘛?
- 前言
- 一、思路分析
- 二、資料爬取
- 1.資料搜索
- 2.獲取城市經緯度
- 3.完整代碼
- 三、熱力分析
- 四、寫在最后
前言
俗話說得好:“人狠話不多,祝福要先上”,在這個春節與情人節交織的好日子,kimol君真誠祝福可愛的小伙伴們:
平安喜樂,萬事順意🌠🌠🌠~
驀然回首,佳人便在燈火闌珊處~👩????👨
玫瑰花🌹作為一種傳遞愛意、互訴情長的禮物,在情人節的今天可謂是爆款,而我一直以來都有一個小小的疑惑:“玫瑰花的銷量究竟跟地區是否有關系呢?如果有,那么它在哪些城市最暢銷呢?”
各位小伙伴,請系好安全帶,咋們發車了🚗…(滴,學生卡)
一、思路分析
思路仍舊是獲取資料+資料分析兩步走戰略,就是這么的簡單粗暴~
分析的首要任務便是獲取玫瑰花的銷量情況,打開美團外賣我們可以看到這樣的畫面:

沒有錯,可以看到月銷量資料, 那么,就決定是它了!
資料分析部分我決定利用pyecharts庫基于每個城市的平均月銷量制作一個熱力圖,這樣便能直觀地反映出受歡迎程度,最后效果是醬紫的:

其對應的數值如下:

我們大抵可以看出,玫瑰花在川渝、江浙滬、京津冀、河南一帶的平均月銷量更高,其更受歡迎,我想,這在一定程度上也反映出了這里的人們對生活的無盡熱愛和對爛漫的質樸追求叭~
結論僅對本次實驗資料負責,僅供參考哦~
二、資料爬取
1.資料搜索
通過Fiddler抓包獲取美團外賣的搜索介面,其URL為:
url = 'https://wx-shangou.meituan.com/mtweapp/v2/search/v9/poiwithfilter?ui=xxx' # xxx為用戶ID,抓包可見
該請求為一個POST請求,對應的資料為:
data = {'wm_dtype': 'microsoft',
'wm_dversion': '7.0.9',
'wm_uuid': 'xxx',
'wm_visitid': 'xxx',
'wm_appversion': '5.13.26',
'wm_logintoken': 'xxx',
'userToken': 'xxx',
'req_time': 1613274108532,
'waimai_sign': '%2F',
'wm_longitude': 116938974,
'wm_latitude': 30109265,
'wm_actual_longitude': 0,
'wm_actual_latitude': 0,
'userid': 'xxx',
'user_id': 'xxx',
'uniqueid': 'xxx',
'open_id': 'xxx',
'openidcipher': 'xxx',
'uuid': 'xxx',
'rc_platform': 13,
'platform': 13,
'rc_app': 0,
'partner': 214,
'riskLevel': 71,
'keyword': '鮮花',
'page_index': 0,
'category_type': 101578,
'entrance_id': 101578,
'sort_type': 0,
'search_global_id': '274108528141A972426FC37CA2E81D27BA604D85428455EA33E345156F93CDB59C024AE9F',
'wm_ctype': 'mt_weapp'}
注:xxx代表用戶登錄狀態以及校驗等相關引數,我們大可不必深究它們是怎么生成的,直接從Fiddler中將其復制出來即可~
其中,keyword表示搜索的關鍵詞,page_index表示搜索結果的頁碼(每次回傳20條資料),wm_longitude和wm_latitude分別表示用戶所在的經緯度,通過測驗可以知道,我們只需要改變經緯度便能得到不同地區的資料,那么可以定義如下函式:
def get_info(keyword, pos, page=0):
'''
獲取外賣商品資訊
'''
url = 'https://wx-shangou.meituan.com/mtweapp/v2/search/v9/poiwithfilter?ui=xxx'
headers = {} # 從Fiddler直接復制即可
data = {'wm_dtype': 'microsoft',
'wm_dversion': '7.0.9',
'wm_uuid': 'xxx',
'wm_visitid': 'xxx',
'wm_appversion': '5.13.26',
'wm_logintoken': 'xxx',
'userToken': 'xxx',
'req_time': 1613274108532,
'waimai_sign': '%2F',
'wm_longitude': int(pos[0]*10**6),
'wm_latitude': int(pos[1]*10**6),
'wm_actual_longitude': 0,
'wm_actual_latitude': 0,
'userid': 'xxx',
'user_id': 'xxx',
'uniqueid': 'xxx',
'open_id': 'xxx',
'openidcipher': 'xxx',
'uuid': 'xxx',
'rc_platform': 13,
'platform': 13,
'rc_app': 0,
'partner': 214,
'riskLevel': 71,
'keyword': keyword,
'page_index': page,
'category_type': 101578,
'entrance_id': 101578,
'sort_type': 0,
'search_global_id': '274108528141A972426FC37CA2E81D27BA604D85428455EA33E345156F93CDB59C024AE9F',
'wm_ctype': 'mt_weapp'}
res = requests.post(url, headers=headers, data=data)
res_json = res.json()
return res_json
然而,我們要怎樣才能得到城市對應的經緯度呢?
2.獲取城市經緯度
通過高德地圖的坐標撿拾系統,便能實作地理位置與經緯度的轉換,由于介面很簡單,這里就不詳細介紹了,同樣是通過抓包分析,可以定義如下轉換函式:
def get_lonlat(keywords):
'''
獲取經緯度
'''
cookies = {
'cna': '2voBF5IOjUUCAXWIWXVuwr8W',
'UM_distinctid': '1767bba477b6bd-00c663bca533b3-1a347740-e1000-1767bba477c515',
'isg': 'BGhoxgK9o-s-8I9R8e9xGWcsOlZ6kcybbxhnvCKZpePsfQjn1qD8K_v0cZWN1oRz',
'l': 'eBOY0AmuO96VEuAdBOfalurza779_IOYYuPzaNbMiOCP_CCp5q8cWZ-AMOL9Cn1Vh6UXc37LhhQJBeYBqMIKnxvOKVLdi6Mmn',
'tfstk': 'cFtVBg4K3mnq_Csdmisa5HrbndsAZ8QG8uWOoFwkl8RrRN_li2NOE50PU9UjqZf..',
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Referer': 'https://lbs.amap.com/console/show/picker',
'Connection': 'keep-alive',
}
params = (
('s', 'rsv3'),
('children', ''),
('key', 'e07ffdf58c8e8672037bef0d6cae7d4a'),
('page', '1'),
('offset', '10'),
('city', '110000'),
('language', 'zh_cn'),
('callback', 'jsonp_160108_'),
('platform', 'JS'),
('logversion', '2.0'),
('sdkversion', '1.3'),
('appname', 'https://lbs.amap.com/console/show/picker'),
('csid', '6DCF386C-8777-4724-AE49-8E688CCEF75A'),
('keywords', keywords),
)
res = requests.get('https://restapi.amap.com/v3/place/text', headers=headers, params=params, cookies=cookies)
html = res.text
data = re.findall('\((.*)\)',html)[0]
data = json.loads(data)
location = data['pois'][0]['location']
lon = float(location.split(',')[0])
lat = float(location.split(',')[1])
return (lon, lat)
3.完整代碼
從每個省級行政區中選出一個城市(即省會),創建一個txt用于將其存盤:

完整的資料爬取代碼如下:
# -*- coding: utf-8 -*-
"""
Created on Sun Feb 14 11:54:59 2021
@author: kimol_love
"""
import os
import re
import json
import requests
import pandas as pd
def get_info(keyword, pos, page=0):
'''
獲取外賣商品資訊
'''
url = 'https://wx-shangou.meituan.com/mtweapp/v2/search/v9/poiwithfilter?ui=xxx' # xxx處需要相應改
headers = {'Connection': 'keep-alive',
'Content-Length': '1191',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat',
'_deferreds': '[object Array]',
'content-type': 'application/x-www-form-urlencoded',
'uuid': 'xxx',
'wm-ctype': 'mt_weapp',
'Accept-Encoding': 'gzip, deflate, br'}
data = {'wm_dtype': 'microsoft',
'wm_dversion': '7.0.9',
'wm_uuid': 'xxx',
'wm_visitid': 'xxx',
'wm_appversion': '5.13.26',
'wm_logintoken': 'xxx',
'userToken': 'xxx',
'req_time': 1613274108532,
'waimai_sign': '%2F',
'wm_longitude': int(pos[0]*10**6),
'wm_latitude': int(pos[1]*10**6),
'wm_actual_longitude': 0,
'wm_actual_latitude': 0,
'userid': 'xxx',
'user_id': 'xxx',
'uniqueid': 'xxx',
'open_id': 'xxx',
'openidcipher': 'xxx',
'uuid': 'xxx',
'rc_platform': 13,
'platform': 13,
'rc_app': 0,
'partner': 214,
'riskLevel': 71,
'keyword': keyword,
'page_index': page,
'category_type': 101578,
'entrance_id': 101578,
'sort_type': 0,
'search_global_id': 'xxx',
'wm_ctype': 'mt_weapp'}
res = requests.post(url, headers=headers, data=data)
res_json = res.json()
return res_json
def parse_info(data):
'''
提取所需資料
'''
result = [] # 用于保存結果
for poi in data['data']['search_poi_list']:
name = poi['name'] # 商店名稱
sales = int(poi['month_sales_tip'][2:]) # 月銷量
address = poi['address'] # 地址
lon = int(poi['longitude'])/10**6 # 經度
lat = int(poi['latitude'])/10**6 # 緯度
result.append({'商店名': name,
'月銷量': sales,
'地址': address,
'經度': lon,
'緯度': lat})
return result
def get_lonlat(keywords):
'''
獲取經緯度
'''
cookies = {
'cna': '2voBF5IOjUUCAXWIWXVuwr8W',
'UM_distinctid': '1767bba477b6bd-00c663bca533b3-1a347740-e1000-1767bba477c515',
'isg': 'BGhoxgK9o-s-8I9R8e9xGWcsOlZ6kcybbxhnvCKZpePsfQjn1qD8K_v0cZWN1oRz',
'l': 'eBOY0AmuO96VEuAdBOfalurza779_IOYYuPzaNbMiOCP_CCp5q8cWZ-AMOL9Cn1Vh6UXc37LhhQJBeYBqMIKnxvOKVLdi6Mmn',
'tfstk': 'cFtVBg4K3mnq_Csdmisa5HrbndsAZ8QG8uWOoFwkl8RrRN_li2NOE50PU9UjqZf..',
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0',
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Referer': 'https://lbs.amap.com/console/show/picker',
'Connection': 'keep-alive',
}
params = (
('s', 'rsv3'),
('children', ''),
('key', 'e07ffdf58c8e8672037bef0d6cae7d4a'),
('page', '1'),
('offset', '10'),
('city', '110000'),
('language', 'zh_cn'),
('callback', 'jsonp_160108_'),
('platform', 'JS'),
('logversion', '2.0'),
('sdkversion', '1.3'),
('appname', 'https://lbs.amap.com/console/show/picker'),
('csid', '6DCF386C-8777-4724-AE49-8E688CCEF75A'),
('keywords', keywords),
)
res = requests.get('https://restapi.amap.com/v3/place/text', headers=headers, params=params, cookies=cookies)
html = res.text
data = re.findall('\((.*)\)',html)[0]
data = json.loads(data)
location = data['pois'][0]['location']
lon = float(location.split(',')[0])
lat = float(location.split(',')[1])
return (lon, lat)
if __name__ == '__main__':
# 讀取城市串列
with open('citys.txt', 'r') as f:
citys = f.readlines()
citys = [c.strip() for c in citys]
# 創建保存結果的目錄
savePath = './data'
if not os.path.exists(savePath):
os.mkdir(savePath)
# 回圈爬取資料
for city in citys:
pos = get_lonlat(city)
result = [] # 用于保存結果
for page in range(5): # 爬取5頁(共100條資料)
data = get_info('鮮花', pos, page)
data = parse_info(data)
result.extend(data)
print('"%s"第%d頁爬取完成!'%(city, page+1))
result = pd.DataFrame(result)
result.to_csv('%s/%s.csv'%(savePath, city), index=False)
最后,我們得到了每個城市對應的玫瑰花月銷量資料:

其中,每個表格的資料格式如下:

三、熱力分析
有了城市玫瑰花月銷量的資料之后,我們便可對其熱度進行分析,這里采用了一種較簡單的方式,即計算每個城市月銷量的平均值,隨后用pyecharts庫將其以熱力圖的方式展示出來,代碼如下:
# -*- coding: utf-8 -*-
"""
Created on Sun Feb 14 15:25:19 2021
@author: kimol_love
"""
import os
import pandas as pd
from pyecharts.charts import Geo
from pyecharts import options as opts
if __name__ == '__main__':
# 計算平均月銷量
savePath = './data'
sales = [] # 平均月銷量
for file in os.listdir(savePath):
city = file.split('.')[0] # 城市
data = pd.read_csv('%s/%s'%(savePath, file))
sale = round(data['月銷量'].mean(), 2) # 平均月銷量
sales.append((city, sale))
max_sale = max([s[1] for s in sales]) # 最高銷量
min_sale = max([s[1] for s in sales]) # 最低銷量
# 繪制散點分布圖
geo = Geo(init_opts=opts.InitOpts(page_title='鮮花平均銷量'))
geo.add_schema(maptype='china', is_roam=False, selected_mode=True, label_opts=opts.LabelOpts(is_show=True), itemstyle_opts=opts.ItemStyleOpts(color='#FFD5CF', border_color='#111'))
geo.add('', sales, type_ = 'heatmap') # 設定地圖型別及資料
geo.set_series_opts(label_opts = opts.LabelOpts(is_show = False)) #設定是否顯示標簽
geo.set_global_opts(title_opts = opts.TitleOpts(title='各城市鮮花平均銷量', subtitle='??情人節快樂??', pos_left='center',
title_textstyle_opts=opts.TextStyleOpts(font_size=23),
subtitle_textstyle_opts=opts.TextStyleOpts(font_size=15,font_weight='bold',color='#71CFEB')),
visualmap_opts = opts.VisualMapOpts(max_=max_sale+10))
# 保存結果
geo.render(path='月銷量(熱力).html')
代碼輕輕一跑,便有了上文的熱力圖,打完,收工~
四、寫在最后
本次分析資料有限,所以結論可能稍顯片面,僅作為娛樂參考,如有不足還請大家多多包涵,如果有感興趣的小伙伴,也可以嘗試著從更多的維度、更細的角度進行分析哦,
最后,再次祝大家伙春節及情人節雙倍快樂呀🎈~
愿大家都能在奔波凡塵中找到屬于自己的棲息之地;
愿大家都能在燦爛煙火中找到屬于自己的美麗風景,
我是kimol君,咋們下次再會~

創作不易,大俠請留步… 動起可愛的雙手,來個贊再走唄 (???←?)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/259747.html
標籤:python
下一篇:鏈堆疊問題
