本文实现一个非常有趣的项目,这个项目是关于胸罩销售数据分析的。是网络爬虫和数据分析的综合应用项目。本项目会从天猫抓取胸罩销售数据,并将这些数据保存到SQLite数据库中,然后对数据进行清洗,最后通过SQL语句、Pandas和Matplotlib对数据进行数据可视化分析。我们从分析结果中可以得出很多有的结果,例如,中国女性胸部标准尺寸是多少;胸罩上胸围的销售比例;哪个颜色的胸罩最受女性欢迎。
1. 项目效果展示
本项目涉及到网络技术、网络爬虫技术、数据库技术、数据分析技术、数据可视化技术。首先应该运行tmallbra.py脚本文件从天猫抓取胸罩销售数据,并将这些数据保存到SQLite数据库中。接下来可以执行analyze目录中的相应Python脚本文件进行可视化数据分析。下面是一些分析结果展示。

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

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

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

图4:罩杯和下胸围分布直方图
其实Google和淘宝也给出了类似的分析结果。Google曾给出了一幅世界女性胸部尺寸分布地图 ,从地图中可以明显看出中国大部分地区呈现绿色(表示平均胸部尺寸为A罩杯),少部分地区呈现蓝色(表示平均胸部尺寸为B罩杯),这也基本验证了图2所示的统计结果:中国大部分女性胸部尺寸是75B和75A。
再看一下淘宝给出的胸罩(按罩杯和上胸围统计)销售比例柱状图。

图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非常像,不过加了一些前缀以及其他信息,估计是要满足一些特殊需要。

图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¤tPage=' + 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'][
