【Python】动手分析天猫内衣售卖数据,得到你想知道的信息!

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

大家好,希望各位能怀着正直、严谨、专业的心态观看这篇文章。ヾ(๑╹◡╹)ノ"

接下来我们尝试用 Python 抓取天猫内衣销售数据,并分析得到中国女性普遍的罩杯数据、最受欢迎的内衣颜色是什么、评论的关键字。

希望看完之后你能替你女朋友买上一件心怡的内衣。

我们先看看分析得到的成果是怎样的?(讲的很详细,推荐跟着敲一遍)

d75002210cbf34fcc503154f6e28beb90eabe08d

(买个内衣这么开心)

图片看不清楚的话,可以把图片单独拉到另一个窗口。

这里是分析了一万条数据得出的结论,可能会有误差,但是还是希望单身的你们能找到 0.06%那一批妹纸。

下面我会详细介绍怎么抓取天猫内衣销售数据,存储、分析、展示。

 ●  研究天猫网站
 ●  抓取天猫评论数据
 ●  存储、分析数据
 ●  可视化

研究天猫网站

我们随意进入一个商品的购买界面(能看到评论的那个界面),F12 开发者模式 -- Network 栏 -- 刷新下界面 -- 在如图的位置搜索 list_ 会看到一个 list_detail_rate.htm?itemId= ....

如下图:【单击】这个url 能看到返回的是一个 Json 数据 ,检查一下你会发现这串 Json 就是商品的评论数据 ['rateDetail']['rateList'] 

79676afb60a47441b7ee544b9317001de38ab977

【双击】这个url 你会得到一个新界面,如图 

fc5d5ef4ad2ee445e7a46b6d962828852b421587

看一下这个信息

2e8af5856da8437c6eaaca681e7d21078d9575fe

这里的路径 就是获取评论数据的 url了。这个 URL 有很多参数你可以分析一下每个值都是干嘛的。

itemId 对应的是商品id, sellerId 对应的是店铺id,currentPage 是当前页。这里 sellerId 可以填任意值,不影响数据的获取。

抓取天猫评论数据

写一个抓取天猫评论数据的方法。getCommentDetail


# 获取商品评论数据
def getCommentDetail(itemId,currentPage):
url = 'https://rate.tmall.com/list_detail_rate.htm?itemId=' + str(
itemId) + '&sellerId=2451699564&order=3&currentPage=' + str(currentPage) + '&append=0callback=jsonp336'
# itemId 产品id ; sellerId 店铺id 字段必须有值,但随意值就行 html = common.getUrlContent(url) # 获取网页信息 # 删掉返回的多余信息
html = html.replace('false','"false"')
html = html.replace('jsonp128(','') #需要确定是不是 jsonp128 html = html.replace(')','') html = html.replace('true','"true"') # 将string 转换为字典对象
return tmalljson
tmalljson = json.loads(html)

这里需要注意的是 jsonp128 这个值需要你自己看一下,你那边跟我这个应该是不同的。

还有几十 common 这我自己封装的一个工具类,主要就是上一篇博客里写的一些功能,想requests pymysql 模块的功能。在文章最后我会贴出来。

在上面的方法里有两个变量,itemIdcurrentPage 这两个值我们动态来控制,所以我们需要获得 一批 商品id号评论的最大页数 用来遍历。

写个获取商品评论最大页数的方法 getLastPage


# 获取商品评论最大页数
def getLastPage(itemId):
tmalljson = getCommentDetail(itemId,1)
return tmalljson['rateDetail']['paginator']['lastPage'] #最大页数

那现在怎么获取 产品的id 列表呢? 我们可以在天猫中搜索商品关键字 用开发者模式观察

524a5ff52aefd421be934233f90d2547c6434d49

这里观察一下这个页面的元素分布,很容易就发现了 商品的id 信息,当然你可以想办法确认一下。 7a796bc38a0a659bacba528028368cb3e6ec6361

现在就写个 获取商品id 的方法 getProductIdList


# 获取商品id
def getProductIdList():
url = 'https://list.tmall.com/search_product.htm?q=内衣' # q参数 是查询的关键字
html = common.getUrlContent(url) # 获取网页信息
# 用Beautiful Soup提取商品页面中所有的商品ID
soup = BeautifulSoup(html,'html.parser') idList = []
for product in productList:
productList = soup.find_all('div', {'class': 'product'}) idList.append(product['data-id'])
return idList

现在所有的基本要求都有了,是时候把他们组合起来。

在 main 方法中写剩下的组装部分


if __name__ == '__main__':
productIdList = getProductIdList() #获取商品id
initial = 0
while initial < len(productIdList) - 30: # 总共有60个商品,我只取了前30个
try: itemId = productIdList[initial]
maxPage = getLastPage(itemId) #获取商品评论最大页数
print('----------', itemId, '------------') num = 1
try:
while num <= maxPage and num < 20: #每个商品的评论我最多取20 页,每页有20条评论,也就是每个商品最多只取 400 个评论 # 抓取某个商品的某页评论数据
while (n < len(rateList)):
tmalljson = getCommentDetail(itemId, num) rateList = tmalljson['rateDetail']['rateList'] commentList = [] n = 0 comment = [] # 商品描述
dtime = rateList[n]['rateDate']
colorSize = rateList[n]['auctionSku'] m = re.split('[:;]', colorSize) rateContent = rateList[n]['rateContent'] comment.append(m[1]) comment.append(m[3])
sql = "insert into bras(bra_id, bra_color, bra_size, resource, comment, comment_time) value(null, %s, %s, %s, %s, %s)"
comment.append('天猫') comment.append(rateContent) comment.append(dtime) commentList.append(comment) n += 1 print(num) common.patchInsertData(sql, commentList) # mysql操作的批量插入
print(e)
num += 1 except Exception as e: num += 1 print(e) continue initial += 1
except Exception as e:

所有的代码就这样完成了,我现在把 common.py 的代码,还有 tmallbra.py 的代码都贴出来


# -*- coding:utf-8 -*-
# Author: zww
import time
import requests import random
import http.client
import socket import pymysql import csv
def getUrlContent(self, url, data=None):
# 封装requests class Common(object): header = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'cache-control': 'max-age=0'
'user-agent': "User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36", } # request 的请求头 timeout = random.choice(range(80, 180)) while True: try:
except socket.error as e:
rep = requests.get(url, headers=header, timeout=timeout) # 请求url地址,获得返回 response 信息 # rep.encoding = 'utf-8' break except socket.timeout as e: # 以下都是异常处理 print('3:', e) time.sleep(random.choice(range(8, 15))) print('4:', e) time.sleep(random.choice(range(20, 60)))
with open(url, 'a', errors='ignore', newline='') as f:
except http.client.BadStatusLine as e: print('5:', e) time.sleep(random.choice(range(30, 80))) except http.client.IncompleteRead as e: print('6:', e) time.sleep(random.choice(range(5, 15))) print('request success') return rep.text # 返回的 Html 全文 def writeData(self, data, url): f_csv = csv.writer(f)
# 关闭数据库连接
f_csv.writerows(data) print('write_csv success') def queryData(self, sql): db = pymysql.connect("localhost", "zww", "960128", "test") cursor = db.cursor() results = [] try: cursor.execute(sql) #执行查询语句 results = cursor.fetchall() except Exception as e: print('查询时发生异常' + e) # 如果发生错误则回滚 db.rollback() db.close()
# sql = "INSERT INTO WEATHER(w_id, w_date, w_detail, w_temperature) VALUES (null, '%s','%s','%s')" % (data[0], data[1], data[2])
return results print('insert data success') def insertData(self, sql): # 打开数据库连接 db = pymysql.connect("localhost", "zww", "000000", "zwwdb") # 使用 cursor() 方法创建一个游标对象 cursor cursor = db.cursor() try: cursor.execute(sql) #单条数据写入 # 提交到数据库执行 db.commit() except Exception as e: print('插入时发生异常' + e) # 如果发生错误则回滚 db.rollback()
# cursor.executemany('insert into WEATHER(w_id, w_date, w_detail, w_temperature_low, w_temperature_high) value(null, %s,%s,%s,%s)',datas)
# 关闭数据库连接 db.close() print('insert data success') def patchInsertData(self, sql, datas): # 打开数据库连接 db = pymysql.connect("localhost", "zww", "960128", "test") # 使用 cursor() 方法创建一个游标对象 cursor cursor = db.cursor() try: # 批量插入数据 cursor.executemany(sql, datas) # 提交到数据库执行 db.commit() except Exception as e: print('插入时发生异常' + e)
print('insert data success')
# 如果发生错误则回滚 db.rollback() # 关闭数据库连接
db.close()

上面需要注意,数据库的配置


# -*- coding:utf-8 -*-
# Author: zww
from Include.commons.common import Common
from bs4 import BeautifulSoup import json import re
def getProductIdList():
import pymysql common = Common() # 获取商品id
url = 'https://list.tmall.com/search_product.htm?q=内衣' # q参数 是查询的关键字,这要改变一下查询值,就可以抓取任意你想知道的数据
html = common.getUrlContent(url) # 获取网页信息 soup = BeautifulSoup(html,'html.parser') idList = [] # 用Beautiful Soup提取商品页面中所有的商品ID
# 获取商品评论数据
productList = soup.find_all('div', {'class': 'product'}) for product in productList: idList.append(product['data-id']) return idList def getCommentDetail(itemId,currentPage):
# itemId 产品id ; sellerId 店铺id 字段必须有值,但随意值就行
url = 'https://rate.tmall.com/list_detail_rate.htm?itemId=' + str( itemId) + '&sellerId=2451699564&order=3&currentPage=' + str(currentPage) + '&append=0callback=jsonp336' html = common.getUrlContent(url) # 获取网页信息 # 删掉返回的多余信息
def getLastPage(itemId):
html = html.replace('jsonp128(','') #需要确定是不是 jsonp128 html = html.replace(')','') html = html.replace('false','"false"') html = html.replace('true','"true"') # 将string 转换为字典对象 tmalljson = json.loads(html) return tmalljson # 获取商品评论最大页数 tmalljson = getCommentDetail(itemId,1)
print('----------', itemId, '------------')
return tmalljson['rateDetail']['paginator']['lastPage'] #最大页数 if __name__ == '__main__': productIdList = getProductIdList() #获取商品id initial = 0 while initial < len(productIdList) - 30: # 总共有60个商品,我只取了前30个 try: itemId = productIdList[initial] maxPage = getLastPage(itemId) #获取商品评论最大页数 num = 1
rateContent = rateList[n]['rateContent']
while num <= maxPage and num < 20: #每个商品的评论我最多取20 页,每页有20条评论,也就是每个商品最多只取 400 个评论 try: # 抓取某个商品的某页评论数据 tmalljson = getCommentDetail(itemId, num) rateList = tmalljson['rateDetail']['rateList'] commentList = [] n = 0 while (n < len(rateList)): comment = [] # 商品描述 colorSize = rateList[n]['auctionSku'] m = re.split('[:;]', colorSize) dtime = rateList[n]['rateDate']
num += 1
comment.append(m[1]) comment.append(m[3]) comment.append('天猫') comment.append(rateContent) comment.append(dtime) commentList.append(comment) n += 1 print(num) sql = "insert into bras(bra_id, bra_color, bra_size, resource, comment, comment_time) value(null, %s, %s, %s, %s, %s)" common.patchInsertData(sql, commentList) # mysql操作的批量插入 num += 1 except Exception as e: print(e) continue
print(e)
initial += 1
except Exception as e:

存储、分析数据

所有的代码都有了,就差数据库的建立了。我这里用的是 MySql 数据库。


CREATE TABLE `bra` (
`bra_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id' ,
`bra_color` varchar(25) NULL COMMENT '颜色' ,
`resource` varchar(25) NULL COMMENT '数据来源' ,
`bra_size` varchar(25) NULL COMMENT '罩杯' ,
`comment_time` datetime NULL COMMENT '评论时间' ,
`comment` varchar(500) CHARACTER SET utf8mb4 DEFAULT NULL COMMENT '评论' , PRIMARY KEY (`bra_id`)
;
) character set utf8

这里有两个地方需要注意, comment 评论字段需要设置编码格式为 utf8mb4 ,因为可能有表情文字。还有需要设置为 utf8 编码,不然存不了中文。

建好了表,就可以完整执行代码了。(这里的执行可能需要点时间,可以做成多线程的方式)。看一下执行完之后,数据库有没有数据。

be7fb0ab6ad9a8523f597a0ce0c5c2f4054a173a

数据是有了,但是有些我们多余的文字描述,我们可以稍微整理一下。

update bra set bra_color = REPLACE(bra_color,'2B6521-无钢圈4-','');
update bra set bra_color = REPLACE(bra_color,'-1','');
update bra set bra_size = substr(bra_size,1,3);
update bra set bra_color = REPLACE(bra_color,'5','');

这里需要根据自己实际情况来修改。如果数据整理的差不多了,我们可以分析一下数据库的信息。


select 'A罩杯' as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 100, 2) , "%") as 比例, COUNT(*) as 销量 from bra where bra_size like '%A'
union all select 'B罩杯' as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 100, 2) , "%") as 比例, COUNT(*) as 销量 from bra where bra_size like '%B'
union all select 'C罩杯' as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 100, 2) , "%") as 比例, COUNT(*) as 销量 from bra where bra_size like '%C'
union all select 'E罩杯' as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 100, 2) , "%") as 比例, COUNT(*) as 销量 from bra where bra_size like '%E'
union all select 'D罩杯' as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 100, 2) , "%") as 比例, COUNT(*) as 销量 from bra where bra_size like '%D' union all select 'F罩杯' as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 100, 2) , "%") as 比例, COUNT(*) as 销量 from bra where bra_size like '%F'
order by 销量 desc;
union all select 'G罩杯' as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 100, 2) , "%") as 比例, COUNT(*) as 销量 from bra where bra_size like '%G'
union all select 'H罩杯' as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 100, 2) , "%") as 比例, COUNT(*) as 销量 from bra where bra_size like '%H'

9aeca4a58227c3c92c473b9f5225b5f6e963a093

(想知道是哪6位小姐姐买的 G (~ ̄▽ ̄)~ )

数据可视化

数据的展示,我用了是 mycharts 模块,如果不了解的可以去 学习一下 http://pyecharts.org/#/zh-cn/prepare

这里我就不细说了,直接贴代码看


# encoding: utf-8
# author zww
from pyecharts import Pie
from Include.commons.common import Common
if __name__ == '__main__':
results = common.queryData("""select count(*) from bra where bra_size like '%A'
common = Common()
union all select count(*) from bra where bra_size like '%B'
union all select count(*) from bra where bra_size like '%C'
union all select count(*) from bra where bra_size like '%E'
union all select count(*) from bra where bra_size like '%D' union all select count(*) from bra where bra_size like '%F'
attr = ["A罩杯", 'G罩杯', "B罩杯", "C罩杯", "D罩杯", "E罩杯", "F罩杯"]
union all select count(*) from bra where bra_size like '%G'""") # 获取每个罩杯数量 v1 = [results[0][0], results[6][0], results[1][0], results[2][0], results[3][0], results[4][0], results[5][0]]
results = common.queryData("""select count(*) from bra where bra_color like '%肤%'
pie = Pie("内衣罩杯", width=1300, height=620) pie.add("", attr, v1, is_label_show=True) pie.render('size.html') print('success') union all select count(*) from bra where bra_color like '%灰%'
union all select count(*) from bra where bra_color like '%红%'
union all select count(*) from bra where bra_color like '%黑%' union all select count(*) from bra where bra_color like '%蓝%' union all select count(*) from bra where bra_color like '%粉%' union all select count(*) from bra where bra_color like '%紫%'
union all select count(*) from bra where bra_color like '%黄%' """) # 获取每个罩杯数量
union all select count(*) from bra where bra_color like '%绿%' union all select count(*) from bra where bra_color like '%白%' union all select count(*) from bra where bra_color like '%褐%' attr = ["肤色", '灰色', "黑色", "蓝色", "粉色", "红色", "紫色", '绿色', "白色", "褐色", "黄色"]
print('success')
v1 = [results[0][0], results[1][0], results[2][0], results[3][0], results[4][0], results[5][0], results[6][0], results[7][0], results[8][0], results[9][0], results[10][0]] pieColor = Pie("内衣颜色", width=1300, height=620) pieColor.add("", attr, v1, is_label_show=True)
pieColor.render('color.html')

这一章就到这里了,该知道的你也知道了,不该知道的你也知道了。

代码全部存放在 GitHub 上 https://github.com/zwwjava/python_capture



原文发布时间为:2018-10-22
本文作者:旺旺笔记
本文来自云栖社区合作伙伴“ Python爱好者社区”,了解相关信息可以关注“ Python爱好者社区”。
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
30天前
|
存储 分布式计算 大数据
基于Python大数据的的电商用户行为分析系统
本系统基于Django、Scrapy与Hadoop技术,构建电商用户行为分析平台。通过爬取与处理海量用户数据,实现行为追踪、偏好分析与个性化推荐,助力企业提升营销精准度与用户体验,推动电商智能化发展。
|
1月前
|
数据采集 Web App开发 数据可视化
Python零基础爬取东方财富网股票行情数据指南
东方财富网数据稳定、反爬宽松,适合爬虫入门。本文详解使用Python抓取股票行情数据,涵盖请求发送、HTML解析、动态加载处理、代理IP切换及数据可视化,助你快速掌握金融数据爬取技能。
1033 1
|
1月前
|
Java 数据挖掘 数据处理
(Pandas)Python做数据处理必选框架之一!(一):介绍Pandas中的两个数据结构;刨析Series:如何访问数据;数据去重、取众数、总和、标准差、方差、平均值等;判断缺失值、获取索引...
Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。 Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。 Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。 Pandas 主要引入了两种新的数据结构:Series 和 DataFrame。
349 0
|
1月前
|
JSON 算法 API
Python采集淘宝商品评论API接口及JSON数据返回全程指南
Python采集淘宝商品评论API接口及JSON数据返回全程指南
|
1月前
|
JSON API 数据安全/隐私保护
Python采集淘宝拍立淘按图搜索API接口及JSON数据返回全流程指南
通过以上流程,可实现淘宝拍立淘按图搜索的完整调用链路,并获取结构化的JSON商品数据,支撑电商比价、智能推荐等业务场景。
|
29天前
|
机器学习/深度学习 大数据 关系型数据库
基于python大数据的台风灾害分析及预测系统
针对台风灾害预警滞后、精度不足等问题,本研究基于Python与大数据技术,构建多源数据融合的台风预测系统。利用机器学习提升路径与强度预测准确率,结合Django框架实现动态可视化与实时预警,为防灾决策提供科学支持,显著提高应急响应效率,具有重要社会经济价值。
|
30天前
|
机器学习/深度学习 大数据 关系型数据库
基于python大数据的青少年网络使用情况分析及预测系统
本研究基于Python大数据技术,构建青少年网络行为分析系统,旨在破解现有防沉迷模式下用户画像模糊、预警滞后等难题。通过整合多平台亿级数据,运用机器学习实现精准行为预测与实时干预,推动数字治理向“数据驱动”转型,为家庭、学校及政府提供科学决策支持,助力青少年健康上网。
|
数据采集 存储 数据挖掘
Python数据分析:Pandas库的高效数据处理技巧
【10月更文挑战第27天】在数据分析领域,Python的Pandas库因其强大的数据处理能力而备受青睐。本文介绍了Pandas在数据导入、清洗、转换、聚合、时间序列分析和数据合并等方面的高效技巧,帮助数据分析师快速处理复杂数据集,提高工作效率。
346 0
|
机器学习/深度学习 数据采集 数据挖掘
解锁 Python 数据分析新境界:Pandas 与 NumPy 高级技巧深度剖析
Pandas 和 NumPy 是 Python 中不可或缺的数据处理和分析工具。本文通过实际案例深入剖析了 Pandas 的数据清洗、NumPy 的数组运算、结合两者进行数据分析和特征工程,以及 Pandas 的时间序列处理功能。这些高级技巧能够帮助我们更高效、准确地处理和分析数据,为决策提供支持。
276 2

推荐镜像

更多
下一篇
oss云网关配置