• 爬了20W+条猫咪交易数据,它不愧是人类团宠


    前言

    看到可爱的猫咪表情包,总是会忍不住收藏,晒部分图如下:
    yauMlt.md.gif

    认识的一些朋友也养了猫,比如橘猫、英短、加菲猫之类的,看他们发朋友圈撸猫,老羡慕了,猫咪真的太可爱啦。发现一个专门交易猫猫的网站—猫猫交易网可以云看猫:http://www.maomijiaoyi.com/
    yauQ6P.md.gif

    从这个网站里爬取了猫猫品种介绍的数据,以及 20W+ 条猫猫交易数据,以此来了解一下可爱的猫咪。

    数据获取

    打开猫猫交易网,先爬取猫咪品种数据,打开页面可以看到猫猫品种列表:
    yaumYd.md.jpg

    但只显示了每种猫猫的品种名,参考价格,点进详情页,可以看到更加详细的数据:品种名、参考价格、中文学名、基本信息、性格特点、生活习性、优缺点、喂养方法等。
    yaunfA.md.jpg

    检查网页,可以发现网页结构简单,容易解析和提取数据。爬虫代码如下:

    # -*- coding: UTF-8 -*-
    """
    @File    :cat_kind_spider.py
    @Author  :叶庭云
    @CSDN    :https://yetingyun.blog.csdn.net/
    """
    import requests
    import re
    import csv
    from lxml import etree
    from tqdm import tqdm
    from fake_useragent import UserAgent
    
    # 随机产生请求头
    ua = UserAgent(verify_ssl=False, path='fake_useragent.json')
    
    def random_ua():        # 用于随机切换请求头
        headers = {
            "Accept-Encoding": "gzip",
            "Accept-Language": "zh-CN",
            "Connection": "keep-alive",
            "Host": "www.maomijiaoyi.com",
            "User-Agent": ua.random
        }
        return headers
    
    
    def create_csv():          # 创建保存数据的csv
        with open('./data/cat_kind.csv', 'w', newline='', encoding='utf-8') as f:
            wr = csv.writer(f)
            wr.writerow(['品种', '参考价格', '中文学名', '别名', '祖先', '分布区域',
                         '原产地', '体型', '原始用途', '今日用途', '分组', '身高',
                         '体重', '寿命', '整体', '毛发', '颜色', '头部', '眼睛',
                         '耳朵', '鼻子', '尾巴', '胸部', '颈部', '前驱', '后驱',
                         '基本信息', 'FCI标准', '性格特点', '生活习性', '优点/缺点',
                         '喂养方法', '鉴别挑选'])
    
    
    def scrape_page(url1):      # 获取HTML网页源代码 返回文本
        response = requests.get(url1, headers=random_ua())
        # print(response.status_code)
        response.encoding = 'utf-8'
        return response.text
    
    
    def get_cat_urls(html1):    # 获取每个品种猫咪详情页url
        dom = etree.HTML(html1)
        lis = dom.xpath('//div[@class="pinzhong_left"]/a')
        cat_urls = []
        for li in lis:
            cat_url = li.xpath('./@href')[0]
            cat_url = 'http://www.maomijiaoyi.com' + cat_url
            cat_urls.append(cat_url)
        return cat_urls
    
    
    def get_info(html2):    # 爬取每个品种猫咪详情页里的有关信息
        # 品种
        kind = re.findall('div class="line1">.*?<div class="name">(.*?)<span>', html2, re.S)[0]
        kind = kind.replace('
    ','').replace('
    ','').replace('	','')
        # 参考价格
        price = re.findall('<div>参考价格:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        price = price.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 中文学名
        chinese_name = re.findall('<div>中文学名:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        chinese_name = chinese_name.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 别名
        other_name = re.findall('<div>别名:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        other_name = other_name.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 祖先
        ancestor = re.findall('<div>祖先:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        ancestor = ancestor.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 分布区域
        area = re.findall('<div>分布区域:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        area = area.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 原产地
        source_area = re.findall('<div>原产地:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        source_area = source_area.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 体型
        body_size = re.findall('<div>体型:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        body_size = body_size.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 原始用途
        source_use = re.findall('<div>原始用途:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        source_use = source_use.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 今日用途
        today_use = re.findall('<div>今日用途:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        today_use = today_use.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 分组
        group = re.findall('<div>分组:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        group = group.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 身高
        height = re.findall('<div>身高:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        height = height.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 体重
        weight = re.findall('<div>体重:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        weight = weight.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 寿命
        lifetime = re.findall('<div>寿命:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
        lifetime = lifetime.replace('
    ', '').replace('
    ', '').replace('	', '')
        # 整体
        entirety = re.findall('<div>整体</div>.*?<!-- 页面小折角 -->.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        entirety = entirety.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 毛发
        hair = re.findall('<div>毛发</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        hair = hair.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 颜色
        color = re.findall('<div>颜色</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        color = color.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 头部
        head = re.findall('<div>头部</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        head = head.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 眼睛
        eye = re.findall('<div>眼睛</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        eye = eye.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 耳朵
        ear = re.findall('<div>耳朵</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        ear = ear.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 鼻子
        nose = re.findall('<div>鼻子</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        nose = nose.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 尾巴
        tail = re.findall('<div>尾巴</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        tail = tail.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 胸部
        chest = re.findall('<div>胸部</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        chest = chest.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 颈部
        neck = re.findall('<div>颈部</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        neck = neck.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 前驱
        font_foot = re.findall('<div>前驱</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        font_foot = font_foot.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
        # 后驱
        rear_foot = re.findall('<div>前驱</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
        rear_foot = rear_foot.replace('
    ', '').replace('
    ', '').replace('	', '').strip()
    
        # 保存前面猫猫的各种有关信息
        cat = [kind, price, chinese_name, other_name, ancestor, area, source_area,
               body_size, source_use, today_use, group, height, weight, lifetime,
               entirety, hair, color, head, eye, ear, nose, tail, chest, neck, font_foot, rear_foot]
    
        # 提取标签栏信息(基本信息-FCI标准-性格特点-生活习性-优缺点-喂养方法-鉴别挑选)
        html2 = etree.HTML(html2)
        labs = html2.xpath('//div[@class="property_list"]/div')
        for lab in labs:
            text1 = lab.xpath('string(.)')
            text1 = text1.replace('
    ','').replace('	','').replace('
    ','').replace(' ','')
            cat.append(text1)
        return cat
    
    
    def write_to_csv(data):     # 保存数据  追加写入
        with open('./data/cat_kind.csv', 'a+', newline='', encoding='utf-8') as fn:
            wr = csv.writer(fn)
            wr.writerow(data)
    
    
    if __name__ == '__main__':
        # 创建保存数据的csv
        create_csv()
        # 猫咪品种页面url
        base_url = 'http://www.maomijiaoyi.com/index.php?/pinzhongdaquan_5.html'
        # 获取品种页面中的所有url
        html = scrape_page(base_url)
        urls = get_cat_urls(html)
        # 进度条可视化运行情况    就不打印东西来看了
        pbar = tqdm(urls)
        # 开始爬取
        for url in pbar:
            text = scrape_page(url)
            info = get_info(text)
            write_to_csv(info)
    

    运行效果如下:
    yauI0O.md.gif

    成功爬取了猫咪品种数据保存到csv,接下来爬取猫猫交易数据,进入到买猫卖猫页面:
    yauo7D.md.gif

    爬取更详细的数据需要进入详情页,包含商家信息、猫咪品种、猫龄、价格、标题、在售只数、预防等信息。
    yau5nK.md.jpg

    由于数据量较大,可以分开爬取,先获取到每一页中的所有猫猫详情交易链接的 url 保存到csv,再读取 csv 中的 url 来请求,爬取每条交易数据,爬虫思路跟前面类似,为了加快爬取效率,可以使用多线程或者异步爬虫。最终获取了 20W+ 条数据。

    数据探索

    通过词云图来直观看一下,可爱的猫咪都有那些品种。
    yauhX6.md.jpg

    看各种猫咪的体型分布
    yauf6x.md.jpg

    所有品种的猫咪里,大型的只有一个品种,是布偶猫,其他品种都是中小型,那以后看见体型比较大的,可以先想到布偶猫。
    yaKZuV.md.jpg

    橘猫是世界各地都有的,不愧是我大橘猫。俗话说 "十个橘猫九个胖还有一个压塌炕"。橘猫比起其他花色的猫咪更喜欢吃东西,它们的食欲很好,能更好地生存,可能这也是橘猫在世界范围都有的原因吧。可它却是小型猫,橘猫小时候颜值一般挺高,看起来小小的一只,又嫩又可爱的,但等橘猫长大以后,才真正地意识到什么是 "橘足轻重"。
    yaKlC9.md.gif
    下面来看猫咪的交易数据,在交易的猫咪中,哪些品种交易数量最多呢?
    yaKk3n.md.jpg

    橘猫的交易数量最多呀,之前也提到橘猫世界各地都有,从这里也可以看到橘猫数量最多。其次是咖啡猫,布偶猫,英短蓝白猫等。
    再看看卖猫商家地区分布
    yaKAcq.md.jpg

    四川,重庆,广东是猫咪售卖商家数量最多的省份,江浙沪等地区猫咪售卖商家数量也很多,均在 10000 家以上。
    yaKEj0.md.jpg

    缅因猫、布偶猫均价名列前茅啊,橘猫的均价排倒数第二,看来挺实惠。
    这些售卖的猫咪猫龄一般为多大呢?
    yaKuEF.md.jpg

    售卖的猫咪猫龄主要在1-6个月,都是刚出生还未满半岁的小猫咪呀。这时候的小猫咪应该很可爱吧,等待有缘的主人把它带回家。
    最后来看一下网站里价格最贵的猫咪和浏览次数最多的猫咪

     1# -*- coding: UTF-8 -*-
     2"""
     3@File    :浏览最多_价格最贵的.py
     4@Author  :叶庭云
     5@CSDN    :https://yetingyun.blog.csdn.net/
     6"""
     7import pandas as pd
     8
     9df = pd.read_excel('处理后数据.xlsx')
    10print(df.info())
    11df1 = df.sort_values(by='浏览次数', ascending=False)
    12print(df1.iloc[:3, ::].values)
    13print('----------------------------------------------------------')
    14df2 = df.sort_values(by='价格', ascending=False)
    15print(df2.iloc[:3, ::].values)
    
    1# 浏览次数最多的
    2http://www.maomijiaoyi.com/index.php?/chanpinxiangqing_441879.html
    3http://www.maomijiaoyi.com/index.php?/chanpinxiangqing_462431.html
    4http://www.maomijiaoyi.com/index.php?/chanpinxiangqing_455366.html
    

    微信图片_20210208234505.png

    浏览次数最多的是这一家卖的缅因猫,浏览次数为16164。emmm,感觉这种猫咪看着还挺凶的,不怎么可爱。
    微信图片_20210208234519.png
    微信图片_20210208234512.png

    反观浏览次数排第二、第三的,价格便宜不少,预防都打了3针疫苗,在售只数还比较充裕,还比第一可爱好多(个人感觉)。

    # 价格最贵的如
    http://www.maomijiaoyi.com/index.php?/chanpinxiangqing_265770.html
    http://www.maomijiaoyi.com/index.php?/chanpinxiangqing_281910.html
    http://www.maomijiaoyi.com/index.php?/chanpinxiangqing_230417.html
    

    微信图片_20210208234502.png
    微信图片_20210208234523.png
    ![微信图片_20210208234516.png](https://i.loli.net/2021/02/08/3ZJTbeDRawGx6uh.png

    价格最贵的发现均为 3000 元的布偶猫。查阅资料发现,布偶猫,大型猫咪,不仅购买的时候价格高昂,饲养成本也比较高,因为食量和运动量都比较大,而且美容等相关费用也会高一些。

  • 相关阅读:
    [原]获取openstack-pike安装包
    [原]Failed connect to mirrors.cloud.aliyuncs.com:80; Connection refused
    [原]shell批量文件增删改前后缀
    [原]CentOS 7 chrony 笔记
    [原]Docker-issue(2) http: server gave HTTP response to HTTPS client
    [原]Docker-issue(1) image name 显示为 <none>
    [原]Django(1)----Django-setting中的STATIC_URL 和STATIC_ROOT 和STATICFILES_DIRS 的区别
    [原]Django-issue(1)---postgresql数据库连接密码错误
    [转]50个极好的bootstrap 后台框架主题下载
    [原]eclipse + pydev :Error in sitecustomize; set PYTHONVERBOSE for tracaeback: KeyError: 'sitecustomize'
  • 原文地址:https://www.cnblogs.com/syy1757528181/p/14391567.html
Copyright © 2020-2023  润新知