淘寶零食專欄分析(淘寶爬蟲+數據分析)

前言:本文爬蟲的關鍵字眼是「美食」,實際分析時發現「零食」的銷售量遠遠高於「美食」,所以在一開始的數據層面就已經決定了本文分析的片面性,本篇博客主要是用於記錄代碼和分析過程。html

實際的結論請看下一篇博客(下一篇博客爬蟲的關鍵字眼是「零食」)。python

https://www.cnblogs.com/little-monkey/p/10822369.htmlweb

1、爬蟲

根據崔慶才老師的爬蟲視頻修改而來,利用selenium進行淘寶爬取(原本想用火車採集器爬取的,嘗試了一下發現無法截取淘寶網址的字段)。app

selenium徹底模擬人工點擊操做,原理上能夠爬取淘寶的全部可見內容。dom

爬蟲代碼有參考  https://www.cnblogs.com/hustcser/p/8744355.html函數

import re
import time
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pyquery import PyQuery as pq
import pymongo

MONGO_URL = 'localhost'
MONGO_DB = 'taobao'
MONGO_TABLE = 'product2'
KEYWORD = '美食'
PAGE_NUM=35            #爬取頁數

client=pymongo.MongoClient(MONGO_URL)
db=client[MONGO_DB]

browser = webdriver.Chrome()
wait=WebDriverWait(browser, 10)

def search():
    print('正在搜素...')
    try:
        browser.get('https://s.taobao.com/search?q=%E7%BE%8E%E9%A3%9F&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.2017.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170306&sort=sale-desc&bcoffset=-30&p4ppushleft=%2C44&ntoffset=-30&fs=1&filter_tianmao=tmall&s=0')
        page_num=PAGE_NUM
        get_products()      # 獲取頁面詳情
        return page_num
    except TimeoutException:
        return search()

# 獲取下頁
def next_page(page_number):
    print('正在翻頁%s', page_number)
    time.sleep(3)
    try:
        input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > input")))
        submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit')))
        input.clear()
        input.send_keys(page_number)
        submit.click()
        wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > ul > li.item.active > span'),str(page_number)))
        get_products()
    except TimeoutException:
        next_page(page_number)

# 解析頁面
def get_products():
    # 判斷元素是否已經加載下來
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-itemlist .items .item')))
    html=browser.page_source
    doc=pq(html)
    items=doc("#mainsrp-itemlist .items .item").items()
    for item in items:
        product={
            # 'image': item.find('.pic .img').attr('src'),
            'title': item.find('.title').text(),
            'price': item.find('.price').text(),
            'deal': item.find('.deal-cnt').text()[:-3],
            'location': item.find('.location').text(),
            'shop': item.find('.shop').text()
        }
        print(product)
        save_to_mongo(product)

def save_to_mongo(result):
    try:
        if db[MONGO_TABLE].insert(result):
            print('存儲到MongoDB成功',result)
    except Exception:
        print('存儲到MongoDB失敗',result)

def main():
    try:
        page_num=search()
        for i in range(2,page_num+1):
            next_page(i)
    except Exception:
        print('出錯啦')
    finally:
        browser.close()

if __name__ == '__main__':
    main()

注意:運行程序後會彈出淘寶登錄頁面,使用手機淘寶掃描登錄,而後坐等爬取結果,最後從MongoDB中導出CSV文件便可。字體

結果以下:ui

2、數據處理

data= pd.read_csv('data/淘寶美食35頁.csv', encoding='utf8',engine='python')
data.drop('_id',axis=1, inplace=True)                #去掉id列
data['price'].replace('¥', '', regex=True, inplace=True)     #去掉price列的'¥'

#從location列中取出省份和城市,而後刪除location列
data['province']=data.location.apply(lambda x:x.split()[0])
data['city']=data.location.apply(lambda x:x.split()[0] if len(x)<4 else x.split()[1])
data.drop('location',axis=1, inplace=True)

#數據類型轉化
data['price']=data.price.astype('float64')
for i in ['province','city']:
    data[i]=data[i].astype('category')

運行結果以下:spa

3、數據挖掘與分析

【數據處理】

import jieba   

#導入整理好的待添加詞語(由於jieba自己的分詞功能不足以應付特定數據)
add_words = pd.read_excel('data/add_words.xlsx',header=None)     
add_words_list = add_words[0].tolist() 
for w in add_words_list:                    # 添加詞語
   jieba.add_word(w , freq=1000) 
   
#導入停用詞表
stopwords = [line.strip() for line in open('data/stop.csv', 'r', encoding='utf-8').readlines()]  

#對每一個標題進行分詞,使用lcut函數
title=data.title.values.tolist()     #轉爲list
title_s=[]
for line in title:
    title_cut=jieba.lcut(line)
    title_s.append(title_cut)
     
#去除冗餘詞Plan1:剔除停用詞:
title_clean = []
for line in title_s:
   line_clean = []
   for word in line:
      if word not in stopwords:
         line_clean.append(word)
   title_clean.append(line_clean)
#去除冗餘詞Plan2:直接定義,定義完後再調用lcut函數
#removes =['熟悉', '技術', '職位', '相關', '工做', '開發', '使用','能力','優先','描述','任職']
#for w in removes:
#   jieba.del_word(w)
   
#去重,對title_clean中的每一個list的元素進行去重,即每一個標題被分割後的詞語惟一,如【麻辣小魚乾香辣小魚乾】->【麻辣,香辣,小魚乾】
#去重後的title_clean_dist爲二維list,即[[……],[……],……]
title_clean_dist = []  
for line in title_clean:   
   line_dist = []
   for word in line:
      if word not in line_dist:
         line_dist.append(word)
   title_clean_dist.append(line_dist)
   
# 將 title_clean_dist 轉化爲一維list
allwords_clean_dist = []
for line in title_clean_dist:
   for word in line:
      allwords_clean_dist.append(word)

# 把列表 allwords_clean_dist 轉爲數據框: 
df_allwords_clean_dist = pd.DataFrame({'allwords': allwords_clean_dist})
  
# 對過濾_去重的詞語 進行分類彙總:
word_count = df_allwords_clean_dist.allwords.value_counts().reset_index()    
word_count.columns = ['word','count']      #添加列名 

 

【詞雲可視化】

# 詞雲可視化
from PIL import Image
from wordcloud import WordCloud
import matplotlib.pyplot as plt

txt = " ".join(allwords_clean_dist)                #將list轉成str,便於詞雲可視化
food_mask=np.array(Image.open("data/mask.png"))
wc = WordCloud(font_path='data/simhei.ttf',        # 設置字體
               background_color="white",           # 背景顏色
               max_words=1000,                    # 詞雲顯示的最大詞數
               max_font_size=100,                  # 字體最大值
               min_font_size=5,                   #字體最小值
               random_state=42,                   #隨機數
               collocations=False,                 #避免重複單詞
               mask=food_mask,                     #造型遮蓋
               width=1000,height=800,margin=2,     #圖像寬高,字間距,須要配合下面的plt.figure(dpi=xx)放縮纔有效
              )
wc.generate(txt) 

plt.figure(dpi=200)
plt.imshow(wc, interpolation='catrom',vmax=1000)
plt.axis("off")                                 #隱藏座標

plt.rcParams['figure.dpi'] = 600
plt.savefig('E:\\1標題詞雲.png')

進一步的,進行不一樣關鍵詞銷量的可視化3d

 

【銷量統計】

ws_sum=[]
for w in word_count.word:
    i=0
    s_list=[]
    for t in title_clean_dist:
        if w in t:
            s_list.append(data.deal[i])
        i+=1
    ws_sum.append(sum(s_list))

df_sum=pd.DataFrame({'ws_sum':ws_sum})
df_word_sum=pd.concat([word_count,df_sum],axis=1,ignore_index=True)
df_word_sum.columns=['word','count','ws_sum']    #詞語,出現次數,包含該詞語的商品銷量

df_word_sum.drop(8,axis=0,inplace=True)            #刪除「空格」詞所在的8行
df_word_sum.sort_values('ws_sum',inplace=True,ascending=True)    #升序排列
df_ws=df_word_sum.tail(40)

index=np.arange(df_ws.word.size)
plt.figure(figsize=(16,13))
plt.barh(index,df_ws.ws_sum,align='center')
plt.yticks(index,df_ws.word,fontsize=11)

#添加數據標籤
for y,x in zip(index,df_ws.ws_sum):
    plt.text(x,y,'%.0f' %x,ha='left',va='center',fontsize=11)    #ha參數有【center,left,right】,va參數有【top,bottom,center,baseline】
    
plt.savefig('E:\\2銷量詞彙排行.png')

 【分析1】根據淘寶標題(賣家傾向)+銷量(買家傾向)分析市場狀況

一、美食、零食、小吃等字眼的商品佔比較高;

二、從進餐時間來看,早餐賣的最多,下午茶也有必定空間;

三、從地域來看,川渝美食領跑全國,湖南、雲南、北京、廈門次之,南京、安徽、上海、黃山也有必定市場;

四、從種類來看,糕點>麪包>肉脯>蛋類,看來中國人民喜歡甜點多於肉、蛋製品;

五、從風格來看,特產和網紅處於第一梯隊,特產賣家最多,網紅銷量最高,第二梯隊中傳統>養分,國人鍾愛特產以及網紅美食坐上銷量寶座的深層緣由,多是宣傳,即買家購買零食時更傾向於購買據說過的東西;

六、從包裝來看,整箱包裝最受歡迎,小包裝次之,大禮包、散裝、禮盒、批發雖然常見於賣家,但銷量比不上整箱包裝和小包裝,這也和糕點、麪包類暢銷相關;

七、從口味來看,麻辣和香辣最受歡迎,和川渝美食地位相符;

八、從品牌來看,銷量上 良品鋪子>三隻松鼠>百草味,三巨頭領銜零食市場,已初步造成口碑。

 【總結1】對美食而言,有力的宣傳能夠極大促進銷量。川渝美食領跑全國,既和其口味【麻辣】、【香辣】有關,更和其「小吃」、「美女」、「網紅」等城市標籤有關;糕點、麪包等精緻食品廣受【辦公室人羣】的歡迎。

 

同理,進行【店名分析】

#導入整理好的待添加詞語(由於jieba自己的分詞功能不足以應付特定數據)
add_words = pd.read_excel('data/add_words.xlsx',header=None)     
add_words_list = add_words[0].tolist() 
for w in add_words_list:                    # 添加詞語
   jieba.add_word(w , freq=1000) 

#去除冗餘詞:直接定義,定義完後再調用lcut函數
removes =['', '', '']
for w in removes:
   jieba.del_word(w) 

#對每一個標題進行分詞,使用lcut函數
shop=data.shop.values.tolist()     #轉爲list
shop_s=[]
for line in shop:
    shop_cut=jieba.lcut(line)
    shop_s.append(shop_cut)
    
shop_clean_dist = []  
for line in shop_s:   
   line_dist = []
   for word in line:
      if word not in line_dist:
         line_dist.append(word)
   shop_clean_dist.append(line_dist)

# 將 title_clean_dist 轉化爲一維list
shop_list = []
for line in shop_clean_dist:
   for word in line:
      shop_list.append(word)

txt = " ".join(shop_list)                #將list轉成str,便於詞雲可視化
sh = WordCloud(font_path='data/simhei.ttf',     # 設置字體
               background_color="white",          # 背景顏色
               max_words=100,                  # 詞雲顯示的最大詞數
               max_font_size=100,                  # 字體最大值
               min_font_size=5,                 #字體最小值
               random_state=42,                 #隨機數
               collocations=False,                 #避免重複單詞
               width=600,height=400,margin=2,     #圖像寬高,字間距,須要配合下面的plt.figure(dpi=xx)放縮纔有效
              )
sh.generate(txt) 
plt.figure(dpi=200)
plt.imshow(sh, interpolation='catrom',vmax=1000)
plt.axis("off")

# 把列表 allwords_clean_dist 轉爲數據框: 
shop_list = pd.DataFrame({'allwords': shop_list})
  
# 對過濾_去重的詞語 進行分類彙總:
shop_count = shop_list.allwords.value_counts().reset_index()    
shop_count.columns = ['shop','count']      #添加列名 

#銷量統計
sh_sum=[]
for w in shop_count.shop:
    i=0
    s_list=[]
    for t in shop_clean_dist:
        if w in t:
            s_list.append(data.deal[i])
        i+=1
    sh_sum.append(sum(s_list))

df_sum=pd.DataFrame({'sh_sum':sh_sum})
df_word_sum=pd.concat([shop_count,df_sum],axis=1,ignore_index=True)
df_word_sum.columns=['shop','count','shop_sum']    #店名,出現次數,該店總銷量

df_word_sum.sort_values('shop_sum',inplace=True,ascending=True)    #升序排列
df_sh=df_word_sum.tail(30)

index=np.arange(df_sh.shop.size)
plt.figure(figsize=(12,9))
plt.barh(index,df_sh.shop_sum,align='center')
plt.yticks(index,df_sh.shop,fontsize=11)

【分析2】店名分析

一、多數店名帶有「旗艦店」、「食品」、「專營」等字眼;

二、良品鋪子霸居榜首,雖然其商品數量很少(只有14件),但其銷量高,甚至勝於天貓超市;

【總結2】店名最好帶有「旗艦店」,對賣家有信服力

 

【價格分佈】

data_p=data[data['price']<150]
print('價格在150如下的商品佔比:%.3f'%(len(data_p)/len(data)))

plt.figure(figsize=(7,5))
plt.hist(data_p['price'],bins=25)
plt.xlabel('價格',fontsize=12)
plt.ylabel('商品數量',fontsize=12)
plt.title('不一樣價格對應的商品數量分佈',fontsize=12)
價格在150如下的商品佔比:0.990

data_s=data[data['deal']<20000] 
data_s=data_s[data_s['deal']>200]
print('銷量在200~20000之間的商品佔比:%.3f'%(len(data_s)/len(data)))

plt.figure(figsize=(7,5))
plt.hist(data_s['deal'],bins=25)
plt.xlabel('銷量',fontsize=12)
plt.ylabel('商品數量',fontsize=12)
plt.title('不一樣銷量對應的商品數量分佈',fontsize=12)
銷量在200~20000之間的商品佔比:0.419

#用qcut將price分紅12組
data['group']=pd.qcut(data.price,12)
df_group=data.group.value_counts().reset_index()

#以group列進行分類,求deal銷量的均值
df_sg=data[['deal','group']].groupby('group').mean().reset_index()

#繪柱形圖
index=np.arange(df_sg.group.size)
plt.figure(figsize=(18,5))
plt.bar(index,df_sg.deal)
plt.xticks(index,df_sg.group,fontsize=11)
plt.xlabel('類別',fontsize=12)
plt.ylabel('平均銷量',fontsize=12)
plt.title('不一樣價格區間商品的平均銷量',fontsize=12)

fig,ax=plt.subplots()
ax.scatter(data['price'],data['deal'])
ax.set_xlabel('價格')
ax.set_ylabel('銷量')
ax.set_title('價格對銷量的影響')
data['GMV']=data['price']*data['deal']

fig,ax=plt.subplots()
ax.scatter(data['price'],data['GMV'])
ax.set_xlabel('價格')
ax.set_ylabel('銷售額')
ax.set_title('價格對銷售額的影響')

【分析3】根據價格、銷量、銷售額分析訂價影響

一、訂價在25元左右的商品最多;

二、銷量越高,商品越少,造成「長尾」分佈;

三、【16.8,19】價格區間的銷量最高,【29.9,34.9】銷量次高峯;

四、價格在15~45之間的銷量和銷售額都不錯,50元以上的零食並不順暢銷。

【總結3】對零食市場而言,應走「薄利多銷」路線,50元如下的市場份額最大。

 

【地域分佈】

plt.figure(figsize=(12,4))
data.province.value_counts().plot(kind='bar')
plt.xticks(rotation=0)    #讓字體橫向分佈
plt.xlabel('省份',fontsize=12)
plt.ylabel('數量',fontsize=12)
plt.title('不一樣省份的商品數量分佈',fontsize=12)

pro_sales=data.pivot_table(index='province',values='deal',aggfunc=np.mean)   #分類求均值
pro_sales.sort_values('deal',inplace=True,ascending=False)
pro_sales=pro_sales.reset_index()

index=np.arange(pro_sales.deal.size)
plt.figure(figsize=(12,4))
plt.bar(index,pro_sales.deal)
plt.xticks(index,pro_sales.province,rotation=0)    #讓字體橫向分佈
plt.xlabel('省份',fontsize=12)
plt.ylabel('平均銷量',fontsize=12)
plt.title('不一樣省份的商品平均銷量分佈',fontsize=12)

pro_sales.to_excel('data/pro_sales.xlsx',index=False)

city_sales=data.pivot_table(index='city',values='deal',aggfunc=np.sum)   #分城市求和
city_sales.sort_values('deal',inplace=True,ascending=False)
city_sales=city_sales.reset_index()
city_sales=city_sales[:30]

index=np.arange(city_sales.deal.size)
plt.figure(figsize=(12,4))
plt.bar(index,city_sales.deal)
plt.xticks(index,city_sales.city,rotation=0)    #讓字體橫向分佈
plt.xlabel('城市',fontsize=12)
plt.ylabel('銷量總和',fontsize=12)
plt.title('不一樣城市的商品銷量之和',fontsize=12)

【分析4】分析地域差別

一、福建的零食商品數量最多(難道是受沙縣小吃主導?),上海次之;

二、湖北雖然在售商品數量較少,但湖北的平均銷量卻最高。城市以武漢和上海銷量最強;

三、在【分析1】中強勢霸榜的川渝美食銷量卻通常,叫好不叫座?

四、銷量高的城市大可能是南方經濟較發達的城市,經濟能帶動美食?南方零食比北方零食更暢銷,猜想南方零食應該種類更加豐富。

相關文章
相關標籤/搜索