1. 程式人生 > >python資料分析之你不知道的bra

python資料分析之你不知道的bra

 

曾經,我把目光放在你身體上四分位的地方,發現了世界的美好。。。

之後,山水流轉,時光荏苒,不再從前。。。

此一文,獻給過往。

先上張圖:好奇怪,為什麼是這麼個比例[皺眉]

這篇文章分為兩個部分,python爬蟲和資料分析。爬取京東bra一些資料,並進行分析,在上帝視角看一看bra的祕密。

第一部分,爬蟲部分。

爬蟲部分利用python和selenium包,爬取京東資料,將資料儲存在資料庫中。

第二部分,將爬到的資料使用pandas包和matplotlib包進行清洗,在視覺化

第一步,先匯入包,需要匯入的包有,selenium包,用來模仿瀏覽器,lxml包,用來分析網頁資訊,顯示等待和隱式等待包,資料庫包。如下

from selenium import webdriver
import time
from lxml import etree
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from databases import Write_databases

然後,寫開啟瀏覽器介面,再獲取URL列表時,使用PhantomJS瀏覽器。

#開啟瀏覽器,返回driver
def open_web():
    driver = webdriver.PhantomJS()
    return driver

獲取京東商城前100也的bra商品詳情頁的URL,(前100頁已經足夠了,50頁之後的商品就基本沒有銷售資訊了)

#獲取bra列表,獲取每個bra的ID,生成詳情頁的url,返回url列表
def get_bra_list(driver,url):
    bra_list_urls = [] #定義URL列表
    driver.get(url)#開啟瀏覽器
    i=100
    while i>0:#設定爬取前100頁
        html = etree.HTML(driver.page_source)
        bra_lists = html.xpath(".//div[@id='J_goodsList']/ul/li")

        for bra_list in bra_lists:
            bra_id = bra_list.xpath(".//div[@class='p-price']/strong/@class")
            bra_detail_url = 'https://item.jd.com/'+bra_id[0].split('_')[1]+'.html'
            bra_list_urls.append(bra_detail_url)

        next_btn = driver.find_element_by_class_name('pn-next')#某一頁資料爬取完成時,點選下一頁按鈕
        next_btn.click()
        i -= 1
        print("=*"*20+str(i))

    return bra_list_urls

得到URL列表之後,再按照列表中的URL一個一個爬取即可。

爬取詳細URL相應資訊,進入詳情頁面之後,首先需要爬取價格,然後點選商品評價,如圖

preview

然後再爬取商品評價中的顏色,尺寸,時間

如下步驟,這次,使用Chrome瀏覽器

#進入詳情頁獲取每個bra的資訊,
def get_bra_info(bra_list_urls):
    path = r'C:\Users\yuy-com\web_driver\chromedriver.exe'#設定Chrome瀏覽器的地址
    sel_driver = webdriver.Chrome(executable_path=path)
    sel_driver.maximize_window()#將瀏覽器設定為最大化
    time.sleep(1)
    for bra_url in bra_list_urls:
        sel_driver.get(url=bra_url)#開啟詳情頁面的URL
         get_current(sel_driver)#開始獲取資料

#獲取評論資訊,返回評論資訊的列表
def get_current(driver):
    bra_de_info = []
    write_data = Write_databases()#初始化資料庫類
    while True:
        souce_html = driver.page_source
        html = etree.HTML(souce_html)
        bra_text = html.xpath(".//div[@class='p-parameter']/ul[2]/li/text()")#獲取商品介紹資訊
        #獲取商品評價
        current_num = html.xpath(".//div[contains(@class,'tab-main')]/ul/li[5]/s/text()")[0].split('(')[1].split(')')[0]
        #如果商品評價為0,則直接跳過
        if current_num == '0':
            print('無評價!')
            continue
        #補貨商品評價標籤,點選
        current = driver.find_element(By.XPATH, ".//div[contains(@class,'tab-main')]/ul/li[5]")
        current.click()
        #解析網頁
        souce_h = etree.HTML(driver.page_source)
        current_list = souce_h.xpath(".//div[@class='tab-con']/div[1]/div")
        
        price = souce_h.xpath(".//div[@class='dd']/span/span[2]/text()")[0]#獲取價格
        brand = souce_h.xpath(".//div[@class='p-parameter']/ul[1]/li/a/text()")[0]#獲取品牌
        bra = {}
        for curr_info in current_list:
            #獲取商品顏色,尺寸和時間資訊
            info = curr_info.xpath(".//div[@class='comment-message']/div/span//text()")
            if info:
                color = info[0]
                size = info[1]
                times = info[2]
                bra['bra_name'] = brand
                bra['bra_color'] = color
                bra['bra_size'] = size
                bra['bra_time'] = times
                bra['bra_price'] = price
                bra['bra_text'] = " ".join(bra_text)

                print('名稱:{},顏色:{},尺寸:{},時間:{},價格:{},描述:{}'.format(brand,color,size, times, price," ".join(bra_text)))
                write_data.insert_data(bra)#寫入資料庫

                bra_de_info.append(bra)
        try:
            點選下一頁獲取評論資訊
            next_btn = driver.find_element(By.XPATH, './/a[@class="ui-pager-next"]')
            WebDriverWait(driver,1000).until(EC.element_to_be_clickable((By.CLASS_NAME,"ui-pager-next")))
            next_btn.click()
        except:
            return bra_de_info

如上步驟資料便可以爬下來了,寫入資料庫之前,我們還需要配置資料庫,在此我新建一個檔案配置。如下

import pymysql#匯入包

class Write_databases():
    def __init__(self):
        self.db = pymysql.connect(
            host = '127.0.0.1',
            user = 'root',
            password = 'root',
            database = 'bra_jd',
            port = 3306
        )
        self.cursor = self.db.cursor()#連線資料庫

    #插入資料介面
    def insert_data(self,data):
        sql = '''
            insert into bra_table(id,bra_name,bra_price,bra_color,bra_size,bra_time,bra_text)
            values(null,%s,%s,%s,%s,%s,%s)
        '''
        self.cursor.execute(sql,(data['bra_name'],data['bra_price'],data['bra_color'],data['bra_size'],data['bra_time'],data['bra_text']))
        self.db.commit()#提交
    #關閉連線
    def close_databases(self):
        self.db.close()

這樣就可以吧資料全部儲存在資料庫中了。大約有兩萬條資料,如下圖所示

我們先看下資料量:有兩萬5前多條

資料清洗:在這裡,我現將資料庫中的資料匯出到cvs檔案,然後pandas包載入檔案。如圖:

首先清洗尺寸資料,清洗之前先看尺寸資料的情況,真的是一片雜亂。

看到這,我的頭一下就很大,慢慢分析吧,分為如下步驟,

首先,先將標記為L,S,M,XL(碼)的資料刪除

bra_da = bra_da[(bra_da['bra_size'] != 'S')
&(bra_da['bra_size'] != 'L')&(bra_da['bra_size'] != 'M')&
(bra_da['bra_size'] != 'X')&(bra_da['bra_size'] != 'XL')&
(bra_da['bra_size'] != 'L碼')&(bra_da['bra_size'] != 'M碼')&
(bra_da['bra_size'] != 'X碼')&(bra_da['bra_size'] != 'XL碼')&
(bra_da['bra_size'] != 'XXL碼')&(bra_da['bra_size'] != 'XXL')]

看了下,雖然少了一點,但是還有很多,繼續

將含有“建議”,“均碼”,“通杯”的資料刪除。因為這些資料沒有明確的指向大小,可以視為垃圾資料。如果含有加號,則取加好之前的資料,否則寫0,最後將寫0的資料刪除,新建一列,用MAP函式實現

def pass_cup_del(bra_data):
    if "+" in bra_data:
        return xxx.split("+")[0]
    elif "建議" in bra_data:
        return '0'
    elif "均碼" in bra_data:
        return '0'
    elif "通杯" in bra_data:
        return '0'
    else:
        return bra_data
 bra_da['bra_size2'] = bra_da['bra_size'].map(pass_cup_del)

分析之後還是很凌亂,決定,將括號刪去,只取括號左邊的資料:再加一列資料,再刪除標記為L,S,M,XL(碼)的資料,將資料框的名稱修改。

def brackets_delete(bra_da):
    if "(" in bra_da:
        return bra_da.split("(")[0]
    else:
        return bra_da

    bra_da['bra_size3'] = bra_da['bra_size2'].map(fun2).map(fun1)

    bra_data = bra_da[(bra_da['bra_size3'] != 'L碼')&(bra_da['bra_size3'] != 'M碼')&(bra_da['bra_size3'] != 'X碼')&(bra_da['bra_size3'] != 'XL碼')&(bra_da['bra_size3'] != 'XXL碼')]

    bra_data.drop(['bra_size2','bra_size'],axis=1,inplace=True)
    bra_da_o = bra_data[bra_data['bra_size3'] == '0']
    bra_data.drop(bra_da_o.index,inplace=True)

到這時,已經差不多了,資料已經變得比較乾淨了,然後將有A的資料換成A,B,C,D,E,F一樣處理

def set_abcd_vlaue(data):
    if 'A' in data:
        return 'A'
    elif 'B' in data:
        return 'B'
    elif 'C' in data:
        return 'C'
    elif 'E' in data:
        return 'E'
    elif 'F' in data:
        return 'F'
    elif 'D' in data:
        return 'D'
    else:
        return '0'

bra_data['bra_size'] = bra_data['bra_size3'].map(set_abcd_vlaue)
    bra_da_o1 = bra_data[bra_data['bra_size'] == '0']
    bra_data.drop(bra_da_o1.index,inplace=True)

如上圖,這樣就處理好了。

然後處理顏色,先看下顏色,竟然五顏六色。[捂臉]

竟然,這麼多顏色,牛X

我將顏色分析了下,準備分為如下色彩:酒紅,棗紅,鈷藍,藏青,紫灰,粉,膚,紅,藍,杏,紫,綠,白,黑,啡,灰,棕

開始處理:

def set_color(color):
    if '酒紅' in color:
        return '酒紅'
    elif '棗紅' in color:
        return '棗紅'
    elif '鈷藍' in color:
        return '鈷藍'
    elif '藏青' in color:
        return '藏青'
    elif '粉' in color:
        return '粉'
    elif '膚' in color:
        return '膚'
    elif '紅' in color:
        return '紅'
    elif '藍' in color:
        return '藍'
    elif '杏' in color:
        return '杏'
    elif '紫' in color:
        return '紫'
    elif '綠' in color:
        return '綠'
    elif '白' in color:
        return '白'
    elif '黑' in color:
        return '黑'
    elif '啡' in color:
        return '啡'
    elif '灰' in color:
        return '灰'
    elif '棕' in color:
        return '棕'
    else:
        return '0'

bra_data['color'] = bra_data['bra_color'].map(set_color)
    bra_color_o = bra_data[bra_data['color'] == '0']
    bra_data.drop(bra_color_o.index,inplace=True)
    bra_data.drop(['bra_color','bra_size3'],axis=1,inplace=True)
    print(set(bra_data['color']))

和之前處理的套路一樣,先將有關的顏色修改,最後刪除無關的顏色項

果然,顏色也分析好了。

看一下處理之後還有多少資料:繩一萬六千多條資料了,應該還能說明點問題。

接下來就是可視化了。視覺化主要分析如下幾項,

1.顏色柱狀圖:我們根據在京東爬的銷售資料,可以檢視在所銷售的bra中,顏色的分部

y_color_valse = []
    bra_color = bra_data['color']
    color_list = set(bra_color)

    for x in color_list:
        num = len(bra_data[bra_data['color'] == x])
        y_color_valse.append(num)

    plt.figure()
    plt.bar(list(color_list),y_color_valse)
    plt.title("bra_color")
    plt.show()

 圖如下:

可見,膚色,黑色,紅色,紫色,佔統治地位,白色酒紅數量較少。我喜歡的粉色,竟然不多,太神奇了。

我們在畫一個顏色的餅圖:

第二個是檢視尺寸的分部

bra_size_label = ['A','B','C','D','E','F']
    y_bra_size = []
    for bra in bra_size_label:
        num = len(bra_data[bra_data['bra_size'] == bra])
        y_bra_size.append(num)
    plt.figure()
    plt.pie(y_bra_size,labels=bra_size_label,autopct='%1.1f%%')
    plt.title("bra_size")
    plt.axis('equal')
    plt.legend(loc='upper left', bbox_to_anchor=(-0.1, 1))
    plt.show()

如圖:B罩杯最多,[偷笑]

 

在這,我們再看看各個品牌的分部:

排名最多的是,carey Key,迪萬,都市麗人,為啥我只聽過都市麗人呢?