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相應資訊,進入詳情頁面之後,首先需要爬取價格,然後點選商品評價,如圖
然後再爬取商品評價中的顏色,尺寸,時間
如下步驟,這次,使用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,迪萬,都市麗人,為啥我只聽過都市麗人呢?