1. 程式人生 > >Python網絡爬蟲實戰:天貓胸罩銷售數據分析

Python網絡爬蟲實戰:天貓胸罩銷售數據分析

顯示 來講 數據顯示 display colors python網絡 java 讀者 rep

本文實現一個非常有趣的項目,這個項目是關於胸罩銷售數據分析的。是網絡爬蟲和數據分析的綜合應用項目。本項目會從天貓抓取胸罩銷售數據,並將這些數據保存到SQLite數據庫中,然後對數據進行清洗,最後通過SQL語句、Pandas和Matplotlib對數據進行數據可視化分析。我們從分析結果中可以得出很多有的結果,例如,中國女性胸部標準尺寸是多少;胸罩上胸圍的銷售比例;哪個顏色的胸罩最受女性歡迎。

1. 項目效果展示

本項目涉及到網絡技術、網絡爬蟲技術、數據庫技術、數據分析技術、數據可視化技術。首先應該運行tmallbra.py腳本文件從天貓抓取胸罩銷售數據,並將這些數據保存到SQLite數據庫中。接下來可以執行analyze目錄中的相應Python腳本文件進行可視化數據分析。下面是一些分析結果展示。

技術分享圖片

圖1:ABCD罩杯胸罩銷售比例

技術分享圖片

圖2:胸罩銷售比例(罩杯和上胸圍綜合指標)

技術分享圖片

圖3:胸罩銷售比例(按顏色分析)31

技術分享圖片

圖4:罩杯和下胸圍分布直方圖

其實Google和淘寶也給出了類似的分析結果。Google曾給出了一幅世界女性胸部尺寸分布地圖 ,從地圖中可以明顯看出中國大部分地區呈現綠色(表示平均胸部尺寸為A罩杯),少部分地區呈現藍色(表示平均胸部尺寸為B罩杯),這也基本驗證了圖2所示的統計結果:中國大部分女性胸部尺寸是75B和75A。

再看一下淘寶給出的胸罩(按罩杯和上胸圍統計)銷售比例柱狀圖。

技術分享圖片

圖5:淘寶胸罩銷售比例柱狀圖(按罩杯和上胸圍統計)

從淘寶給出的數據可以看出,銷售最好的胸罩尺寸是75B,這個統計結果雖然銷售比例不同(取的樣本不同而導致的),但按銷售數據排行,這個分析結果與本項目的統計結果(圖2)基本吻合。

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開始。通過這個字段,可以獲得更多的評論數據。

3.抓取天貓胸罩銷售數據

既然對天貓胸罩的評論數據的來源已經非常清楚了,本節就抓取這些數據。在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

4. 抓取胸罩商品列表

應用讓爬蟲自動選取胸罩商品,而不是我們一個一個挑。所以可以利用如下的天貓商城的搜索頁面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

4.將抓取的銷售數據保存到SQLite數據庫中

剩下的工作就很簡單了,只需要對商品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)

5. 數據清洗

如果讀者使用前面介紹的方法從天貓和京東抓取了胸罩銷售數據,現在我們已經有了一個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:清洗後的數據

6. 用SQL語句分析胸罩(按罩杯尺寸)的銷售比例

既然銷售數據都保存在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語句統計胸罩(按罩杯尺寸)銷售比例

其他的銷售數據的分析類似。

7. 用Pandas和Matplotlib分析對胸罩銷售比例進行可視化分析

既然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。這兩個工具真是個強大的東西。祝大家學習愉快

Python爬蟲視頻課程:中國女性胸部大小分析

Python網絡爬蟲實戰:天貓胸罩銷售數據分析