利用Python对天猫店铺销售进行分析.上

作者: Garfield_Liang | 来源:发表于2016-06-11 16:10 被阅读1066次

    <p>自从上年年底了解到数据分析和挖掘这个概念之后,今年1月底毕业前夕,让自己完全沉下心来学习Python的数据,截止到目前也有4个多月了。我称这条路叫做数据之路,我一直在想,我们现在身处在这个被数据充满的世界里面,学会挖掘数据以及分析数据,就像是学会游泳一样。即使我不是一个数据分析师,甚至不是程序员,我仅仅是作为在一家小小的电商公司的计划工程师,学会数据分析一定可以提高我的工作效率(当然最开始的时候是考虑能不能将这个当成自己的副业)。</p>


    数据之路:

    <p>废话不说,先来聊聊我1月底到现在整个数据之路的经过。决定了要用Python进行数据分析之后,我是先通过这个Codecademy来进行Python学习的。这个网址好像主要是针对网页编程的。迅速的过完里面的Python练习,有了基本概念,就开始考虑怎么用Python来进行数据分析了。</p>

    <p>这个时候,第二个网站映入了我的眼帘,叫做Dataquest。这个网址不错,里面有所有关于数据分析的课程,他有三个Level,分别叫做Data Analyst,Data Scientist,以及Data Engineer(这个目前还没有开放)。</p>

    • Data Analyst的课程包括:基本Python的用法,Pandas的使用,数据可视化,Linux系统命令行操作基础,简单的爬虫网络,统计原理,R语言。
    • Data Scientist可以认为是Data Analyst 的升级版,加入了:机器学习,数据结构和算法,高级Python用法,大数据的处理方式。

    <p>其中部分课程是要收费才能做,我就充了两个月的Basic会员,将Data Analyst的课程完成了个85%之后感觉就差不多了。</p>

    <p>除此之外,还看了些书,最重要当然要看是Python各个库的Document。</p>


    第一个实例:

    立项

    <p>第一个实例做什么我还是想了好久,想做点实用点的,就选了淘宝的一个门店,来做数据每天的销量以及评论更新状态分析吧。任务包括:</p>

    • 收集产品的基本信息;
    • 每天定点收集最新的销量以及推送的评论;

    <p>随便选了个门店,先打开主页浏览下,发现是卖伞的,仔细看一下,有5个类别:Black、Air、Bon、Joli、Moma(X系列进去看好像都停售,就不管了)。</p>

    Request扒内容

    <p>采用Requests模块,采用get(说起来get函数和post函数是什么区别,什么时候要用get函数或者post函数,到现还没有搞懂)函数将url里面的内容扒下来,同时加了headers,将自己伪装成浏览器。将扒下来来的内容用BeautifulSoup进行中‘lxml’解析器进行解析,这样网页的内容就像是被扒光衣服一样展示在我们面前。</p>

    <p>另外,在BeautifulSoup中有四种解析器,分别是自带的、'lxml'、‘xml’以及‘html5lib’四种解析器,具体区别可以看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" href="//bananaumbrella.tmall.com/category-819110723.htm?search=y&catName=Black">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" href="//bananaumbrella.tmall.com/category-819110724.htm?search=y&catName=Air">Air</a>
    </h4>
    </li>
    

    <p>其中,每个tag里面的href中的url就是我们需要的。利用BeautifulSoup中的find_all函数将这些标签抓出来,先通过find_all寻找所有a标签,返回一个含有a标签的list,再通过list的链表推导式将其中的href抓取出来。其中get()是个好东西,例如这句话:</p>

    <a class="cat-name fst-cat-name" href="//bananaumbrella.tmall.com/category-1184183711.htm?search=y&catName=Moma">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数据库

    <p> 我也不知道为什么我对Sql如此的喜欢,其中项目一开始我是导出为csv函数的,后来大概是可能想到之前在dataquest上学了Sql的语法,就想在这个任务里面尝试吧。(从最终的结果来看,其实我不太能分别我最后得到db好还是csv好,求大神指点呀。。)</p>

    <p>在Sql上学过db中几个表格的关联,经过无数次的尝试,我知道每次采集的数据中有很多相同的参数,例如产品的ID(skuid),名称(name),链接地址(href),原售价(oldprice),活动售价(price)。而变化的参数有两个:</p>

    • 销量(scount)
    • 评论(cite)

    <p>评论和销量每次更新时,都会以当前时间增加一列,加入新内容。</p>

    <p>因此我就想到了用采用表格的键约束,制作一个主表用于存放变化不变的参数,制作两个附表分别存放销量和评论,主表的附表之间通过键(key)来连接。</p>

    <p>所以首先当然是要建立一个数据库db文件了,然后建立表格,建表的时候一开始我是采用CREATE TABLE UB(skuid int primary key , name text, href text, oldprice real, price real);,后来发现如果重复调试这个程序的时候,必须要先将久的db文件删除之后,才能执行,不然回报错。所以后面我就将这句话改成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)
    
    解析每个类别网址的内容

    <p>首先继续采用Requests函数以及BeautifulSoup函数去将页面的内容解析出来,过程和我们一开始做的一样,不做重复。</p>

    <p>结合浏览器的Inspect功能进行搜索,不难找到每个类似的这样一段内容(谁可以告诉我像这种html正确的排版应该是怎样的。。。):</p>

    <div class="popitem" style="width:167px;">
    <a class="pic" href="//item.taobao.com/item.htm?id=24875700842" style="width:167px;" target="_blank">
    <img data-ks-lazyload="//gdp.alicdn.com/bao/uploaded/i4/TB13q8EKpXXXXbzaXXXXXXXXXXX_!!0-item_pic.jpg_220x10000.jpg" src="//assets.alicdn.com/s.gif" title="【新品】BananaUmbrella蕉下小黑伞苏桃双层防晒女太阳伞遮阳伞" width="167"/> 
    </a>
    <div class="expannel expannel-float">
    <a class="mask" href="//item.taobao.com/item.htm?id=24875700842" style="display:block;visibility:visible;" target="_blank">
    </a>
    <div class="exinfo exi_2 ext_4 abs" style="bottom:0px;">
    <div class="desc">
    <a href="//item.taobao.com/item.htm?id=24875700842" 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 href="//item.taobao.com/item.htm?id=24875700842" 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="//wwc.alicdn.com/avatar/getAvatar.do?userId=0&width=24&height=24&type=sns" height="20" src="//assets.alicdn.com/s.gif"/> 
     <span>1***_</span> 质量很好,遮阳也超好,就是份量有点撑,因为是双层所以卷完也比较大,总体还是不错的
    </div>
    </div>
    </div>
    

    <p>里面涵盖了所有我们需要的信息。因此,先用find_all函数将所有tag为divclasspopitem的先扒出来。扒出来之后,发现list有重复的,通过set函数删除重复的项目</p>

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

    <p>对find_item里面的内容进行循环,开始按照我们的需要将里面的内容一个个的剔除出来。</p>

    <p>先是找出我们的primary key。在classdesc的标签中,里面就包含了产品的商品的名字以及对应的链接,再仔细看看链接回发现后面有id=24875700842,这就是我们要找的。注意,找class时候可以同时根据tagclass一起找,而class的寻找除了可以用上面的方法,还可以通过关键字class_(区别class,用class会报错)来寻找。找到href之后,发现我们要的id就是一串数字,可以通过正则表达式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>这个时候,基本信息已经找到了,可以将相应的信息写入我们的主表中,写的时候需要判断,这个id在我们的表格中是否存在,如果存在我们就不继续添加信息到主表中:</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就出来,但是剔除出来的是一个带括号的字符,写一个正则表达式的函数将括号剔除:</p>

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

    <p>对应的scount和cite找到之后,就要考虑怎么将数据写入到我们的附表中,这个时候需要注意有两种情况,如果是第一次输入的时候,需要加入产品的skuid以及相应的内容,如果是判定该skuid是已经在附表的id列表中,那就直接更新对应列的数据即可:</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>为了可以时刻监控数据,需要在Ubuntu里面设置任务,买了一个国外的服务DigitalOcean,并设置Ubuntu的定时任务:</p>

    $ crontab -e
    

    <p>通过nano设置任务:</p>

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

    结语:

    <p>这样就基本完成自己写的第一个项目任务了,可以收集信息,可以储存数据,当然稍作改动就可以将数据保存为csv。除此之外,后续这个程序还有改进的空间,包括:</p>

    • 每天晚上对一天采集的数据进行分析,分析出今天的最佳销量(用Sql就可以实现)
    • 通过销量和单价计算每日的销售额(终于需要可以用Pandas了)
    • 将上面的内容统一生成pdf报表(pdf生成目前还没有思路)
    • 将报表发到邮箱中(发送邮箱应该是可以很轻松完成的)

    <p>下一篇文章将会对这方面进行重点研究。</p>

    相关文章

      网友评论

      本文标题:利用Python对天猫店铺销售进行分析.上

      本文链接:https://www.haomeiwen.com/subject/uszsdttx.html