原创 为了给小女友挑合适罩杯的内衣,我用 Python 爬了淘宝内衣店的数据!

2019-9-24 11:33 1342 13 2 分类: 机器人/ AI 文集: AI


640?wx_fmt=jpeg编辑: 开发者最前线 & 可可| 作者:躲猫猫的猫,原文链接:https://www.cnblogs.com/zhaww/p/9636383.html大家好,希望各位能怀着正直、严谨、专业的心态观看这篇文章。ヾ(๑╹◡╹)ノ"老天真的对我不薄,让我终于有了女友,自从有了女友后,我为了能替女朋友买上一件心怡的内衣接下来我们尝试用 Python 抓取天猫内衣销售数据,并分析得到中国女性普遍的罩杯数据、最受欢迎的内衣颜色是什么、评论的关键字。我们先看看分析得到的成果是怎样的?(讲的很详细,推荐跟着敲一遍)
  640?wx_fmt=png640?wx_fmt=png640?wx_fmt=png(买个内衣这么开心)
图片看不清楚的话,可以把图片单独拉到另一个窗口。这里是分析了一万条数据得出的结论,可能会有误差,但是还是希望单身的你们能找到 0.06% 那一批妹纸。下面我会详细介绍怎么抓取天猫内衣销售数据,存储、分析、展示。
  • 研究天猫网站

  • 抓取天猫评论数据

  • 存储、分析数据

  • 可视化

研究天猫网站我们随意进入一个商品的购买界面(能看到评论的那个界面),F12 开发者模式 -- Network 栏 -- 刷新下界面 -- 在如图的位置搜索 list_ 会看到一个 list_detail_rate.htm?itemId= ….如下图:【单击】这个url 能看到返回的是一个 Json 数据 ,检查一下你会发现这串 Json 就是商品的评论数据 [ rateDetail ][ rateList ]640?wx_fmt=png【双击】这个url 你会得到一个新界面,如图640?wx_fmt=png看一下这个信息640?wx_fmt=png这里的路径 就是获取评论数据的 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¤tPage=  + str(currentPage) +  &append=0callback=jsonp336
    # itemId 产品id ;sellerId 店铺id 字段必须有值,但随意值就行
    html = common.getUrlContent(url)  # 获取网页信息
    # 删掉返回的多余信息
    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
这里需要注意的是 jsonp128 这个值需要你自己看一下,你那边跟我这个应该是不同的。在上面的方法里有两个变量,itemId 和 currentPage 这两个值我们动态来控制,所以我们需要获得 一批 商品id号 和 评论的最大页数 用来遍历。写个获取商品评论最大页数的方法 getLastPage# 获取商品评论最大页数
def getLastPage(itemId):
    tmalljson = getCommentDetail(itemId,1)
    return tmalljson[ rateDetail ][ paginator ][ lastPage ] #最大页数
那现在怎么获取 产品的id 列表呢?我们可以在天猫中搜索商品关键字 用开发者模式观察640?wx_fmt=png这里观察一下这个页面的元素分布,很容易就发现了 商品的id 信息,当然你可以想办法确认一下。640?wx_fmt=png现在就写个 获取商品id 的方法 getProductIdList# 获取商品id
def getProductIdList():
    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
现在所有的基本要求都有了,是时候把他们组合起来。在 main 方法中写剩下的组装部分if __name__ ==  __main__ :
    productIdList = getProductIdList() #获取商品id
    initial = 0
    while initial < len(productIdList) - 30:  # 总共有60个商品,我只取了前30个
        try:
            itemId = productIdList[initial]
            print( ---------- , itemId,  ------------ )
            maxPage = getLastPage(itemId) #获取商品评论最大页数
            num = 1
            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)
                        rateContent = rateList[n][ rateContent ]
                        dtime = rateList[n][ rateDate ]
                        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:
                    num += 1
                    print(e)
                    continue
            initial += 1
        except Exception as e:
            print(e)
所有的代码就这样完成了,我现在把 common.py 的代码,还有 tmallbra.py 的代码都贴出来# -*- coding:utf-8 -*-
# Author: zww
import requests
import time
import random
import socket
import http.client
import pymysql
import csv

# 封装requests
class Common(object):
    def getUrlContent(self, url, data=None):
        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 ,
             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",
             cache-control max-age=0
        }  # request 的请求头
        timeout = random.choice(range(80180))
        while True:
            try:
                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(815)))
            except socket.error as e:
                print( 4: , e)
                time.sleep(random.choice(range(2060)))
            except http.client.BadStatusLine as e:
                print( 5: , e)
                time.sleep(random.choice(range(3080)))
            except http.client.IncompleteRead as e:
                print( 6: , e)
                time.sleep(random.choice(range(515)))
        print( request success )
        return rep.text  # 返回的 Html 全文

    def writeData(self, data, url):
        with open(url,  a , errors= ignore , newline= as f:
            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()
        return results
        print( insert data success )

    def insertData(self, sql):
        # 打开数据库连接
        db = pymysql.connect("localhost""zww""000000""zwwdb")
        # 使用 cursor() 方法创建一个游标对象 cursor
        cursor = db.cursor()

        try:
            # sql = "INSERT INTO WEATHER(w_id, w_date, w_detail, w_temperature) VALUES (null,  %s , %s , %s )" % (data[0], data[1], data[2])
            cursor.execute(sql)    #单条数据写入
            # 提交到数据库执行
            db.commit()
        except Exception as e:
            print( 插入时发生异常  + e)
            # 如果发生错误则回滚
            db.rollback()
        # 关闭数据库连接
        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( insert into WEATHER(w_id, w_date, w_detail, w_temperature_low, w_temperature_high) value(null, %s,%s,%s,%s) ,datas)
            cursor.executemany(sql, datas)

            # 提交到数据库执行
            db.commit()
        except Exception as e:
            print( 插入时发生异常  + e)
            # 如果发生错误则回滚
            db.rollback()
        # 关闭数据库连接
        db.close()
        print( insert data success )
上面需要注意,数据库的配置。# -*- coding:utf-8 -*-
# Author: zww

from Include.commons.common import Common
from bs4 import BeautifulSoup
import json
import re
import pymysql

common = Common()

# 获取商品id
def getProductIdList():
    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):
    url =  https://rate.tmall.com/list_detail_rate.htm?itemId=  + str(
        itemId) +  &sellerId=2451699564&order=3¤tPage=  + str(currentPage) +  &append=0callback=jsonp336
    # itemId 产品id ;sellerId 店铺id 字段必须有值,但随意值就行
    html = common.getUrlContent(url)  # 获取网页信息
    # 删掉返回的多余信息
    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

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

if __name__ ==  __main__ :
    productIdList = getProductIdList() #获取商品id
    initial = 0
    while initial < len(productIdList) - 30:  # 总共有60个商品,我只取了前30个
        try:
            itemId = productIdList[initial]
            print( ---------- , itemId,  ------------ )
            maxPage = getLastPage(itemId) #获取商品评论最大页数
            num = 1
            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)
                        rateContent = rateList[n][ rateContent ]
                        dtime = rateList[n][ rateDate ]
                        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:
                    num += 1
                    print(e)
                    continue
            initial += 1
        except Exception as e:
            print(e)
存储、分析数据所有的代码都有了,就差数据库的建立了。我这里用的是 MySql 数据库。CREATE TABLE `bra` (
`bra_id`  int(11NOT NULL AUTO_INCREMENT COMMENT  id  ,
`bra_color`  varchar(25NULL COMMENT  颜色  ,
`bra_size`  varchar(25NULL COMMENT  罩杯  ,
`resource`  varchar(25NULL COMMENT  数据来源  ,
`comment`  varchar(500CHARACTER SET utf8mb4 DEFAULT NULL COMMENT  评论  ,
`comment_time`  datetime NULL COMMENT  评论时间  ,
PRIMARY KEY (`bra_id`)
character set utf8
;这里有两个地方需要注意, comment 评论字段需要设置编码格式为 utf8mb4  ,因为可能有表情文字。还有表需要设置为 utf8 编码,不然存不了中文。
建好了表,就可以完整执行代码了。(这里的执行可能需要点时间,可以做成多线程的方式)。看一下执行完之后,数据库有没有数据。640?wx_fmt=png数据是有了,但是有些我们多余的文字描述,我们可以稍微整理一下。
update bra set bra_color = REPLACE(bra_color, 2B6521-无钢圈4- , );
update bra set bra_color = REPLACE(bra_color, -1 , );
update bra set bra_color = REPLACE(bra_color, 5 , );
update bra set bra_size = substr(bra_size,1,3);
这里需要根据自己实际情况来修改。如果数据整理的差不多了,我们可以分析一下数据库的信息。select  A罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %A
union all select  B罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %B
union all select  C罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %C
union all select  D罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %D
union all select  E罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %E
union all select  F罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %F
union all select  G罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %G
union all select  H罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %H
order by 销量 desc;
640?wx_fmt=png  (想知道是哪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__ :
    common = Common()
    results = common.queryData("""select count(*) from bra where bra_size like  %A  
            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  %D  
            union all select count(*) from bra where bra_size like  %E  
            union all select count(*) from bra where bra_size like  %F  
            union all select count(*) from bra where bra_size like  %G """)  # 获取每个罩杯数量
    attr = ["A罩杯",  G罩杯 , "B罩杯", "C罩杯", "D罩杯", "E罩杯", "F罩杯"]
    v1 = [results[0][0], results[6][0], results[1][0], results[2][0], results[3][0], results[4][0], results[5][0]]
    pie = Pie("内衣罩杯", width=1300, height=620)
    pie.add("", attr, v1, is_label_show=True)
    pie.render( size.html )
    print( success )

    results = common.queryData("""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  %褐%  
        union all select count(*) from bra where bra_color like  %黄%  """)  # 获取每个罩杯数量
    attr = ["肤色",  灰色 , "黑色", "蓝色", "粉色", "红色", "紫色",  绿色 , "白色", "褐色", "黄色"]
    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 )
    print( success )
这一章就到这里了,该知道的你也知道了,不该知道的你也知道了。哪些人是G杯,哪些妹子是A杯,以后找对象就不用担心这块的了。代码已放到github, 点击文末阅读原文,获取全部源码。


640?wx_fmt=jpeg编辑: 开发者最前线 & 可可| 作者:躲猫猫的猫,原文链接:https://www.cnblogs.com/zhaww/p/9636383.html大家好,希望各位能怀着正直、严谨、专业的心态观看这篇文章。ヾ(๑╹◡╹)ノ"老天真的对我不薄,让我终于有了女友,自从有了女友后,我为了能替女朋友买上一件心怡的内衣接下来我们尝试用 Python 抓取天猫内衣销售数据,并分析得到中国女性普遍的罩杯数据、最受欢迎的内衣颜色是什么、评论的关键字。我们先看看分析得到的成果是怎样的?(讲的很详细,推荐跟着敲一遍)
  640?wx_fmt=png640?wx_fmt=png640?wx_fmt=png(买个内衣这么开心)
图片看不清楚的话,可以把图片单独拉到另一个窗口。这里是分析了一万条数据得出的结论,可能会有误差,但是还是希望单身的你们能找到 0.06% 那一批妹纸。下面我会详细介绍怎么抓取天猫内衣销售数据,存储、分析、展示。
  • 研究天猫网站

  • 抓取天猫评论数据

  • 存储、分析数据

  • 可视化

研究天猫网站我们随意进入一个商品的购买界面(能看到评论的那个界面),F12 开发者模式 -- Network 栏 -- 刷新下界面 -- 在如图的位置搜索 list_ 会看到一个 list_detail_rate.htm?itemId= ….如下图:【单击】这个url 能看到返回的是一个 Json 数据 ,检查一下你会发现这串 Json 就是商品的评论数据 [ rateDetail ][ rateList ]640?wx_fmt=png【双击】这个url 你会得到一个新界面,如图640?wx_fmt=png看一下这个信息640?wx_fmt=png这里的路径 就是获取评论数据的 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¤tPage=  + str(currentPage) +  &append=0callback=jsonp336
    # itemId 产品id ;sellerId 店铺id 字段必须有值,但随意值就行
    html = common.getUrlContent(url)  # 获取网页信息
    # 删掉返回的多余信息
    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
这里需要注意的是 jsonp128 这个值需要你自己看一下,你那边跟我这个应该是不同的。在上面的方法里有两个变量,itemId 和 currentPage 这两个值我们动态来控制,所以我们需要获得 一批 商品id号 和 评论的最大页数 用来遍历。写个获取商品评论最大页数的方法 getLastPage# 获取商品评论最大页数
def getLastPage(itemId):
    tmalljson = getCommentDetail(itemId,1)
    return tmalljson[ rateDetail ][ paginator ][ lastPage ] #最大页数
那现在怎么获取 产品的id 列表呢?我们可以在天猫中搜索商品关键字 用开发者模式观察640?wx_fmt=png这里观察一下这个页面的元素分布,很容易就发现了 商品的id 信息,当然你可以想办法确认一下。640?wx_fmt=png现在就写个 获取商品id 的方法 getProductIdList# 获取商品id
def getProductIdList():
    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
现在所有的基本要求都有了,是时候把他们组合起来。在 main 方法中写剩下的组装部分if __name__ ==  __main__ :
    productIdList = getProductIdList() #获取商品id
    initial = 0
    while initial < len(productIdList) - 30:  # 总共有60个商品,我只取了前30个
        try:
            itemId = productIdList[initial]
            print( ---------- , itemId,  ------------ )
            maxPage = getLastPage(itemId) #获取商品评论最大页数
            num = 1
            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)
                        rateContent = rateList[n][ rateContent ]
                        dtime = rateList[n][ rateDate ]
                        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:
                    num += 1
                    print(e)
                    continue
            initial += 1
        except Exception as e:
            print(e)
所有的代码就这样完成了,我现在把 common.py 的代码,还有 tmallbra.py 的代码都贴出来# -*- coding:utf-8 -*-
# Author: zww
import requests
import time
import random
import socket
import http.client
import pymysql
import csv

# 封装requests
class Common(object):
    def getUrlContent(self, url, data=None):
        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 ,
             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",
             cache-control max-age=0
        }  # request 的请求头
        timeout = random.choice(range(80180))
        while True:
            try:
                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(815)))
            except socket.error as e:
                print( 4: , e)
                time.sleep(random.choice(range(2060)))
            except http.client.BadStatusLine as e:
                print( 5: , e)
                time.sleep(random.choice(range(3080)))
            except http.client.IncompleteRead as e:
                print( 6: , e)
                time.sleep(random.choice(range(515)))
        print( request success )
        return rep.text  # 返回的 Html 全文

    def writeData(self, data, url):
        with open(url,  a , errors= ignore , newline= as f:
            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()
        return results
        print( insert data success )

    def insertData(self, sql):
        # 打开数据库连接
        db = pymysql.connect("localhost""zww""000000""zwwdb")
        # 使用 cursor() 方法创建一个游标对象 cursor
        cursor = db.cursor()

        try:
            # sql = "INSERT INTO WEATHER(w_id, w_date, w_detail, w_temperature) VALUES (null,  %s , %s , %s )" % (data[0], data[1], data[2])
            cursor.execute(sql)    #单条数据写入
            # 提交到数据库执行
            db.commit()
        except Exception as e:
            print( 插入时发生异常  + e)
            # 如果发生错误则回滚
            db.rollback()
        # 关闭数据库连接
        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( insert into WEATHER(w_id, w_date, w_detail, w_temperature_low, w_temperature_high) value(null, %s,%s,%s,%s) ,datas)
            cursor.executemany(sql, datas)

            # 提交到数据库执行
            db.commit()
        except Exception as e:
            print( 插入时发生异常  + e)
            # 如果发生错误则回滚
            db.rollback()
        # 关闭数据库连接
        db.close()
        print( insert data success )
上面需要注意,数据库的配置。# -*- coding:utf-8 -*-
# Author: zww

from Include.commons.common import Common
from bs4 import BeautifulSoup
import json
import re
import pymysql

common = Common()

# 获取商品id
def getProductIdList():
    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):
    url =  https://rate.tmall.com/list_detail_rate.htm?itemId=  + str(
        itemId) +  &sellerId=2451699564&order=3¤tPage=  + str(currentPage) +  &append=0callback=jsonp336
    # itemId 产品id ;sellerId 店铺id 字段必须有值,但随意值就行
    html = common.getUrlContent(url)  # 获取网页信息
    # 删掉返回的多余信息
    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

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

if __name__ ==  __main__ :
    productIdList = getProductIdList() #获取商品id
    initial = 0
    while initial < len(productIdList) - 30:  # 总共有60个商品,我只取了前30个
        try:
            itemId = productIdList[initial]
            print( ---------- , itemId,  ------------ )
            maxPage = getLastPage(itemId) #获取商品评论最大页数
            num = 1
            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)
                        rateContent = rateList[n][ rateContent ]
                        dtime = rateList[n][ rateDate ]
                        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:
                    num += 1
                    print(e)
                    continue
            initial += 1
        except Exception as e:
            print(e)
存储、分析数据所有的代码都有了,就差数据库的建立了。我这里用的是 MySql 数据库。CREATE TABLE `bra` (
`bra_id`  int(11NOT NULL AUTO_INCREMENT COMMENT  id  ,
`bra_color`  varchar(25NULL COMMENT  颜色  ,
`bra_size`  varchar(25NULL COMMENT  罩杯  ,
`resource`  varchar(25NULL COMMENT  数据来源  ,
`comment`  varchar(500CHARACTER SET utf8mb4 DEFAULT NULL COMMENT  评论  ,
`comment_time`  datetime NULL COMMENT  评论时间  ,
PRIMARY KEY (`bra_id`)
character set utf8
;这里有两个地方需要注意, comment 评论字段需要设置编码格式为 utf8mb4  ,因为可能有表情文字。还有表需要设置为 utf8 编码,不然存不了中文。
建好了表,就可以完整执行代码了。(这里的执行可能需要点时间,可以做成多线程的方式)。看一下执行完之后,数据库有没有数据。640?wx_fmt=png数据是有了,但是有些我们多余的文字描述,我们可以稍微整理一下。
update bra set bra_color = REPLACE(bra_color, 2B6521-无钢圈4- , );
update bra set bra_color = REPLACE(bra_color, -1 , );
update bra set bra_color = REPLACE(bra_color, 5 , );
update bra set bra_size = substr(bra_size,1,3);
这里需要根据自己实际情况来修改。如果数据整理的差不多了,我们可以分析一下数据库的信息。select  A罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %A
union all select  B罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %B
union all select  C罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %C
union all select  D罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %D
union all select  E罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %E
union all select  F罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %F
union all select  G罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %G
union all select  H罩杯  as 罩杯, CONCAT(ROUND(COUNT(*)/(select count(*) from bra) * 1002) , "%"as 比例, COUNT(*) as 销量  from bra where bra_size like  %H
order by 销量 desc;
640?wx_fmt=png  (想知道是哪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__ :
    common = Common()
    results = common.queryData("""select count(*) from bra where bra_size like  %A  
            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  %D  
            union all select count(*) from bra where bra_size like  %E  
            union all select count(*) from bra where bra_size like  %F  
            union all select count(*) from bra where bra_size like  %G """)  # 获取每个罩杯数量
    attr = ["A罩杯",  G罩杯 , "B罩杯", "C罩杯", "D罩杯", "E罩杯", "F罩杯"]
    v1 = [results[0][0], results[6][0], results[1][0], results[2][0], results[3][0], results[4][0], results[5][0]]
    pie = Pie("内衣罩杯", width=1300, height=620)
    pie.add("", attr, v1, is_label_show=True)
    pie.render( size.html )
    print( success )

    results = common.queryData("""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  %褐%  
        union all select count(*) from bra where bra_color like  %黄%  """)  # 获取每个罩杯数量
    attr = ["肤色",  灰色 , "黑色", "蓝色", "粉色", "红色", "紫色",  绿色 , "白色", "褐色", "黄色"]
    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 )
    print( success )
这一章就到这里了,该知道的你也知道了,不该知道的你也知道了。哪些人是G杯,哪些妹子是A杯,以后找对象就不用担心这块的了。代码已放到github, 点击文末阅读原文,获取全部源码。

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

curton 2019-9-24 22:03

中国最佳男友
相关推荐阅读
minicaihong 2020-10-22 16:44
场效应管放大电路的直流偏置电路详解
什么是偏置电路晶体管构成的放大器要做到不失真地将信号电压放大,就必须保证晶体管的发射结正偏、集电结反偏。即应该设置它的工作点。所谓工作点就是通过外部电路的设置使晶体管的基极、发射极和集电极处于所要求的...
minicaihong 2020-10-22 16:37
场效应管偏置电路-场效应管偏置电路的工作原理及作用分析
什么是偏置电路晶体管构成的放大器要做到不失真地将信号电压放大,就必须保证晶体管的发射结正偏、集电结反偏。即应该设置它的工作点。所谓工作点就是通过外部电路的设置使晶体管的基极、发射极和集电极处于所要求的...
minicaihong 2020-10-22 16:27
MOS管偏置电路-MOS管直流、恒流等偏置电路图文及方程详解
MOS管偏置电路MOS管直流偏置电路MOS管的单电源直流偏置电路有两种:1、只能用于结型和耗尽型MOS管的自给偏置电路。2、可用于各种MOS管的分压式偏置电路自给MOS管偏置电路(1)图解法根据图中电...
minicaihong 2020-05-27 09:50
sprintf 格式化字符串
sprintf 格式化字符串好久没写博客了,又遇到自己觉得很傻的问题,格式化字符串还要找下定义和用法sprintf() 函数把格式化的字符串写入变量中。arg1、arg2、++ 参数将被插入...
minicaihong 2020-05-25 15:07
12T和1T的单片机
标准51是12T的,就是说12个时钟周期(晶振周期,例如12M的,周期是1/12M,单位秒),机器做一个指令度周期,刚好就是1/12M*12=1uS,常见指令例如nop就是一个周期,刚好1uS,其他的...
minicaihong 2020-05-23 16:22
4HC595驱动8*8点阵屏
74HC595驱动8*8点阵屏置顶 菜袅1号 2020-05-19 10:00:03   52   收藏展开该项目使用国产M0核单片机,驱动方式类似于stm32平台;点阵驱动芯片:...
EE直播间
更多
我要评论
1
13
关闭 站长推荐上一条 /3 下一条