利用Python對天貓店鋪銷售進行分析.上

<p>自從上年年底了解到數(shù)據(jù)分析和挖掘這個概念之后,今年1月底畢業(yè)前夕,讓自己完全沉下心來學習Python的數(shù)據(jù),截止到目前也有4個多月了。我稱這條路叫做數(shù)據(jù)之路,我一直在想,我們現(xiàn)在身處在這個被數(shù)據(jù)充滿的世界里面,學會挖掘數(shù)據(jù)以及分析數(shù)據(jù),就像是學會游泳一樣。即使我不是一個數(shù)據(jù)分析師,甚至不是程序員,我僅僅是作為在一家小小的電商公司的計劃工程師,學會數(shù)據(jù)分析一定可以提高我的工作效率(當然最開始的時候是考慮能不能將這個當成自己的副業(yè))。</p>


數(shù)據(jù)之路:

<p>廢話不說,先來聊聊我1月底到現(xiàn)在整個數(shù)據(jù)之路的經(jīng)過。決定了要用Python進行數(shù)據(jù)分析之后,我是先通過這個Codecademy來進行Python學習的。這個網(wǎng)址好像主要是針對網(wǎng)頁編程的。迅速的過完里面的Python練習,有了基本概念,就開始考慮怎么用Python來進行數(shù)據(jù)分析了。</p>

<p>這個時候,第二個網(wǎng)站映入了我的眼簾,叫做Dataquest。這個網(wǎng)址不錯,里面有所有關于數(shù)據(jù)分析的課程,他有三個Level,分別叫做Data Analyst,Data Scientist,以及Data Engineer(這個目前還沒有開放)。</p>

  • Data Analyst的課程包括:基本Python的用法,Pandas的使用,數(shù)據(jù)可視化,Linux系統(tǒng)命令行操作基礎,簡單的爬蟲網(wǎng)絡,統(tǒng)計原理,R語言。
  • Data Scientist可以認為是Data Analyst 的升級版,加入了:機器學習,數(shù)據(jù)結構和算法,高級Python用法,大數(shù)據(jù)的處理方式。

<p>其中部分課程是要收費才能做,我就充了兩個月的Basic會員,將Data Analyst的課程完成了個85%之后感覺就差不多了。</p>

<p>除此之外,還看了些書,最重要當然要看是Python各個庫的Document。</p>


第一個實例:

立項

<p>第一個實例做什么我還是想了好久,想做點實用點的,就選了淘寶的一個門店,來做數(shù)據(jù)每天的銷量以及評論更新狀態(tài)分析吧。任務包括:</p>

  • 收集產(chǎn)品的基本信息;
  • 每天定點收集最新的銷量以及推送的評論;

<p>隨便選了個門店,先打開主頁瀏覽下,發(fā)現(xiàn)是賣傘的,仔細看一下,有5個類別:Black、Air、Bon、Joli、Moma(X系列進去看好像都停售,就不管了)。</p>

Request扒內容

<p>采用Requests模塊,采用get(說起來get函數(shù)和post函數(shù)是什么區(qū)別,什么時候要用get函數(shù)或者post函數(shù),到現(xiàn)還沒有搞懂)函數(shù)將url里面的內容扒下來,同時加了headers,將自己偽裝成瀏覽器。將扒下來來的內容用BeautifulSoup進行中‘lxml’解析器進行解析,這樣網(wǎng)頁的內容就像是被扒光衣服一樣展示在我們面前。</p>

<p>另外,在BeautifulSoup中有四種解析器,分別是自帶的、'lxml'、‘xml’以及‘html5lib’四種解析器,具體區(qū)別可以看Document文件。</p>

import requests
from bs4 import BeautifulSoup

url = "https://bananaumbrella.tmall.com/?"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36"}
response = requests.get(url, headers = headers)
interial = BeautifulSoup(response.content, "lxml")

<p>獲得HTML的內容之后,快速在Console上Crtl+F尋找上面的幾個類別,很快就找到了這個這段代碼(每個類別都類似,就復制兩段),每個href中的catName很明顯就是我們要找的東西:</p>

<li class="cat fst-cat">
<li class="cat fst-cat">
<h4 class="cathd fst-cat-hd ">
<i class="cat-icon fst-cat-icon active-trigger"></i>
<a class="cat-name fst-cat-name" >Black</a>
</h4>
</li>
<li class="cat fst-cat">
<h4 class="cat-hd fst-cat-hd ">
<i class="cat-icon fst-cat-icon active-trigger"></i>
<a class="cat-name fst-cat-name" >Air</a>
</h4>
</li>

<p>其中,每個tag里面的href中的url就是我們需要的。利用BeautifulSoup中的find_all函數(shù)將這些標簽抓出來,先通過find_all尋找所有a標簽,返回一個含有a標簽的list,再通過list的鏈表推導式將其中的href抓取出來。其中get()是個好東西,例如這句話:</p>

<a class="cat-name fst-cat-name" >Moma</a>

<p>通過get('href')就可以直接獲得其中的鏈接,對獲得的list再通過list slice就可以得到每個類別的url。</p>

categroys = interial.find_all("a")
categroy = [item.get("href") for item in categroys if item.get("class") == ['cat-name', 'fst-cat-name']]
categroy = categroy[1:]
建立Sqlite數(shù)據(jù)庫

<p> 我也不知道為什么我對Sql如此的喜歡,其中項目一開始我是導出為csv函數(shù)的,后來大概是可能想到之前在dataquest上學了Sql的語法,就想在這個任務里面嘗試吧。(從最終的結果來看,其實我不太能分別我最后得到db好還是csv好,求大神指點呀。。)</p>

<p>在Sql上學過db中幾個表格的關聯(lián),經(jīng)過無數(shù)次的嘗試,我知道每次采集的數(shù)據(jù)中有很多相同的參數(shù),例如產(chǎn)品的ID(skuid),名稱(name),鏈接地址(href),原售價(oldprice),活動售價(price)。而變化的參數(shù)有兩個:</p>

  • 銷量(scount)
  • 評論(cite)

<p>評論和銷量每次更新時,都會以當前時間增加一列,加入新內容。</p>

<p>因此我就想到了用采用表格的鍵約束,制作一個主表用于存放變化不變的參數(shù),制作兩個附表分別存放銷量和評論,主表的附表之間通過鍵(key)來連接。</p>

<p>所以首先當然是要建立一個數(shù)據(jù)庫db文件了,然后建立表格,建表的時候一開始我是采用CREATE TABLE UB(skuid int primary key , name text, href text, oldprice real, price real);,后來發(fā)現(xiàn)如果重復調試這個程序的時候,必須要先將久的db文件刪除之后,才能執(zhí)行,不然回報錯。所以后面我就將這句話改成CREATE TABLE IF NOT EXISTS UB(skuid int primary key , name text, href text, oldprice real, price real);。</p>

<p>建立主表時候,一個要約定哪個是鍵(primary key),這里采用每個商品的id作為鍵(key),而主表UB里面的是primary key,附表 scount 和 cite 里面的是foreign key。</p>

import datetime, sqlite3

conn = sqlite3.connect("data.db")
time = datetime.datetime.now()
c = conn.cursor()
time = time.strftime("%Y%m%d-%H%M")
c.execute("CREATE TABLE IF NOT EXISTS UB(skuid int primary key , name text, href text, oldprice real, price real);")
c.execute("CREATE TABLE IF NOT EXISTS CITE(citeskuid int, FOREIGN KEY(citeskuid) REFERENCES UB(skuid));")
c.execute("CREATE TABLE IF NOT EXISTS SCOUNT(scountskuid int, FOREIGN KEY(scountskuid) REFERENCES UB(skuid));")
c.execute("ALTER TABLE CITE ADD COLUMN '%s' 'text';" % time)
c.execute("ALTER TABLE SCOUNT ADD COLUMN '%s' 'int';" % time)
解析每個類別網(wǎng)址的內容

<p>首先繼續(xù)采用Requests函數(shù)以及BeautifulSoup函數(shù)去將頁面的內容解析出來,過程和我們一開始做的一樣,不做重復。</p>

<p>結合瀏覽器的Inspect功能進行搜索,不難找到每個類似的這樣一段內容(誰可以告訴我像這種html正確的排版應該是怎樣的。。。):</p>

<div class="popitem" style="width:167px;">
<a class="pic"  style="width:167px;" target="_blank">
<img data-ks-lazyload="http://gdp.alicdn.com/bao/uploaded/i4/TB13q8EKpXXXXbzaXXXXXXXXXXX_!!0-item_pic.jpg_220x10000.jpg" src="http://assets.alicdn.com/s.gif" title="【新品】BananaUmbrella蕉下小黑傘蘇桃雙層防曬女太陽傘遮陽傘" width="167"/> 
</a>
<div class="expannel expannel-float">
<a class="mask"  style="display:block;visibility:visible;" target="_blank">
</a>
<div class="exinfo exi_2 ext_4 abs" style="bottom:0px;">
<div class="desc">
<a  target="_blank">【新品】BananaUmbrella蕉下小黑傘蘇桃雙層防曬女太陽傘遮陽傘</a>
</div>
<div class="scount" style="float:left;">
<i>已售:</i> 
<em>(218520)</em>
</div>
<div class="simple-sns sns-widget" data-like='{"title":"http://item.taobao.com/item.htm?id=24875700842","key":"24875700842","type":2}' style="float:left;"></div>
<div class="simple-sns sns-widget" data-sharebtn='{"type":"item","key":"24875700842","client_id":"68"}' style="float:right;" title="微博分享"></div>
<div style="clear:both;"></div>
</div>
</div>
<div class="itembox" style="width:167px;">
<div class="bottom-sprice">
<a  target="_blank">
<span class="rmb">RMB: </span><em>249.00</em>
<s class="oldprice"><span class="rmb">RMB: </span><em>599</em></s>
</a>
</div>
</div>
<div class="rates" style="width:167px;">
<div class="feedback">
<img data-ks-lazyload="http://wwc.alicdn.com/avatar/getAvatar.do?userId=0&width=24&height=24&type=sns" height="20" src="http://assets.alicdn.com/s.gif"/> 
 <span>1***_</span> 質量很好,遮陽也超好,就是份量有點撐,因為是雙層所以卷完也比較大,總體還是不錯的
</div>
</div>
</div>

<p>里面涵蓋了所有我們需要的信息。因此,先用find_all函數(shù)將所有tag為div,classpopitem的先扒出來。扒出來之后,發(fā)現(xiàn)list有重復的,通過set函數(shù)刪除重復的項目</p>

find_item = interial_item.find_all("div", "popitem")
find_item = list(set(find_item))

<p>對find_item里面的內容進行循環(huán),開始按照我們的需要將里面的內容一個個的剔除出來。</p>

<p>先是找出我們的primary key。在classdesc的標簽中,里面就包含了產(chǎn)品的商品的名字以及對應的鏈接,再仔細看看鏈接回發(fā)現(xiàn)后面有id=24875700842,這就是我們要找的。注意,找class時候可以同時根據(jù)tagclass一起找,而class的尋找除了可以用上面的方法,還可以通過關鍵字class_(區(qū)別class,用class會報錯)來尋找。找到href之后,發(fā)現(xiàn)我們要的id就是一串數(shù)字,可以通過正則表達式re.search("\d+", href)來搜索,并通過group()返回搜索的字符串,再通過int將字符串轉為整型,最終寫為:</p>

desc = item.find("div", class_="desc")
href = desc.a.get("href")
pri = int(re.search("\d+", href).group())

<p>這個時候,基本信息已經(jīng)找到了,可以將相應的信息寫入我們的主表中,寫的時候需要判斷,這個id在我們的表格中是否存在,如果存在我們就不繼續(xù)添加信息到主表中:</p>

c.execute("SELECT skuid FROM UB;")
if (pri,) not in c.fetchall():
    name = desc.string
    prices = item.find("div", class_="bottom-sprice").find_all("em")
    price = float(prices[0].string)
    oldprice = float(prices[1].string)
    href = "https:" + href
    c.execute("INSERT INTO UB VALUES(?, ?, ?, ?, ?);", [pri, name, href, oldprice, price]) 

<p>后面就是將sount和cite扒出來,scount容易通過item.em.string就出來,但是剔除出來的是一個帶括號的字符,寫一個正則表達式的函數(shù)將括號剔除:</p>

def del_par(string):
    patt = re.compile("\((.*)\)")
    str_list = patt.findall(string)
    return int(str_list[0])

<p>對應的scount和cite找到之后,就要考慮怎么將數(shù)據(jù)寫入到我們的附表中,這個時候需要注意有兩種情況,如果是第一次輸入的時候,需要加入產(chǎn)品的skuid以及相應的內容,如果是判定該skuid是已經(jīng)在附表的id列表中,那就直接更新對應列的數(shù)據(jù)即可:</p>

scount = del_par(item.em.string)
feedback = item.find("div", "feedback").contents
user = feedback[2].string
cite = user + ":" +feedback[3]     
c.execute("SELECT scountskuid FROM SCOUNT;")
if (pri,) not in c.fetchall():
    c.execute("INSERT INTO SCOUNT(scountskuid, '%s') VALUES('%s', '%s');" % (time, pri, scount))
    c.execute("INSERT INTO CITE(citeskuid, '%s') VALUES('%s', '%s');" % (time, pri, scount))           
else:
    c.execute("UPDATE SCOUNT SET '%s' = '%s' WHERE scountskuid = '%s';" % (time, scount, pri))
    c.execute("UPDATE CITE SET '%s' = '%s' WHERE citeskuid = '%s';" % (time, cite, pri))

最后,寫完之后。還要將所有我們的命令提交才叫完成:

c.close()
conn.commit()
Ubuntu定時任務

<p>為了可以時刻監(jiān)控數(shù)據(jù),需要在Ubuntu里面設置任務,買了一個國外的服務DigitalOcean,并設置Ubuntu的定時任務:</p>

$ crontab -e

<p>通過nano設置任務:</p>

30 8,13,18,23 * * * [script address] >> [log record] 2<&1

結語:

<p>這樣就基本完成自己寫的第一個項目任務了,可以收集信息,可以儲存數(shù)據(jù),當然稍作改動就可以將數(shù)據(jù)保存為csv。除此之外,后續(xù)這個程序還有改進的空間,包括:</p>

  • 每天晚上對一天采集的數(shù)據(jù)進行分析,分析出今天的最佳銷量(用Sql就可以實現(xiàn))
  • 通過銷量和單價計算每日的銷售額(終于需要可以用Pandas了)
  • 將上面的內容統(tǒng)一生成pdf報表(pdf生成目前還沒有思路)
  • 將報表發(fā)到郵箱中(發(fā)送郵箱應該是可以很輕松完成的)

<p>下一篇文章將會對這方面進行重點研究。</p>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容