Python网络爬虫实战:根据天猫胸罩销售数据分析中国女性胸部大小分布

本文实现一个很是有趣的项目,这个项目是关于胸罩销售数据分析的。是网络爬虫和数据分析的综合应用项目。本项目会从天猫抓取胸罩销售数据,并将这些数据保存到SQLite数据库中,而后对数据进行清洗,最后经过SQL语句、Pandas和Matplotlib对数据进行数据可视化分析。咱们从分析结果中能够得出不少有的结果,例如,中国女性胸部标准尺寸是多少;胸罩上胸围的销售比例;哪一个颜色的胸罩最受女性欢迎。sql

1. 项目效果展现

本项目涉及到网络技术、网络爬虫技术、数据库技术、数据分析技术、数据可视化技术。首先应该运行tmallbra.py脚本文件从天猫抓取胸罩销售数据,并将这些数据保存到SQLite数据库中。接下来能够执行analyze目录中的相应Python脚本文件进行可视化数据分析。下面是一些分析结果展现。数据库

image.png

图1:ABCD罩杯胸罩销售比例json

image.png

图2:胸罩销售比例(罩杯和上胸围综合指标)浏览器

image.png

图3:胸罩销售比例(按颜色分析)31网络

image.png

图4:罩杯和下胸围分布直方图并发

其实Google和淘宝也给出了相似的分析结果。Google曾给出了一幅世界女性胸部尺寸分布地图 ,从地图中能够明显看出中国大部分地区呈现绿色(表示平均胸部尺寸为A罩杯),少部分地区呈现蓝色(表示平均胸部尺寸为B罩杯),这也基本验证了图2所示的统计结果:中国大部分女性胸部尺寸是75B和75A。app

再看一下淘宝给出的胸罩(按罩杯和上胸围统计)销售比例柱状图。异步

image.png

图5:淘宝胸罩销售比例柱状图(按罩杯和上胸围统计)函数

从淘宝给出的数据能够看出,销售最好的胸罩尺寸是75B,这个统计结果虽然销售比例不一样(取的样本不一样而致使的),但按销售数据排行,这个分析结果与本项目的统计结果(图2)基本吻合。工具

2. 天猫胸罩销售数据分析

这里的销售数据其实就是评论数据。用户购买一件商品并发了评论,就会记录销售数据。分析销售数据的第一步就是要搞明白数据是怎么跑到客户端浏览器上的。一般来说,浏览器从服务端获取数据有两种方式:同步和异步。同步就是数据随HTML代码一同发送到客户端,不过如今的大型网站不多有用同步方式传输数据了。异步方式是HTML代码与数据分别发送到客户端,数据通常是JSON格式,经过AJAX技术获取,而后再使用JS将获取到的数据显示在HTML中的元素上。不过有时会加一些反爬虫技术,或处于其余目的,异步数据可能并非纯的JSON格式,例如,有多是一段JavaScript代码,或在JSON格式数据中加一些其余的内容。不过这些基本都没用,加的内容确定是有规律的,不然本身的程序都没法读了。

如今进到天猫商城官网https://www.tmall.com,在搜索框输入“胸罩”,点击“搜索”按钮进行搜索。随便找一个销售胸罩的店铺点进去。而后在页面的右键菜单中点击“检查”菜单项,打开调试窗口,切换到“Network”标签页。接下来查看商品的评论,会在“Network”标签页显示评论信息要访问的Url。在上方的搜索框输入“list_detail”,会列出全部已“list_detail”做为前缀的Url。这些Url就是用AJAX异步获取的评论数据。点击某个Url,会在右侧显示如图6所示的数据,很明显,这些数据与JSON很是像,不过加了一些前缀以及其余信息,估计是要知足一些特殊须要。

image.png

图6:天猫评论数据

在返回的评论数据中,rateList就是咱们须要的信息,rateList列表中一共是20个对象,包含了20条评论数据,也就是说,经过这个Url,每次返回了20条评论数据。

在Url中还有两个HTTP GET请求字段对咱们有用。

• itemId:当前商品的ID,经过这个字段,能够得到指定商品的评论数
据(不光是胸罩)。
• currentPage:当前的页码,从1开始。经过这个字段,能够得到更多的评论数据。

3.抓取天猫胸罩销售数据

既然对天猫胸罩的评论数据的来源已经很是清楚了,本节就抓取这些数据。在tmallbra.py脚本文件中有一个核心函数,用于抓取指定商品的某一页评论数据。

def getRateDetail(itemId,currentPage):
    # Url最后的callback字段是用于天猫网站内部回调的,和咱们不要紧,不过这个字段的值关系到
    # 返回数据的前缀,咱们能够利用这个值去截取返回数据
    url = 'https://rate.tmall.com/list_detail_rate.htm?itemId=' + str(itemId) + 
'&spuId=837695373&sellerId=3075989694&order=3&currentPage=' + str(currentPage) + 
'&append=0... ...&callback=jsonp1278'
    r = http.request('GET',url,headers = headers)
    # 返回数据时GB18030编码,因此要用这个编码格式进行解码
    c = r.data.decode('GB18030')
    # 下面的代码将返回的评论数据转换为JSON格式
    c = c.replace('jsonp1278(','')
    c = c.replace(')','')
    c = c.replace('false','"false"')
    c = c.replace('true','"true"')
    # 将JSON格式的评论数据转换为字典对象
    tmalljson = json.loads(c)
    return tmalljson

4. 抓取胸罩商品列表

应用让爬虫自动选取胸罩商品,而不是咱们一个一个挑。因此能够利用以下的天猫商城的搜索页面Url进行搜索,按销量从大到小排列。

https://list.tmall.com/search_product.htm... ...

这个Url不须要传递任何参数,本项目只取第一个商品页的全部商品。在tmallbra.py脚本文件中有一个而核心函数getProductIdList,用于返回第一个商品页的全部商品ID(以列表形式返回)。

def getProductIdList():
    url = 'https://list.tmall.com/search_product.htm... ...'
    r = http.request('GET', url,headers = headers)
    c = r.data.decode('GB18030')
    soup = BeautifulSoup(c,'lxml')
    linkList = []
    idList = []
    # 用Beautiful Soup提取商品页面中全部的商品ID
    tags = soup.find_all(href=re.compile('detail.tmall.com/item.htm'))
    for tag in tags:
        linkList.append(tag['href'])
    linkList = list(set(linkList))
    for link in linkList:
        aList = link.split('&')
        # //detail.tmall.com/item.htm?id=562173686340
        # 将商品ID添加到列表中
        idList.append(aList[0].replace('//detail.tmall.com/item.htm?id=',''))
    return idList

4.将抓取的销售数据保存到SQLite数据库中

剩下的工做就很简单了,只须要对商品ID列表迭代,而后对每个商品的评论数据进行抓取,天猫每一个商品最多能够得到99页评论,最大评论页数能够经过getLastPage函数得到。

def getLastPage(itemId):
    tmalljson = getRateDetail(itemId,1)
    return tmalljson['rateDetail']['paginator']['lastPage']

下面的代码会抓取商品搜索第一页的全部胸罩商品的评论数据,并将这些数据保存到SQLite数据库中。

# 对商品ID进行迭代
while initial < len(productIdList):
    try:
        itemId = productIdList[initial]
        print('----------',itemId,'------------')
        maxnum = getLastPage(itemId)
        num = 1
        while num <= maxnum:
            try:
                # 抓取某个商品的某页评论数据
                tmalljson = getRateDetail(itemId, num)
                rateList = tmalljson['rateDetail']['rateList']
                n = 0
                while n < len(rateList):
                    # 颜色分类:H007浅蓝色加粉色;尺码:32/70A
                    colorSize = rateList[n]['auctionSku']
                    m = re.split('[:;]',colorSize)
                    rateContent = rateList[n]['rateContent']
                    color = m[1]
                    size = m[3]
                    dtime = rateList[n]['rateDate']
                    # 将抓取的数据保存到SQLite数据库中
                    cursor.execute('''insert into t_sales(color,size,source,discuss,time) 
                                    values('%s','%s','%s','%s','%s') ''' % (color,size,'天猫',rateContent,dtime))
                    conn.commit()
                    n += 1
                    print(color)
                print(num)
                num += 1
            except Exception as e:
                continue        
        initial += 1
    except Exception as e:
        print(e)

5. 数据清洗

若是读者使用前面介绍的方法从天猫和京东抓取了胸罩销售数据,如今咱们已经有了一个SQLite数据库,里面有一个t_sales表,保存了全部抓取的数据,如图7所示。

image.png

图7:保存到数据库中的胸罩销售数据

从销售数据能够看出,网络爬虫抓取了颜色(color)、尺寸(size)、来源(source)、评论(discuss)和时间(time)五类数据。固然还能够抓取更多的数据,这里只为了演示数据分析的方法,因此并无抓取那么多的数据。

不过这五类数据有些不规范,本项目值考虑color和size,因此先要对这两类数据进行清洗。因为每一个店铺,每一个商品的颜色叫法可能不一样,因此须要将这些颜色值统一一下。例如,全部包含“黑”的颜色值均可以认为是黑色。因此能够新创建一个color1字段(尽可能不要修改原始数据),将清洗后的颜色值保存到color1字段中。而后可使用下面的SQL语句对颜色值进行清洗。

update t_sales  set color1 = '黑色'  where color like '%黑%' ;
update t_sales  set color1 = '绿色'  where color like '%绿%' ;
update t_sales  set color1 = '红色'  where color like '%红%' ;
update t_sales  set color1 = '白色'  where color like '%白%' ;
update t_sales  set color1 = '蓝色'  where color like '%蓝%' ;
update t_sales  set color1 = '粉色'  where color like '%粉%'  and color1 is null ;
update t_sales  set color1 = '青色'  where color like '%青%' ;
update t_sales  set color1 = '卡其色'  where color like '%卡其%' ;
update t_sales  set color1 = '紫色'  where color like '%紫%' ;
update t_sales  set color1 = '肤色'  where color like '%肤%' ;
update t_sales  set color1 = '水晶虾'  where color like '%水晶虾%' ;
update t_sales  set color1 = '玫瑰色'  where color like '%玫瑰%' ;
update t_sales  set color1 = '银灰'  where color like '%银灰%' ;

胸罩尺寸清洗的方式与胸罩颜色相似,你们能够本身经过SQL语句去完成。

清洗完的结果如图8所示。

image.png

图8:清洗后的数据

6. 用SQL语句分析胸罩(按罩杯尺寸)的销售比例

既然销售数据都保存在SQLite数据库中,那么咱们不妨先用SQL语句作一下统计分析。本节将对胸罩按罩杯的销售量作一个销售比例统计分析。因为抓取的数据没有超过D罩杯的,因此作数据分析时就不考虑D以上罩杯的胸罩销售数据了。这里只考虑A、B、C和D罩杯胸罩的销售数据。

本节要统计的是某一个尺寸的胸罩销售数量占整个销售数量的百分比,这里须要统计和计算以下3类数据。

• 某一个尺寸的胸罩销售数量。

• 胸罩销售总数量

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

这3类数据彻底能够用一条SQL语句搞定,为了同时搞定A、B、C和D罩杯的销售比例,能够用4条相似的SQL语句,中间用union all链接。

select 'A' as 罩杯,printf("%.2f%%",(100.0 * count(*)/ (select count(*) from t_sales  where size1 is not null)))  as 比例, count(*) as 销量 from t_sales where size1='A'
union all
select 'B',printf("%.2f%%",(100.0 * count(*)/ (select count(*) from t_sales  where size1 is not null))) , count(*) as c from t_sales where size1='B'
union all
select 'C',printf("%0.2f%%",(100.0 * count(*)/ (select count(*) from t_sales  where size1 is not null))) , count(*) as c from t_sales where size1='C'
union all
select 'D',printf("%.2f%%",(100.0 * count(*)/ (select count(*) from t_sales  where size1 is not null))) , count(*) as c from t_sales where size1='D'
order by 销量 desc

上面的SQL语句不只加入了销售比例,还加入了销售数量,而且按销量降序排列。这些SQL语句须要考虑size1字段空值的状况,由于抓取的少部分销售记录并无罩杯尺寸数据。执行上面的SQL语句后,会输出如图9所示的查询结果。

image.png

图9:用SQL语句统计胸罩(按罩杯尺寸)销售比例

其余的销售数据的分析相似。

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

既然Python提供了这么好的Pandas和Matplotlib,那么就能够彻底不使用SQL语句进行数据分析了。能够100%使用Python代码搞定一切。

本节将使用Pandas完成与上一节相同的数据分析,并使用Matplotlib将分析结果以图形化方式展示出来。

Pandas在前面的章节已经讲过了,这里再也不深刻介绍。本次分析主要使用了groupby方法按罩杯(size1)分组,而后使用count方法统计组内数量,最后使用insert方法添加了一个“比例”字段。

from pandas import *
from matplotlib.pyplot import *
import sqlite3
import sqlalchemy
# 打开bra.sqlite数据库
engine = sqlalchemy.create_engine('sqlite:///bra.sqlite')
rcParams['font.sans-serif'] = ['SimHei']
# 查询t_sales表中全部的数据
sales = read_sql('select source,size1 from t_sales',engine)
# 对size1进行分组,并统计每一组的记录数
size1Count = sales.groupby('size1')['size1'].count()
print(size1Count)
# 计算总销售数量
size1Total = size1Count.sum()
print(size1Total)
print(type(size1Count))
# 将Series转换为DataFrame
size1 = size1Count.to_frame(name='销量')
print(size1)
# 格式化浮点数
options.display.float_format = '{:,.2f}%'.format
# 插入新的“比例”列
size1.insert(0,'比例', 100 * size1Count / size1Total)
print(size1)
# 将索引名改成“罩杯”
size1.index.names=['罩杯']
print(size1)

# 数据可视化
print(size1['销量'])
# 饼图要显示的文本
labels = ['A罩杯','B罩杯','C罩杯','D罩杯']
# 用饼图绘制销售比例
size1['销量'].plot(kind='pie',labels = labels, autopct='%.2f%%')
# 设置长宽相同
axis('equal')
legend()
show()

运行程序,会看到在窗口上绘制了如图10所示的胸罩销售比例。用Pandas分析获得的数据与使用SQL分析获得的数据彻底相同。

image.png

图10:胸罩销售比例(按罩杯尺寸)

其余分析也可使用Pandas,可视化使用Matplotlib。这两个工具真是个强大的东西。祝你们学习愉快

image.png

相关文章
相关标签/搜索