zoukankan      html  css  js  c++  java
  • python爬虫——分析天猫iphonX的销售数据

     
     
     

    01.引言

      这篇文章是我最近刚做的一个项目,会带领大家使用多种技术实现一个非常有趣的项目,该项目是关于苹果机(iphoneX)的销售数据分析,是网络爬虫和数据分析的综合应用项目。本项目会分别从天猫和京东抓取iphoneX的销售数据(利用 Chrome 工具跟踪 Web 数据),并将这些数据保存到 Mysql 数据库中,然后对数据进行清洗,最后通过 SQL 语句、Pandas 和 Matplotlib 对数据进行数据可视化分析。我们从分析结果中可以得出很多有趣的结果,例如,大家最爱买的颜色是,最喜欢的是多少G内存的iphoneX等等,当然本文介绍的只是一个小的应用,时间够的话如果大家刚兴趣可以进一步进行推广。

      废话不多说,马上开始。

    02.分析

      首先从马云粑粑的天猫“取“点数据,取数据的第一步即使要分析一下 Web 页面中数据是如何来的。也就是说数据,数据是通过何种方式发送到客户端浏览器的。天猫和京东的数据基本上没采用什么有意义的反爬技术,所以抓取数据相对比较容易(针对于复杂的后期会介绍抓包工具以及Scrapy框架自动爬取的方式)。

      进到天猫苹果的官方旗舰店后,开始使用 Chrome 浏览器或者火狐都可以,他们都有很方便的调试工具。开始搜索”iphoneX“关键字,然后页面就会弹出iphoneX的商品详情页,浏览商品页面,在页面的右键菜单中点击“检查”菜单项,打开调试窗口,切换到“Network”选项卡,这个选项卡可以实时显示出当前页面向服务端发送的所有请求,以及这些请求的请求头、响应头、响应内容以及其他与调试有关的信息。对于调试和跟踪 Web 应用相当方便。

      打开“Network”选项卡后,进到商品评论处,切换到下一页,会看到“Network”选项卡下方出现很多 URL,这就是切换评论页时向服务端新发出的请求。我们要找的东西就在这些 URL 中。至于如何找到具体的 URL,那就要依靠经验了。可以一个一个点击寻找(在右侧的“Preview”选项卡中显示 URL 的响应内容),也可以根据 URL 名判断,一般程序员不会起无意义的名字,这样很不好维护。这里我们找到一个”list_detail_rate.htm?“的URL,点开后,我们发现如图1所示,ratelist中的信息正是一条条的评论信息,所以也正是我们需要的Url。

    然后右键选中左边”list_detail_rate.htm?“选择保存URL地址,然后用浏览器打开,可以看到如图2所示的内容。

      这个 URL 就是iphoneX的某一页的评论(销售)数据,如果要查询所有的评论数据,就需要动态改变 URL 的参数。下面看一下“Headers”选项卡下面的“Query String Parameters”部分,如图3所示,会清楚地了解该 URL 的具体参数值。

     

      在这些参数中有一部分对我们有用,例如,itemId 表示商品 ID,currentPage 表示当前获取的评论页数,在通过爬虫获取这些评论数据时,需要不断改变这些参数值以获取不同的评论数据。

    尽管根据评论数计算(每页20条评论),某些商品的评论页数可能多达数百页,甚至上千页。

    03.抓取天猫iphoneX的销售数据

      因为本项目抓取指定商品销售数据需要使用 JSON 模块中相应的 API 进行分析,因为返回的销售数据是 JSON 格式的,而从搜索页面抓取的商品列表需要分析 HTML 代码,这里我使用urllib模块。在对数据进行分析整理后,需要将数据保存到 Mysql 数据库中,因此,本例还会使用 mysql.connector 模块,本例使用的其他模块还包括 re正则模块和urllib.error异常处理模块,所以需要在 Python 脚本开头使用下面的代码导入相关模块。

    1
    2
    3
    4
    import urllib
    import mysql.connector
    import re
    import urllib.error

      使用 request 方法发送 HTTP 请求时,可以使用 decode() 函数对 GET 字段进行编码。

    1
    data=urllib.request.urlopen(url).read().decode('GB18030')

      然后,可以利用正则表达式对data数据进行正则匹配,这里就不仔细描述了,代码如下;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    for currentPage in range(1,100):
        try:
            commt_url='https://rate.tmall.com/list_detail_rate.htm?itemId=560257961625&spuId=893336129&sellerId=1917047079&order=3&currentPage='+str(currentPage)+'&append=0&content=1&tagId=&posi=&picture=&'
            proxy_add="119.183.220.224:8088"#设置代理服务器,具体的大家可以去西刺免费的IP网站选择一个,“人生苦短,我选代理”
            #------------备用IP-----------
            #proxy_add="124.128.39.138:8088"
            #proxy_add="223.241.78.1064:8010"
            commt_data=use_proxy_2(commt_url,proxy_add) #爬取网页的评论内容
            #正则匹配目标参数:网络类型、机身颜色、存储容量、购买途径、评价、评论日期   
            pat='"aliMallSeller":.*?auctionSku":"(.*?)","auctionTitle.*?"cmsSource":"(.*?)","displayRatePic.*?"rateContent":"(.*?)","rateDate":"(.*?)","reply.*?":""}'
            list_detail=re.compile(pat).findall(commt_data)
        except urllib.error.URLError as e:
            if hasattr(e,"code"):
                print(e.code)
            if hasattr(e,"reason"):
                print(e.reason)

      正则匹配后的数据一个list,而且所有的数据都在一起,如下所示:

    所以需要对数据进行拆分,生成不同的字段,分别为‘type#网络类型’,‘color#机身颜色’,‘rom #存储容量’,‘source #来源购买途径’,‘discuss #评论’,‘time #评论日期’。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for in range(len(list_detail)):#i表示每页第i条评论
            data=list(list_detail[i])
            #print(data)
            item_data=data[0]
            = re.split('[:;]',item_data)
            #print(m)
            type = m[1]#网络类型
            color = m[3]#机身颜色
            rom = m[5]#存储容量
            source = data[1]#来源购买途径
            discuss = data[2]#评论
            time = data[3]#评论日期

      然后就是将数据存入数据库中,利用python将数据存入数据库的方法有很多,这里我用的是mysql.connector模块。这里在插入数据库前,我们可以先在本地的数据库建好表,如下我用的是MySQL-Front可视化操作工作,比较直观反应。

    然后开始将爬到的数据插入数据库,代码:

    #插入mysql数据库
    #连接数据库,这里注意端口号port的值是int类型,不能写成字符型,我第一次的时候就是吃了苦头
    conn = mysql.connector.connect(
    user='root',
    password='111111',
    host='127.0.0.1',
    port=3306,
    database='pachong'
    )
    #获取游标
    cursor = conn.cursor()
    #插入数据
    cursor.execute("INSERT INTO iphoneX(type,color,rom,source,discuss,time) VALUES ('"+type+"','"+color+"','"+rom+"','"+source+"','"+discuss+"','"+time+"')")
    print('第'+str(currentPage)+'页,第'+str(i)+'条数据') 
    print('************** 数据保存成功 **************')
    #提交数据
    conn.commit()
    #关闭连接
    cursor.close()

      

    保存成功后,再取数据库中查看,如图所示;

    下面看一下完整的实现代码

    复制代码
    import urllib
    import mysql.connector
    import re
    import urllib.error
    #设置请求头headers
    headers=("user-agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36")
    opener=urllib.request.build_opener()
    opener.addheaders=[headers]#添加报头
    urllib.request.install_opener(opener)#设置opner全局化
    #设置代理服务器
    def use_proxy_1(url,proxy_add):
        proxy=urllib.request.ProxyHandler({'http':proxy_add})
        opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
        urllib.request.install_opener(opener)
        data=urllib.request.urlopen(url).read().decode('utf-8')
        return data
    def use_proxy_2(url,proxy_add):
        proxy=urllib.request.ProxyHandler({'http':proxy_add})
        opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
        urllib.request.install_opener(opener)
        data=urllib.request.urlopen(url).read().decode('GB18030')#用GB18030格式转码
        return data
    for currentPage in range(1,30):
        try:
            commt_url='https://rate.tmall.com/list_detail_rate.htm?itemId=560257961625&spuId=893336129&sellerId=1917047079&order=3&currentPage='+str(currentPage)+'&append=0&content=1&tagId=&posi=&picture=&'
            proxy_add="119.183.220.224:8088"#设置代理服务器,具体的大家可以去西刺免费的IP网站选择一个,“人生苦短,我选代理”
            #------------备用IP-----------
            #proxy_add="124.128.39.138:8088"
            #proxy_add="223.241.78.1064:8010"
            commt_data=use_proxy_2(commt_url,proxy_add) #爬取网页的评论内容
            #正则匹配目标参数:网络类型、机身颜色、存储容量、购买途径、评价、评论日期    
            pat='"aliMallSeller":.*?auctionSku":"(.*?)","auctionTitle.*?"cmsSource":"(.*?)","displayRatePic.*?"rateContent":"(.*?)","rateDate":"(.*?)","reply.*?":""}'
            list_detail=re.compile(pat).findall(commt_data)
        except urllib.error.URLError as e:
            if hasattr(e,"code"):
                print(e.code)
            if hasattr(e,"reason"):
                print(e.reason)
        #print(list_detail)
        #返回的结果是list形式,通过循环进行遍历
        #考虑到爬取的数据量比较大,还是来一个异常处理,这个东西是必要的,省很多不必要的麻烦
      
        for i in range(len(list_detail)):#i表示每页第i条评论
            data=list(list_detail[i])
            #print(data)
            item_data=data[0]
            m = re.split('[:;]',item_data)
            #print(m)
            type = m[1]#网络类型
            color = m[3]#机身颜色
            rom = m[5]#存储容量
            source = data[1]#来源购买途径
            discuss = data[2]#评论
            time = data[3]#评论日期
            #print(type,color,rom,source,discuss,time)
    
            try:
                #插入mysql数据库
                #连接数据库,这里注意端口号port的值是int类型,不能写成字符型,我第一次的时候就是吃了苦头
                conn = mysql.connector.connect(
                    user='root',
                    password='111111',
                    host='127.0.0.1',
                    port=3306,
                    database='pachong'
                )
                #获取游标
                cursor = conn.cursor()
                #插入数据
                cursor.execute("INSERT INTO iphoneX(type,color,rom,source,discuss,time) VALUES ('"+type+"','"+color+"','"+rom+"','"+source+"','"+discuss+"','"+time+"')")
                print('第'+str(currentPage)+'页,第'+str(i)+'条数据')   
                print('************** 数据保存成功 **************')
                #提交数据
                conn.commit()
                #关闭连接
                cursor.close() 
            except Exception as e:
                print(e)
                print('第'+str(currentPage)+'页,第'+str(i)+'条数据')    
                print('*************!!!! 保存失败!!!! **************')  
    复制代码

     04 数据分析

      如果说抓取数据是数据分析的第1步,那么数据清洗就是数据分析的第2步,至于为什么要进行数据清洗呢?如何进行数据清洗呢?本文就不具体描述了,下面具体对我们抓取的天猫商城iphoneX的销售数据进行分析。

      从销售数据可以看出,网络爬虫抓取了‘type#网络类型’,‘color#机身颜色’,‘rom #存储容量’,‘source #来源购买途径’,‘discuss #评论’,‘time #评论日期六类数据,当然还可以抓取更多的数据。这里我们主要是对颜色color和内存rom进行分析,下面利用SQl语句和Pandas库对数据进行基本的分析。

    用 SQL 语句分析IphoneX(按颜色)销售比例

      既然销售数据都保存在Mysql数据库中,那么我们不妨先用 SQL 语句做一下统计分析,本节将对iphoneX的销售量做一个销售比例统计分析。我们要统计的是某一个颜色的销售数量占整个销售数量的百分比,这里需要统计和计算如下3类数据。

    • 某一个颜色的iphoneX销售数量
    • iphoneX销售总数量

    第1类数据和第2类数据的差值(百分比)  

    用 Pandas 和 Matplotlib 分析对胸罩销售比例进行可视化分析

      接下来将使用 Pandas 完成与前面相同的数据分析,并使用 Matplotlib 将分析结果以图形化方式展现出来。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    # 打开iphoneX数据库
    #数据分析        
    from pandas import *
    from matplotlib.pyplot import *
    import mysql.connector
    import matplotlib
    import matplotlib.pyplot as plt
     
    conn = mysql.connector.connect(
                    user='root',
                    password='111111',
                    host='127.0.0.1',
                    port=3306,
                    database='pachong'
                )
    cur=conn.cursor()
     # 对color进行分组,并统计每一组的记录数
    # 对color进行分组,并统计每一组的记录数
    try:
        cur.execute("select count(*) from iphoneX;")
        alldata = cur.fetchall()
        #color统计
        cur.execute("select count(*) from iphoneX where color='银色';")
        y_color= cur.fetchall()[0]
        cur.execute("select count(*) from iphoneX where color='深空灰色';")
        h_color= cur.fetchall()[0]
        #rom统计
        cur.execute("select count(*) from iphoneX where rom='64GB';")
        rom64 = cur.fetchall()[0]
        cur.execute("select count(*) from iphoneX where rom='256GB';")
        rom256 = cur.fetchall()[0]
    except:
        print("Select is failed")
    # 数据可视化
    # 饼图要显示的文本
    labels1 = [u'y_color',u'h_color']
    labels2 = [u'64_rom',u'256_rom']
    # 用饼图绘制销售比例
    X1=[y_color,h_color] 
    X2=[rom64,rom256]
    fig = plt.figure()
    #解决不能显示中文的方法
    plt.pie(X1,labels=labels1,autopct='%.2f%%'#画饼图(数据,数据对应的标签,百分数保留两位小数点)
    zhfont1 = matplotlib.font_manager.FontProperties(fname='C:WindowsFontssimsun.ttc')
    plt.title("颜色比例图",fontproperties=zhfont1)
    plt.show()
    plt.pie(X2,labels=labels2,autopct='%.2f%%'#画饼图(数据,数据对应的标签,百分数保留两位小数点)
    zhfont1 = matplotlib.font_manager.FontProperties(fname='C:WindowsFontssimsun.ttc')
    plt.title("内存比例图",fontproperties=zhfont1)
    plt.show()

             

    从上图的分析结果可以看出,iphoneX的“深空灰色”销售比例都很大,同时买256GB内存的要比64GB内存的比例大,基本上和我个人的判断差不多。今天就介绍到这里了,时间有限,后期会不断更新,大家也可以爬取不同商品的不同信息,进行更加具体的分析。

    每天学习一点点 编程PDF电子书、视频教程免费下载:
    http://www.shitanlife.com/code

  • 相关阅读:
    java中的自动拆装箱详解
    Information:java: javacTask: 源发行版 8 需要目标发行版 1.8
    2019 安易迅java面试笔试题 (含面试题解析)
    2019 农信互联java面试笔试题 (含面试题解析)
    2019 博盾习言java面试笔试题 (含面试题解析)
    2019 蓝鲸人java面试笔试题 (含面试题解析)
    2019 上海轻轻java面试笔试题 (含面试题解析)
    2019 苏州朗动java面试笔试题 (含面试题解析)
    2019 医渡云java面试笔试题 (含面试题解析)
    2019 海看java面试笔试题 (含面试题解析)
  • 原文地址:https://www.cnblogs.com/scode2/p/8809038.html
Copyright © 2011-2022 走看看