作者 | 葉庭雲
來源 | 修煉Python
頭圖 | 下載於視覺中國
前言
看到可愛的貓咪表情包,總是會忍不住收藏,曬部分圖如下:
認識的一些朋友也養了貓,比如橘貓、英短、加菲貓之類的,看他們發朋友圈擼貓,老羨慕了,貓咪真的太可愛啦。發現一個專門交易貓貓的網站—貓貓交易網可以雲看貓:http://www.maomijiaoyi.com/
從這個網站裏爬取了貓貓品種介紹的數據,以及 20W+ 條貓貓交易數據,以此來了解一下可愛的貓咪。
數據獲取
打開貓貓交易網,先爬取貓咪品種數據,打開頁面可以看到貓貓品種列表:
但只顯示了每種貓貓的品種名,參考價格,點進詳情頁,可以看到更加詳細的數據:品種名、參考價格、中文學名、基本信息、性格特點、生活習性、優缺點、餵養方法等。
檢查網頁,可以發現網頁結構簡單,容易解析和提取數據。爬蟲代碼如下:
1# -*- coding: UTF-8 -*-
2"""
3@File :cat_kind_spider.py
4@Author :葉庭雲
5@CSDN :https://yetingyun.blog.csdn.net/
6"""
7import requests
8import re
9import csv
10from lxml import etree
11from tqdm import tqdm
12from fake_useragent import UserAgent
13
14# 隨機產生請求頭
15ua = UserAgent(verify_ssl=False, path='fake_useragent.json')
16
17def random_ua(): # 用於隨機切換請求頭
18 headers = {
19 "Accept-Encoding": "gzip",
20 "Accept-Language": "zh-CN",
21 "Connection": "keep-alive",
22 "Host": "www.maomijiaoyi.com",
23 "User-Agent": ua.random
24 }
25 return headers
26
27
28def create_csv(): # 創建保存數據的csv
29 with open('./data/cat_kind.csv', 'w', newline='', encoding='utf-8') as f:
30 wr = csv.writer(f)
31 wr.writerow(['品種', '參考價格', '中文學名', '別名', '祖先', '分佈區域',
32 '原產地', '體型', '原始用途', '今日用途', '分組', '身高',
33 '體重', '壽命', '整體', '毛髮', '顏色', '頭部', '眼睛',
34 '耳朵', '鼻子', '尾巴', '胸部', '頸部', '前驅', '後驅',
35 '基本信息', 'FCI標準', '性格特點', '生活習性', '優點/缺點',
36 '餵養方法', '鑑別挑選'])
37
38
39def scrape_page(url1): # 獲取HTML網頁源代碼 返回文本
40 response = requests.get(url1, headers=random_ua())
41 # print(response.status_code)
42 response.encoding = 'utf-8'
43 return response.text
44
45
46def get_cat_urls(html1): # 獲取每個品種貓咪詳情頁url
47 dom = etree.HTML(html1)
48 lis = dom.xpath('//div[@class="pinzhong_left"]/a')
49 cat_urls = []
50 for li in lis:
51 cat_url = li.xpath('./@href')[0]
52 cat_url = 'http://www.maomijiaoyi.com' + cat_url
53 cat_urls.append(cat_url)
54 return cat_urls
55
56
57def get_info(html2): # 爬取每個品種貓咪詳情頁裏的有關信息
58 # 品種
59 kind = re.findall('div class="line1">.*?<div class="name">(.*?)<span>', html2, re.S)[0]
60 kind = kind.replace('\r','').replace('\n','').replace('\t','')
61 # 參考價格
62 price = re.findall('<div>參考價格:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
63 price = price.replace('\r', '').replace('\n', '').replace('\t', '')
64 # 中文學名
65 chinese_name = re.findall('<div>中文學名:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
66 chinese_name = chinese_name.replace('\r', '').replace('\n', '').replace('\t', '')
67 # 別名
68 other_name = re.findall('<div>別名:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
69 other_name = other_name.replace('\r', '').replace('\n', '').replace('\t', '')
70 # 祖先
71 ancestor = re.findall('<div>祖先:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
72 ancestor = ancestor.replace('\r', '').replace('\n', '').replace('\t', '')
73 # 分佈區域
74 area = re.findall('<div>分佈區域:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
75 area = area.replace('\r', '').replace('\n', '').replace('\t', '')
76 # 原產地
77 source_area = re.findall('<div>原產地:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
78 source_area = source_area.replace('\r', '').replace('\n', '').replace('\t', '')
79 # 體型
80 body_size = re.findall('<div>體型:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
81 body_size = body_size.replace('\r', '').replace('\n', '').replace('\t', '').strip()
82 # 原始用途
83 source_use = re.findall('<div>原始用途:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
84 source_use = source_use.replace('\r', '').replace('\n', '').replace('\t', '')
85 # 今日用途
86 today_use = re.findall('<div>今日用途:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
87 today_use = today_use.replace('\r', '').replace('\n', '').replace('\t', '')
88 # 分組
89 group = re.findall('<div>分組:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
90 group = group.replace('\r', '').replace('\n', '').replace('\t', '')
91 # 身高
92 height = re.findall('<div>身高:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
93 height = height.replace('\r', '').replace('\n', '').replace('\t', '')
94 # 體重
95 weight = re.findall('<div>體重:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
96 weight = weight.replace('\r', '').replace('\n', '').replace('\t', '')
97 # 壽命
98 lifetime = re.findall('<div>壽命:</div>.*?<div>(.*?)</div>', html2, re.S)[0]
99 lifetime = lifetime.replace('\r', '').replace('\n', '').replace('\t', '')
100 # 整體
101 entirety = re.findall('<div>整體</div>.*?<!-- 頁面小折角 -->.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
102 entirety = entirety.replace('\r', '').replace('\n', '').replace('\t', '').strip()
103 # 毛髮
104 hair = re.findall('<div>毛髮</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
105 hair = hair.replace('\r', '').replace('\n', '').replace('\t', '').strip()
106 # 顏色
107 color = re.findall('<div>顏色</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
108 color = color.replace('\r', '').replace('\n', '').replace('\t', '').strip()
109 # 頭部
110 head = re.findall('<div>頭部</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
111 head = head.replace('\r', '').replace('\n', '').replace('\t', '').strip()
112 # 眼睛
113 eye = re.findall('<div>眼睛</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
114 eye = eye.replace('\r', '').replace('\n', '').replace('\t', '').strip()
115 # 耳朵
116 ear = re.findall('<div>耳朵</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
117 ear = ear.replace('\r', '').replace('\n', '').replace('\t', '').strip()
118 # 鼻子
119 nose = re.findall('<div>鼻子</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
120 nose = nose.replace('\r', '').replace('\n', '').replace('\t', '').strip()
121 # 尾巴
122 tail = re.findall('<div>尾巴</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
123 tail = tail.replace('\r', '').replace('\n', '').replace('\t', '').strip()
124 # 胸部
125 chest = re.findall('<div>胸部</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
126 chest = chest.replace('\r', '').replace('\n', '').replace('\t', '').strip()
127 # 頸部
128 neck = re.findall('<div>頸部</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
129 neck = neck.replace('\r', '').replace('\n', '').replace('\t', '').strip()
130 # 前驅
131 font_foot = re.findall('<div>前驅</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
132 font_foot = font_foot.replace('\r', '').replace('\n', '').replace('\t', '').strip()
133 # 後驅
134 rear_foot = re.findall('<div>前驅</div>.*?<div></div>.*?<div>(.*?)</div>', html2, re.S)[0]
135 rear_foot = rear_foot.replace('\r', '').replace('\n', '').replace('\t', '').strip()
136
137 # 保存前面貓貓的各種有關信息
138 cat = [kind, price, chinese_name, other_name, ancestor, area, source_area,
139 body_size, source_use, today_use, group, height, weight, lifetime,
140 entirety, hair, color, head, eye, ear, nose, tail, chest, neck, font_foot, rear_foot]
141
142 # 提取標籤欄信息(基本信息-FCI標準-性格特點-生活習性-優缺點-餵養方法-鑑別挑選)
143 html2 = etree.HTML(html2)
144 labs = html2.xpath('//div[@class="property_list"]/div')
145 for lab in labs:
146 text1 = lab.xpath('string(.)')
147 text1 = text1.replace('\n','').replace('\t','').replace('\r','').replace(' ','')
148 cat.append(text1)
149 return cat
150
151
152def write_to_csv(data): # 保存數據 追加寫入
153 with open('./data/cat_kind.csv', 'a+', newline='', encoding='utf-8') as fn:
154 wr = csv.writer(fn)
155 wr.writerow(data)
156
157
158if __name__ == '__main__':
159 # 創建保存數據的csv
160 create_csv()
161 # 貓咪品種頁面url
162 base_url = 'http://www.maomijiaoyi.com/index.php?/pinzhongdaquan_5.html'
163 # 獲取品種頁面中的所有url
164 html = scrape_page(base_url)
165 urls = get_cat_urls(html)
166 # 進度條可視化運行情況 就不打印東西來看了
167 pbar = tqdm(urls)
168 # 開始爬取
169 for url in pbar:
170 text = scrape_page(url)
171 info = get_info(text)
172 write_to_csv(info)
運行效果如下:
成功爬取了貓咪品種數據保存到csv,接下來爬取貓貓交易數據,進入到買貓賣貓頁面:
爬取更詳細的數據需要進入詳情頁,包含商家信息、貓咪品種、貓齡、價格、標題、在售只數、預防等信息。
由於數據量較大,可以分開爬取,先獲取到每一頁中的所有貓貓詳情交易鏈接的 url 保存到csv,再讀取 csv 中的 url 來請求,爬取每條交易數據,爬蟲思路跟前面類似,爲了加快爬取效率,可以使用多線程或者異步爬蟲。最終獲取了 20W+ 條數據。
數據探索
通過詞雲圖來直觀看一下,可愛的貓咪都有那些品種。
看各種貓咪的體型分佈
所有品種的貓咪裏,大型的只有一個品種,是布偶貓,其他品種都是中小型,那以後看見體型比較大的,可以先想到布偶貓。
橘貓是世界各地都有的,不愧是我大橘貓。俗話說 "十個橘貓九個胖還有一個壓塌炕"。橘貓比起其他花色的貓咪更喜歡喫東西,它們的食慾很好,能更好地生存,可能這也是橘貓在世界範圍都有的原因吧。可它卻是小型貓,橘貓小時候顏值一般挺高,看起來小小的一隻,又嫩又可愛的,但等橘貓長大以後,才真正地意識到什麼是 "橘足輕重"。
下面來看貓咪的交易數據,在交易的貓咪中,哪些品種交易數量最多呢?
橘貓的交易數量最多呀,之前也提到橘貓世界各地都有,從這裏也可以看到橘貓數量最多。其次是咖啡貓,布偶貓,英短藍白貓等。
再看看賣貓商家地區分佈
四川,重慶,廣東是貓咪售賣商家數量最多的省份,江浙滬等地區貓咪售賣商家數量也很多,均在 10000 家以上。
緬因貓、布偶貓均價名列前茅啊,橘貓的均價排倒數第二,看來挺實惠。
這些售賣的貓咪貓齡一般爲多大呢?
售賣的貓咪貓齡主要在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
瀏覽次數最多的是這一家賣的緬因貓,瀏覽次數爲16164。emmm,感覺這種貓咪看着還挺兇的,不怎麼可愛。
反觀瀏覽次數排第二、第三的,價格便宜不少,預防都打了3針疫苗,在售只數還比較充裕,還比第一可愛好多(個人感覺)。
1# 價格最貴的如
2http://www.maomijiaoyi.com/index.php?/chanpinxiangqing_265770.html
3http://www.maomijiaoyi.com/index.php?/chanpinxiangqing_281910.html
4http://www.maomijiaoyi.com/index.php?/chanpinxiangqing_230417.html
價格最貴的發現均爲 3000 元的布偶貓。查閱資料發現,布偶貓,大型貓咪,不僅購買的時候價格高昂,飼養成本也比較高,因爲食量和運動量都比較大,而且美容等相關費用也會高一些。
參考文章:
https://mp.weixin.qq.com/s/-Fh156bh1166R9fqNa6OmQ
福 利
CSDN給大家發壓歲錢啦!
2月4日到2月11日每天上午11點
價值198元的芒果TV年卡,價值99元的CSDN月卡!現金紅包,CSDN電子書月卡等獎品大放送!百分百中獎!
電腦端點擊鏈接參與:https://t.csdnimg.cn/gAkN
更多精彩推薦
☞英超引入 AI 球探,尋找下一個足球巨星☞三年投 1000 億,達摩院何以仗劍走天涯?☞程序員硬核“年終大掃除”,清理了數據庫 70GB 空間
☞2021年淺談多任務學習
點分享點收藏點點贊點在看