Python之?dāng)?shù)據(jù)爬取&數(shù)據(jù)可視化
前言
臨近中秋,月餅的銷量持續(xù)增長,然而不僅僅是中秋節(jié),非旺季也有很多月餅愛好者在電商平臺購買月餅。本文利用淘寶上的公開數(shù)據(jù),應(yīng)用 python 對月餅非旺季的銷售狀況進(jìn)行分析,并對統(tǒng)計結(jié)果進(jìn)行數(shù)據(jù)可視化的展示。
數(shù)據(jù)來源
本次研究的數(shù)據(jù)來源于淘寶網(wǎng)關(guān)于月餅的公開數(shù)據(jù),整個數(shù)據(jù)集包括 4033條數(shù)據(jù),其中將為空值的數(shù)據(jù)直接從數(shù)據(jù)集中刪除。
數(shù)據(jù)處理
數(shù)據(jù)預(yù)處理
對于較粗糙的數(shù)據(jù):
1.添加列名
2.去除重復(fù)數(shù)據(jù)(翻頁爬取過程中會有重復(fù))
3.購買人數(shù)為空的記錄,替換成0人付款
4.將購買人數(shù)轉(zhuǎn)換為銷量(注意部分單位為萬)
5.刪除無發(fā)貨地址的商品,并提取其中的省份
描述型統(tǒng)計分析
1
價格分布

可以觀察到22元以下占比最多,達(dá)到了百分之七十,說明大部分人在月餅的消費(fèi)上還是比較保守的,更看中的是吃的屬性,而非作為饋贈的禮物。
2
銷量前十店鋪

天貓超市作為綜合性商城,包含多個工廠的品牌種類,因此成為月餅購買者的首選。
3
銷量前十產(chǎn)品

從單個銷量前十的圖中可以看到,非旺季時間排名第一的竟是月餅?zāi)>?。出乎意料,排名第二的是鮮花月餅。
4
全國銷量圖(非旺季)

因?yàn)榉峭?,月銷量到2.5w的很少。只有上海地區(qū)的月銷量有3.6w,而包郵省份江浙地區(qū)的銷量僅有3w和5w,而四川和重慶地區(qū)的月銷量只有5k和2k。
python代碼
數(shù)據(jù)爬取:
代碼塊
#?-*-?coding:?utf-8?-*-
from?selenium?import?webdriver
import?time
import?csv
import?re
#?搜索商品,獲取商品頁碼
def?search_product(key_word):
????#?定位輸入框????browser.find_element_by_id("q").send_keys(key_word)
????#?定義點(diǎn)擊按鈕,并點(diǎn)擊
????browser.find_element_by_class_name('btn-search').click()
????#?最大化窗口:為了方便我們掃碼
????browser.maximize_window()
????#?等待15秒,給足時間我們掃碼
????time.sleep(15)
????#?定位這個“頁碼”,獲取“共100頁這個文本”
????page_info?=?browser.find_element_by_xpath('//div[@class="total"]').text
????#?需要注意的是:findall()返回的是一個列表,雖然此時只有一個元素它也是一個列表。
????page?=?re.findall("(\d+)",page_info)[0]
????return?page
#?獲取數(shù)據(jù)
def?get_data():
????#?通過頁面分析發(fā)現(xiàn):所有的信息都在items節(jié)點(diǎn)下
????items?=?browser.find_elements_by_xpath('//div[@class="items"]/div[@class="item?J_MouserOnverReq??"]')
????for?item?in?items:
????????#?參數(shù)信息
????????pro_desc?=?item.find_element_by_xpath('.//div[@class="row?row-2?title"]/a').text
????????#?價格
????????pro_price?=?item.find_element_by_xpath('.//strong').text
????????#?付款人數(shù)
????????buy_num?=?item.find_element_by_xpath('.//div[@class="deal-cnt"]').text
????????#?旗艦店
????????shop?=?item.find_element_by_xpath('.//div[@class="shop"]/a').text
????????#?發(fā)貨地
????????address?=?item.find_element_by_xpath('.//div[@class="location"]').text
????????#print(pro_desc,?pro_price,?buy_num,?shop,?address)
????????with?open('{}.csv'.format(key_word),?mode='a',?newline='',?encoding='utf-8-sig')?as?f:
????????????csv_writer?=?csv.writer(f,?delimiter=',')
????????????csv_writer.writerow([pro_desc,?pro_price,?buy_num,?shop,?address])
def?main():
????browser.get('https://www.taobao.com/')
????page?=?search_product(key_word)
????print(page)
????get_data()
????page_num?=?1
????while?int(page)?!=?page_num:
????????print("*"?*?100)
????????print("正在爬取第{}頁".format(page_num?+?1))
????????browser.get('https://s.taobao.com/search?q={}&s={}'.format(key_word,?page_num*44))
????????browser.implicitly_wait(15)
????????get_data()
????????page_num?+=?1
????print("數(shù)據(jù)爬取完畢!")
if?__name__?==?'__main__':
????key_word?=?"月餅"
????browser?=?webdriver.Chrome()
????main()
數(shù)據(jù)處理和可視化:
代碼塊
#?導(dǎo)包
import?pandas?as?pd
import?numpy?as?np
import?re
#?導(dǎo)入爬取得到的數(shù)據(jù)
df?=?pd.read_csv("月餅.csv",?engine='python',?encoding='utf-8-sig',?header=None)
df.columns?=?["商品名",?"價格",?"付款人數(shù)",?"店鋪",?"發(fā)貨地址"]
df.head(10)
#?去除重復(fù)值
df.drop_duplicates(inplace=True)
#?處理購買人數(shù)為空的記錄
df['付款人數(shù)']=df['付款人數(shù)'].replace(np.nan,'0人付款')
#?提取數(shù)值
df['num']?=?[re.findall(r'(\d+\.{0,1}\d*)',?i)[0]?for?i?in?df['付款人數(shù)']]??#?提取數(shù)值
df['num']?=?df['num'].astype('float')??#?轉(zhuǎn)化數(shù)值型
#?提取單位(萬)
df['unit']?=?[''.join(re.findall(r'(萬)',?i))?for?i?in?df['付款人數(shù)']]??#?提取單位(萬)
df['unit']?=?df['unit'].apply(lambda?x:10000?if?x=='萬'?else?1)
#?計算銷量
df['銷量']?=?df['num']?*?df['unit']
#?刪除無發(fā)貨地址的商品,并提取省份
df?=?df[df['發(fā)貨地址'].notna()]
df['省份']?=?df['發(fā)貨地址'].str.split('?').apply(lambda?x:x[0])
#?刪除多余的列
df.drop(['付款人數(shù)',?'發(fā)貨地址',?'num',?'unit'],?axis=1,?inplace=True)
#?重置索引
df?=?df.reset_index(drop=True)
df.head(10)?
#df.to_csv('清洗完成數(shù)據(jù).csv')
df1?=?df.sort_values(by="價格",?axis=0,?ascending=False)
df1.iloc[:5,:]
import?jieba
import?jieba.analyse
txt?=?df['商品名'].str.cat(sep='。')
#?添加關(guān)鍵詞
jieba.add_word('粽子',?999,?'五芳齋')
#?讀入停用詞表
stop_words?=?[]
with?open('stop_words.txt',?'r',?encoding='utf-8')?as?f:
????lines?=?f.readlines()
????for?line?in?lines:
????????stop_words.append(line.strip())
#?添加停用詞
stop_words.extend(['logo',?'10',?'100',?'200g',?'100g',?'140g',?'130g'])??
#?評論字段分詞處理
word_num?=?jieba.analyse.extract_tags(txt,
??????????????????????????????????????topK=100,
??????????????????????????????????????withWeight=True,
??????????????????????????????????????allowPOS=())
#?去停用詞
word_num_selected?=?[]
for?i?in?word_num:
????if?i[0]?not?in?stop_words:
????????word_num_selected.append(i)
key_words?=?pd.DataFrame(word_num_selected,?columns=['words','num'])
import?pyecharts
print(pyecharts.__version__)
#?導(dǎo)入包
from?pyecharts.charts?import?Bar
from?pyecharts?import?options?as?opts?
#?計算top10店鋪
shop_top10?=?df.groupby('商品名')['銷量'].sum().sort_values(ascending=False).head(10)
#?繪制柱形圖
bar0?=?Bar(init_opts=opts.InitOpts(width='1350px',?height='750px'))?
bar0.add_xaxis(shop_top10.index.tolist())
bar0.add_yaxis('sales_num',?shop_top10.values.tolist())?
bar0.set_global_opts(title_opts=opts.TitleOpts(title='月餅商品銷量Top10'),
?????????????????????xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
?????????????????????visualmap_opts=opts.VisualMapOpts(max_=shop_top10.values.max()))?
bar0.render("月餅商品銷量Top10.html")
from?pyecharts.charts?import?Map?
#?計算銷量
province_num?=?df.groupby('省份')['銷量'].sum().sort_values(ascending=False)?
#?繪制地圖
map1?=?Map(init_opts=opts.InitOpts(width='1350px',?height='750px'))
map1.add("",?[list(z)?for?z?in?zip(province_num.index.tolist(),?province_num.values.tolist())],
?????????maptype='china'
????????)?
map1.set_global_opts(title_opts=opts.TitleOpts(title='各省份月餅銷量分布'),
?????????????????????visualmap_opts=opts.VisualMapOpts(max_=300000),
?????????????????????toolbox_opts=opts.ToolboxOpts()
????????????????????)
map1.render("各省份月餅銷量分布.html")
from?pyecharts.charts?import?Pie
def?price_range(x):?#按照淘寶推薦劃分價格區(qū)間
????if?x?<=?22:
????????return?'22元以下'
????elif?x?<=?115:
????????return?'22-115元'
????elif?x?<=?633:
????????return?'115-633元'
????else:
????????return?'633元以上'
df['price_range']?=?df['價格'].apply(lambda?x:?price_range(x))?
price_cut_num?=?df.groupby('price_range')['銷量'].sum()?
data_pair?=?[list(z)?for?z?in?zip(price_cut_num.index,?price_cut_num.values)]
print(data_pair)
#?餅圖
pie1?=?Pie(init_opts=opts.InitOpts(width='1350px',?height='750px'))
#?內(nèi)置富文本
pie1.add(?
????????series_name="銷量",
????????radius=["35%",?"55%"],
????????data_pair=data_pair,
????????label_opts=opts.LabelOpts(formatter='{—占比go7utgvlrp%}'),
)
pie1.set_global_opts(legend_opts=opts.LegendOpts(pos_left="left",?pos_top='30%',?orient="vertical"),?
?????????????????????toolbox_opts=opts.ToolboxOpts(),
?????????????????????title_opts=opts.TitleOpts(title='不同價格區(qū)間的月餅銷量占比'))
pie1.render("不同價格區(qū)間的月餅銷量占比.html")
from?pyecharts.charts?import?WordCloud
from?pyecharts.globals?import?SymbolType
#?詞云圖
word1?=?WordCloud(init_opts=opts.InitOpts(width='1350px',?height='750px'))
word1.add("",?[*zip(key_words.words,?key_words.num)],
??????????word_size_range=[20,?200],
??????????shape=SymbolType.DIAMOND)
word1.set_global_opts(title_opts=opts.TitleOpts('月餅商品名稱詞云圖'),
??????????????????????toolbox_opts=opts.ToolboxOpts())
word1.render("月餅商品名稱詞云圖.html")

推薦閱讀
(點(diǎn)擊標(biāo)題可跳轉(zhuǎn)閱讀)
轉(zhuǎn)了嗎 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ?贊了嗎 在看嗎



