國慶假期已經過半,你是出去浪了?還是在家裡宅著呢?那你知道你的朋友去哪浪了嗎?本文我們通過爬取去哪網售票資料(piao.qunar.com
)來簡單分析一下。
資料爬取
首選,我們開啟網址:piao.qunar.com
,在搜尋框輸入一個省級行政區劃進行搜尋,以浙江為例,如圖所示:
再將頁面向下拉,F12 開啟開發者工具,點選下一頁看一下 URL,如圖所示:
通過觀察 URL 我們可以看出 keyword
和 page
是動態的,一個是輸入條件值,另一個是頁碼值,當我們需要翻頁爬取時可以進行動態賦值,再將開發者工具切到 Response,我們可以發現返回的資料是 JSON 格式的,如圖所示:
這裡我們以 34 個省級行政區劃作為 keyword 進行分頁爬取,主要爬取程式碼實現如下:
def get_city_data(cities, pages):
cityNames = []
sightNames = []
stars = []
scores = []
qunarPrices = []
saleCounts = []
districtses = []
points = []
intros = []
frees = []
addresses = []
for city in cities:
for page in range(1, pages+1):
try:
print(f'正在爬取{city}第{page}頁資料...')
time.sleep(random.uniform(1.5, 2.5))
url = f'https://piao.qunar.com/ticket/list.json?from=mpl_search_suggest&keyword={city}&page={page}'
print('url:', url)
result = requests.get(url, headers=headers, timeout=(2.5, 5.5))
status = result.status_code
if(status == 200):
# 每頁資料
response_info = json.loads(result.text)
print('資料:', response_info)
sight_list = response_info['data']['sightList']
for sight in sight_list:
sightName = sight['sightName'] # 名稱
star = sight.get('star', None) # 星級
score = sight.get('score', 0) # 評分
qunarPrice = sight.get('qunarPrice', 0) # 價格
saleCount = sight.get('saleCount', 0) # 銷量
districts = sight.get('districts', None) # 行政區劃
point = sight.get('point', None) # 座標
intro = sight.get('intro', None) # 簡介
free = sight.get('free', True) # 是否免費
address = sight.get('address', None) # 地址
cityNames.append(city)
sightNames.append(sightName)
stars.append(star)
scores.append(score)
qunarPrices.append(qunarPrice)
saleCounts.append(saleCount)
districtses.append(districts)
points.append(point)
intros.append(intro)
frees.append(free)
addresses.append(address)
except:
continue
city_dic = {'cityName': cityNames, 'sightName': sightNames, 'star': stars,
'score': scores, 'qunarPrice': qunarPrices, 'saleCount': saleCounts,
'districts': districtses, 'point': points, 'intro': intros,
'free': frees, 'address': addresses}
city_df = pd.DataFrame(city_dic)
city_df.to_csv('cities.csv', index=False)
資料分析
現在資料有了,我們再來簡單分析一下。
位置分佈
首選,我們來看一下景區的位置分佈情況。
先看一下景區的整體分佈情況,主要程式碼實現如下:
for city in df[(df.iloc[:, 5] > 0)].iloc[:, 0]:
if city != "":
cities.append(city)
data = Counter(cities).most_common(100)
gx = []
gy = []
for c in data:
gx.append(c[0])
gy.append(c[1])
(
Map(init_opts=opts.InitOpts(theme=ThemeType.MACARONS, height="500px"))
.add('數量', [list(z) for z in zip(gx, gy)], 'china')
.set_global_opts(
title_opts=opts.TitleOpts(title='各地景區數量分佈'),
visualmap_opts=opts.VisualMapOpts(max_=150, is_piecewise=True),
)
).render_notebook()
看一下效果:
再看一下各地景區的銷量情況,主要程式碼實現如下:
df_item = df[['cityName','saleCount']]
df_sum = df_item.groupby('cityName').sum()
(
Map(init_opts=opts.InitOpts(theme=ThemeType.ROMANTIC, height="500px"))
.add('銷量', [list(z) for z in zip(df_sum.index.values.tolist(), df_sum.values.tolist())], 'china')
.set_global_opts(
title_opts=opts.TitleOpts(title='各地景區銷量分佈'),
visualmap_opts=opts.VisualMapOpts(max_=150000, is_piecewise=True)
)
).render_notebook()
看一下效果:
最熱景區
我們接著看 TOP10 熱門景區有哪些?它們的價格又是多少呢?主要程式碼實現如下:
sort_sale = df.sort_values(by='saleCount', ascending=True)
(
Bar(init_opts=opts.InitOpts(theme=ThemeType.MACARONS, width='125%'))
.add_xaxis(list(sort_sale['sightName'])[-10:])
.add_yaxis('銷量', sort_sale['saleCount'].values.tolist()[-10:])
.add_yaxis('價格', sort_sale['qunarPrice'].values.tolist()[-10:])
.reversal_axis()
.set_global_opts(
title_opts=opts.TitleOpts(title='最熱景區TOP10'),
yaxis_opts=opts.AxisOpts(name='名稱', axislabel_opts=opts.LabelOpts(rotate=-30)),
xaxis_opts=opts.AxisOpts(name='銷量/價格'),
)
.set_series_opts(label_opts=opts.LabelOpts(position="right"))
).render_notebook()
看一下效果:
從圖中我們可以看出 TOP10 熱門景區的價格大多數都在 500 以內,算是比較親民了。如果你的朋友喜歡熱鬧,他(她)可能去了熱門景區。
再接著看熱門景區的介紹情況,這裡我們選取 T100 資料,通過詞雲來看一下。主要實現程式碼如下:
sort_sale = df.sort_values(by='saleCount', ascending=True)
stylecloud.gen_stylecloud(text=cts_str, max_words=100,
collocations=False,
font_path="SIMLI.TTF",
icon_name="fab fa-firefox",
size=800,
output_name="hot.png")
看一下效果:
最豪景區
我們再看一下票價 TOP10 景區有哪些?它們的銷量怎麼樣呢?主要程式碼實現如下:
sort_price = df.sort_values(by='qunarPrice', ascending=True)
(
Bar(init_opts=opts.InitOpts(theme=ThemeType.ROMA))
.add_xaxis(list(sort_price['sightName'])[-10:])
.add_yaxis('價格', sort_price['qunarPrice'].values.tolist()[-10:])
.add_yaxis('銷量', sort_price['saleCount'].values.tolist()[-10:])
.reversal_axis()
.set_global_opts(
title_opts=opts.TitleOpts(title='最豪景區TOP10'),
yaxis_opts=opts.AxisOpts(name='名稱'),
xaxis_opts=opts.AxisOpts(name='價格/銷量'),
)
.set_series_opts(label_opts=opts.LabelOpts(position="right"))
).render_notebook()
看一下效果:
如果你的朋友是一個熱愛旅遊的土豪,他(她)很有可能去了土豪景區了。
再接著看一下土豪景區的介紹情況,這裡我們還是選取 T100 資料,通過詞雲來看一下。
主要程式碼實現如下:
sort_price = df.sort_values(by='qunarPrice', ascending=True)
stylecloud.gen_stylecloud(text=cts_str, max_words=100,
collocations=False,
font_path="SIMLI.TTF",
icon_name="fas fa-yen-sign",#最豪
size=800,
output_name="money.png")
看一下效果:
景區星級
我們再來看一下各省級行政區劃的 5A 級景區數量情況,主要程式碼實現如下:
df_sum = df[df['star']=='5A'].groupby('cityName').count()['star']
(
Bar(init_opts=opts.InitOpts(theme=ThemeType.MACARONS))
.add_xaxis(df_sum.index.values.tolist())
.add_yaxis('數量', df_sum.values.tolist())
.set_global_opts(
title_opts=opts.TitleOpts(title='各地5A景區數量'),
datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_='inside')],
)
).render_notebook()
看一下效果:
如果你的朋友熱愛旅遊且對 5A 級景區情有獨鍾,他(她)可能去了 5A 景區的城市了。
最後,我們看一下 T200 熱門景區的星級比例情況是怎樣的?主要程式碼實現如下:
sort_data = df.sort_values(by=['saleCount'], ascending=True)
rates = list(sort_data['star'])[-200:]
gx = ["3A", "4A", "5A"]
gy = [
rates.count("3A"),
rates.count("4A"),
rates.count("5A")
]
(
Pie(init_opts=opts.InitOpts(theme=ThemeType.MACARONS))
.add("", list(zip(gx, gy)), radius=["40%", "70%"])
.set_global_opts(title_opts=opts.TitleOpts(title="銷量TOP200景區星級比例", pos_left = "left"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%", font_size=12))
).render_notebook()
看一下效果:
從圖中我們可以看出 90% 以上的景區均為 4/5A 級。
好了,本文就到這裡了,文中我們對去哪網售票資料中的幾個指標進行了簡單的分析,可以做個簡單的參考,當然了,如果你感興趣的話,還可以繼續對其他指標進行分析。
原始碼在公眾號Python小二後臺回覆qunar獲取。