本文實現一個很是有趣的項目,這個項目是關於胸罩銷售數據分析的。是網絡爬蟲和數據分析的綜合應用項目。本項目會從天貓抓取胸罩銷售數據,並將這些數據保存到SQLite數據庫中,而後對數據進行清洗,最後經過SQL語句、Pandas和Matplotlib對數據進行數據可視化分析。咱們從分析結果中能夠得出不少有的結果,例如,中國女性胸部標準尺寸是多少;胸罩上胸圍的銷售比例;哪一個顏色的胸罩最受女性歡迎。sql
本項目涉及到網絡技術、網絡爬蟲技術、數據庫技術、數據分析技術、數據可視化技術。首先應該運行tmallbra.py腳本文件從天貓抓取胸罩銷售數據,並將這些數據保存到SQLite數據庫中。接下來能夠執行analyze目錄中的相應Python腳本文件進行可視化數據分析。下面是一些分析結果展現。數據庫
圖1:ABCD罩杯胸罩銷售比例json
圖2:胸罩銷售比例(罩杯和上胸圍綜合指標)瀏覽器
圖3:胸罩銷售比例(按顏色分析)31網絡
圖4:罩杯和下胸圍分佈直方圖併發
其實Google和淘寶也給出了相似的分析結果。Google曾給出了一幅世界女性胸部尺寸分佈地圖 ,從地圖中能夠明顯看出中國大部分地區呈現綠色(表示平均胸部尺寸爲A罩杯),少部分地區呈現藍色(表示平均胸部尺寸爲B罩杯),這也基本驗證了圖2所示的統計結果:中國大部分女性胸部尺寸是75B和75A。app
再看一下淘寶給出的胸罩(按罩杯和上胸圍統計)銷售比例柱狀圖。異步
圖5:淘寶胸罩銷售比例柱狀圖(按罩杯和上胸圍統計)函數
從淘寶給出的數據能夠看出,銷售最好的胸罩尺寸是75B,這個統計結果雖然銷售比例不一樣(取的樣本不一樣而致使的),但按銷售數據排行,這個分析結果與本項目的統計結果(圖2)基本吻合。工具
這裏的銷售數據其實就是評論數據。用戶購買一件商品併發了評論,就會記錄銷售數據。分析銷售數據的第一步就是要搞明白數據是怎麼跑到客戶端瀏覽器上的。一般來說,瀏覽器從服務端獲取數據有兩種方式:同步和異步。同步就是數據隨HTML代碼一同發送到客戶端,不過如今的大型網站不多有用同步方式傳輸數據了。異步方式是HTML代碼與數據分別發送到客戶端,數據通常是JSON格式,經過AJAX技術獲取,而後再使用JS將獲取到的數據顯示在HTML中的元素上。不過有時會加一些反爬蟲技術,或處於其餘目的,異步數據可能並非純的JSON格式,例如,有多是一段JavaScript代碼,或在JSON格式數據中加一些其餘的內容。不過這些基本都沒用,加的內容確定是有規律的,不然本身的程序都沒法讀了。
如今進到天貓商城官網https://www.tmall.com,在搜索框輸入「胸罩」,點擊「搜索」按鈕進行搜索。隨便找一個銷售胸罩的店鋪點進去。而後在頁面的右鍵菜單中點擊「檢查」菜單項,打開調試窗口,切換到「Network」標籤頁。接下來查看商品的評論,會在「Network」標籤頁顯示評論信息要訪問的Url。在上方的搜索框輸入「list_detail」,會列出全部已「list_detail」做爲前綴的Url。這些Url就是用AJAX異步獲取的評論數據。點擊某個Url,會在右側顯示如圖6所示的數據,很明顯,這些數據與JSON很是像,不過加了一些前綴以及其餘信息,估計是要知足一些特殊須要。
圖6:天貓評論數據
在返回的評論數據中,rateList就是咱們須要的信息,rateList列表中一共是20個對象,包含了20條評論數據,也就是說,經過這個Url,每次返回了20條評論數據。
在Url中還有兩個HTTP GET請求字段對咱們有用。
• itemId:當前商品的ID,經過這個字段,能夠得到指定商品的評論數
據(不光是胸罩)。
• currentPage:當前的頁碼,從1開始。經過這個字段,能夠得到更多的評論數據。
既然對天貓胸罩的評論數據的來源已經很是清楚了,本節就抓取這些數據。在tmallbra.py腳本文件中有一個核心函數,用於抓取指定商品的某一頁評論數據。
def getRateDetail(itemId,currentPage): # Url最後的callback字段是用於天貓網站內部回調的,和咱們不要緊,不過這個字段的值關係到 # 返回數據的前綴,咱們能夠利用這個值去截取返回數據 url = 'https://rate.tmall.com/list_detail_rate.htm?itemId=' + str(itemId) + '&spuId=837695373&sellerId=3075989694&order=3¤tPage=' + str(currentPage) + '&append=0... ...&callback=jsonp1278' r = http.request('GET',url,headers = headers) # 返回數據時GB18030編碼,因此要用這個編碼格式進行解碼 c = r.data.decode('GB18030') # 下面的代碼將返回的評論數據轉換爲JSON格式 c = c.replace('jsonp1278(','') c = c.replace(')','') c = c.replace('false','"false"') c = c.replace('true','"true"') # 將JSON格式的評論數據轉換爲字典對象 tmalljson = json.loads(c) return tmalljson
應用讓爬蟲自動選取胸罩商品,而不是咱們一個一個挑。因此能夠利用以下的天貓商城的搜索頁面Url進行搜索,按銷量從大到小排列。
https://list.tmall.com/search_product.htm... ...
這個Url不須要傳遞任何參數,本項目只取第一個商品頁的全部商品。在tmallbra.py腳本文件中有一個而核心函數getProductIdList,用於返回第一個商品頁的全部商品ID(以列表形式返回)。
def getProductIdList(): url = 'https://list.tmall.com/search_product.htm... ...' r = http.request('GET', url,headers = headers) c = r.data.decode('GB18030') soup = BeautifulSoup(c,'lxml') linkList = [] idList = [] # 用Beautiful Soup提取商品頁面中全部的商品ID tags = soup.find_all(href=re.compile('detail.tmall.com/item.htm')) for tag in tags: linkList.append(tag['href']) linkList = list(set(linkList)) for link in linkList: aList = link.split('&') # //detail.tmall.com/item.htm?id=562173686340 # 將商品ID添加到列表中 idList.append(aList[0].replace('//detail.tmall.com/item.htm?id=','')) return idList
剩下的工做就很簡單了,只須要對商品ID列表迭代,而後對每個商品的評論數據進行抓取,天貓每一個商品最多能夠得到99頁評論,最大評論頁數能夠經過getLastPage函數得到。
def getLastPage(itemId): tmalljson = getRateDetail(itemId,1) return tmalljson['rateDetail']['paginator']['lastPage']
下面的代碼會抓取商品搜索第一頁的全部胸罩商品的評論數據,並將這些數據保存到SQLite數據庫中。
# 對商品ID進行迭代 while initial < len(productIdList): try: itemId = productIdList[initial] print('----------',itemId,'------------') maxnum = getLastPage(itemId) num = 1 while num <= maxnum: try: # 抓取某個商品的某頁評論數據 tmalljson = getRateDetail(itemId, num) rateList = tmalljson['rateDetail']['rateList'] n = 0 while n < len(rateList): # 顏色分類:H007淺藍色加粉色;尺碼:32/70A colorSize = rateList[n]['auctionSku'] m = re.split('[:;]',colorSize) rateContent = rateList[n]['rateContent'] color = m[1] size = m[3] dtime = rateList[n]['rateDate'] # 將抓取的數據保存到SQLite數據庫中 cursor.execute('''insert into t_sales(color,size,source,discuss,time) values('%s','%s','%s','%s','%s') ''' % (color,size,'天貓',rateContent,dtime)) conn.commit() n += 1 print(color) print(num) num += 1 except Exception as e: continue initial += 1 except Exception as e: print(e)
若是讀者使用前面介紹的方法從天貓和京東抓取了胸罩銷售數據,如今咱們已經有了一個SQLite數據庫,裏面有一個t_sales表,保存了全部抓取的數據,如圖7所示。
圖7:保存到數據庫中的胸罩銷售數據
從銷售數據能夠看出,網絡爬蟲抓取了顏色(color)、尺寸(size)、來源(source)、評論(discuss)和時間(time)五類數據。固然還能夠抓取更多的數據,這裏只爲了演示數據分析的方法,因此並無抓取那麼多的數據。
不過這五類數據有些不規範,本項目值考慮color和size,因此先要對這兩類數據進行清洗。因爲每一個店鋪,每一個商品的顏色叫法可能不一樣,因此須要將這些顏色值統一一下。例如,全部包含「黑」的顏色值均可以認爲是黑色。因此能夠新創建一個color1字段(儘可能不要修改原始數據),將清洗後的顏色值保存到color1字段中。而後可使用下面的SQL語句對顏色值進行清洗。
update t_sales set color1 = '黑色' where color like '%黑%' ; update t_sales set color1 = '綠色' where color like '%綠%' ; update t_sales set color1 = '紅色' where color like '%紅%' ; update t_sales set color1 = '白色' where color like '%白%' ; update t_sales set color1 = '藍色' where color like '%藍%' ; update t_sales set color1 = '粉色' where color like '%粉%' and color1 is null ; update t_sales set color1 = '青色' where color like '%青%' ; update t_sales set color1 = '卡其色' where color like '%卡其%' ; update t_sales set color1 = '紫色' where color like '%紫%' ; update t_sales set color1 = '膚色' where color like '%膚%' ; update t_sales set color1 = '水晶蝦' where color like '%水晶蝦%' ; update t_sales set color1 = '玫瑰色' where color like '%玫瑰%' ; update t_sales set color1 = '銀灰' where color like '%銀灰%' ;
胸罩尺寸清洗的方式與胸罩顏色相似,你們能夠本身經過SQL語句去完成。
清洗完的結果如圖8所示。
圖8:清洗後的數據
既然銷售數據都保存在SQLite數據庫中,那麼咱們不妨先用SQL語句作一下統計分析。本節將對胸罩按罩杯的銷售量作一個銷售比例統計分析。因爲抓取的數據沒有超過D罩杯的,因此作數據分析時就不考慮D以上罩杯的胸罩銷售數據了。這裏只考慮A、B、C和D罩杯胸罩的銷售數據。
本節要統計的是某一個尺寸的胸罩銷售數量佔整個銷售數量的百分比,這裏須要統計和計算以下3類數據。
• 某一個尺寸的胸罩銷售數量。
• 胸罩銷售總數量
• 第1類數據和第2類數據的差值(百分比)
這3類數據徹底能夠用一條SQL語句搞定,爲了同時搞定A、B、C和D罩杯的銷售比例,能夠用4條相似的SQL語句,中間用union all鏈接。
select 'A' as 罩杯,printf("%.2f%%",(100.0 * count(*)/ (select count(*) from t_sales where size1 is not null))) as 比例, count(*) as 銷量 from t_sales where size1='A' union all select 'B',printf("%.2f%%",(100.0 * count(*)/ (select count(*) from t_sales where size1 is not null))) , count(*) as c from t_sales where size1='B' union all select 'C',printf("%0.2f%%",(100.0 * count(*)/ (select count(*) from t_sales where size1 is not null))) , count(*) as c from t_sales where size1='C' union all select 'D',printf("%.2f%%",(100.0 * count(*)/ (select count(*) from t_sales where size1 is not null))) , count(*) as c from t_sales where size1='D' order by 銷量 desc
上面的SQL語句不只加入了銷售比例,還加入了銷售數量,而且按銷量降序排列。這些SQL語句須要考慮size1字段空值的狀況,由於抓取的少部分銷售記錄並無罩杯尺寸數據。執行上面的SQL語句後,會輸出如圖9所示的查詢結果。
圖9:用SQL語句統計胸罩(按罩杯尺寸)銷售比例
其餘的銷售數據的分析相似。
既然Python提供了這麼好的Pandas和Matplotlib,那麼就能夠徹底不使用SQL語句進行數據分析了。能夠100%使用Python代碼搞定一切。
本節將使用Pandas完成與上一節相同的數據分析,並使用Matplotlib將分析結果以圖形化方式展示出來。
Pandas在前面的章節已經講過了,這裏再也不深刻介紹。本次分析主要使用了groupby方法按罩杯(size1)分組,而後使用count方法統計組內數量,最後使用insert方法添加了一個「比例」字段。
from pandas import * from matplotlib.pyplot import * import sqlite3 import sqlalchemy # 打開bra.sqlite數據庫 engine = sqlalchemy.create_engine('sqlite:///bra.sqlite') rcParams['font.sans-serif'] = ['SimHei'] # 查詢t_sales表中全部的數據 sales = read_sql('select source,size1 from t_sales',engine) # 對size1進行分組,並統計每一組的記錄數 size1Count = sales.groupby('size1')['size1'].count() print(size1Count) # 計算總銷售數量 size1Total = size1Count.sum() print(size1Total) print(type(size1Count)) # 將Series轉換爲DataFrame size1 = size1Count.to_frame(name='銷量') print(size1) # 格式化浮點數 options.display.float_format = '{:,.2f}%'.format # 插入新的「比例」列 size1.insert(0,'比例', 100 * size1Count / size1Total) print(size1) # 將索引名改成「罩杯」 size1.index.names=['罩杯'] print(size1) # 數據可視化 print(size1['銷量']) # 餅圖要顯示的文本 labels = ['A罩杯','B罩杯','C罩杯','D罩杯'] # 用餅圖繪製銷售比例 size1['銷量'].plot(kind='pie',labels = labels, autopct='%.2f%%') # 設置長寬相同 axis('equal') legend() show()
運行程序,會看到在窗口上繪製瞭如圖10所示的胸罩銷售比例。用Pandas分析獲得的數據與使用SQL分析獲得的數據徹底相同。
圖10:胸罩銷售比例(按罩杯尺寸)
其餘分析也可使用Pandas,可視化使用Matplotlib。這兩個工具真是個強大的東西。祝你們學習愉快