您好,登錄后才能下訂單哦!
摘要:使用 Scrapy 爬取豌豆莢全網(wǎng) 70,000+ App,并進(jìn)行探索性分析。
寫(xiě)在前面:若對(duì)數(shù)據(jù)抓取部分不感興趣,可以直接下拉到數(shù)據(jù)分析部分。
之前我們使用了 Scrapy 爬取并分析了酷安網(wǎng) 6000+ App,為什么這篇文章又在講抓 App 呢?
因?yàn)槲蚁矚g折騰 App,哈哈。當(dāng)然,主要是因?yàn)橄旅孢@幾點(diǎn):
第一、之前抓取的網(wǎng)頁(yè)很簡(jiǎn)單
在抓取酷安網(wǎng)時(shí),我們使用 for 循環(huán),遍歷了幾百頁(yè)就完成了所有內(nèi)容的抓取,非常簡(jiǎn)單,但現(xiàn)實(shí)往往不會(huì)這么 easy,有時(shí)我們要抓的內(nèi)容會(huì)比較龐大,比如抓取整個(gè)網(wǎng)站的數(shù)據(jù),為了增強(qiáng)爬蟲(chóng)技能,所以本文選擇了「豌豆莢」這個(gè)網(wǎng)站。
目標(biāo)是: 爬取該網(wǎng)站所有分類(lèi)下的 App 信息并下載 App 圖標(biāo),數(shù)量在 70,000 左右,比酷安升了一個(gè)數(shù)量級(jí)。
第二、再次練習(xí)使用強(qiáng)大的 Scrapy 框架
之前只是初步地使用了 Scrapy 進(jìn)行抓取,還沒(méi)有充分領(lǐng)會(huì)到 Scrapy 有多么牛逼,所以本文嘗試深入使用 Scrapy,增加隨機(jī) UserAgent、代理 IP 和圖片下載等設(shè)置。
第三、對(duì)比一下酷安和豌豆莢兩個(gè)網(wǎng)站
相信很多人都在使用豌豆莢下載 App,我則使用酷安較多,所以也想比較一下這兩個(gè)網(wǎng)站有什么異同點(diǎn)。
話不多說(shuō),下面開(kāi)始抓取流程。
首先,我們來(lái)了解一下要抓取的目標(biāo)網(wǎng)頁(yè)是什么樣的。
可以看到該網(wǎng)站上的 App 分成了很多類(lèi),包括:「應(yīng)用播放」、「系統(tǒng)工具」等,一共有 14 個(gè)大類(lèi)別,每個(gè)大類(lèi)下又細(xì)分了多個(gè)小類(lèi),例如,影音播放下包括:「視頻」、「直播」等。
點(diǎn)擊「視頻」進(jìn)入第二級(jí)子類(lèi)頁(yè)面,可以看到每款 App 的部分信息,包括:圖標(biāo)、名稱(chēng)、安裝數(shù)量、體積、評(píng)論等。
接著,我們可以再進(jìn)入第三級(jí)頁(yè)面,也就是每款 App 的詳情頁(yè),可以看到多了下載數(shù)、好評(píng)率、評(píng)論數(shù)這幾樣參數(shù),抓取思路和第二級(jí)頁(yè)面大同小異,同時(shí)為了減小網(wǎng)站壓力,所以 App 詳情頁(yè)就不抓取了。
所以,這是一個(gè)分類(lèi)多級(jí)頁(yè)面的抓取問(wèn)題,依次抓取每一個(gè)大類(lèi)下的全部子類(lèi)數(shù)據(jù)。
學(xué)會(huì)了這種抓取思路,很多網(wǎng)站我們都可以去抓,比如很多人愛(ài)爬的「豆瓣電影」也是這樣的結(jié)構(gòu)。
數(shù)據(jù)抓取完成后,本文主要是對(duì)分類(lèi)型數(shù)據(jù)的進(jìn)行簡(jiǎn)單的探索性分析,包括這么幾個(gè)方面:
下載量最多 / 最少的 App 總排名
下載量最多 / 最少的 App 分類(lèi) / 子分類(lèi)排名
App 下載量區(qū)間分布
App 名稱(chēng)重名的有多少
Python
Scrapy
Pyecharts
我們剛才已經(jīng)初步對(duì)網(wǎng)站進(jìn)行了分析,大致思路可以分為兩步,首先是提取所有子類(lèi)的 URL 鏈接,然后分別抓取每個(gè) URL 下的 App 信息就行了。
可以看到,子類(lèi)的 URL 是由兩個(gè)數(shù)字構(gòu)成,前面的數(shù)字表示分類(lèi)編號(hào),后面的數(shù)字表示子分類(lèi)編號(hào),得到了這兩個(gè)編號(hào),就可以抓取該分類(lèi)下的所有 App 信息,那么怎么獲取這兩個(gè)數(shù)值代碼呢?
回到分類(lèi)頁(yè)面,定位查看信息,可以看到分類(lèi)信息都包裹在每個(gè) li 節(jié)點(diǎn)中,子分類(lèi) URL 則又在子節(jié)點(diǎn) a 的 href 屬性中,大分類(lèi)一共有 14 個(gè),子分類(lèi)一共有 88 個(gè)。
到這兒,思路就很清晰了,我們可以用 CSS 提取出全部子分類(lèi)的 URL,然后分別抓取所需信息即可。
另外還需注意一點(diǎn),該網(wǎng)站的 首頁(yè)信息是靜態(tài)加載的,從第 2 頁(yè)開(kāi)始是采用了 Ajax 動(dòng)態(tài)加載,URL 不同,需要分別進(jìn)行解析提取。
我們要爬取兩部分內(nèi)容,一是 APP 的數(shù)據(jù)信息,包括前面所說(shuō)的:名稱(chēng)、安裝數(shù)量、體積、評(píng)論等,二是下載每款 App 的圖標(biāo),分文件夾進(jìn)行存放。
由于該網(wǎng)站有一定的反爬措施,所以我們需要添加隨機(jī) UA 和代理 IP
這里隨機(jī) UA 使用 scrapy-fake-useragent 庫(kù),一行代碼就能搞定,代理 IP 直接上阿布云付費(fèi)代理,幾塊錢(qián)搞定簡(jiǎn)單省事。
下面,就直接上代碼了。
1import scrapy 2 3class WandoujiaItem(scrapy.Item): 4 cate_name = scrapy.Field() #分類(lèi)名 5 child_cate_name = scrapy.Field() #分類(lèi)編號(hào) 6 app_name = scrapy.Field() # 子分類(lèi)名 7 install = scrapy.Field() # 子分類(lèi)編號(hào) 8 volume = scrapy.Field() # 體積 9 comment = scrapy.Field() # 評(píng)論10 icon_url = scrapy.Field() # 圖標(biāo)url
Python資源分享qun 784758214 ,內(nèi)有安裝包,PDF,學(xué)習(xí)視頻,這里是Python學(xué)習(xí)者的聚集地,零基礎(chǔ),進(jìn)階,都?xì)g迎
中間件主要用于設(shè)置代理 IP。
1import base64 2proxyServer = "http://http-dyn.abuyun.com:9020" 3proxyUser = "你的信息" 4proxyPass = "你的信息" 5 6proxyAuth = "Basic " + base64.urlsafe_b64encode(bytes((proxyUser + ":" + proxyPass), "ascii")).decode("utf8") 7class AbuyunProxyMiddleware(object): 8 def process_request(self, request, spider): 9 request.meta["proxy"] = proxyServer10 request.headers["Proxy-Authorization"] = proxyAuth21 logging.debug('Using Proxy:%s'%proxyServer)
該文件用于存儲(chǔ)數(shù)據(jù)到 MongoDB 和下載圖標(biāo)到分類(lèi)文件夾中。
存儲(chǔ)到 MongoDB:
1MongoDB 存儲(chǔ) 2class MongoPipeline(object): 3 def __init__(self,mongo_url,mongo_db): 4 self.mongo_url = mongo_url 5 self.mongo_db = mongo_db 6 7 @classmethod 8 def from_crawler(cls,crawler): 9 return cls(10 mongo_url = crawler.settings.get('MONGO_URL'),11 mongo_db = crawler.settings.get('MONGO_DB')12 )1314 def open_spider(self,spider):15 self.client = pymongo.MongoClient(self.mongo_url)16 self.db = self.client[self.mongo_db]1718 def process_item(self,item,spider):19 name = item.__class__.__name__20 # self.db[name].insert(dict(item))21 self.db[name].update_one(item, {'$set': item}, upsert=True)22 return item2324 def close_spider(self,spider):25 self.client.close()
按文件夾下載圖標(biāo):
1# 分文件夾下載 2class ImagedownloadPipeline(ImagesPipeline): 3 def get_media_requests(self,item,info): 4 if item['icon_url']: 5 yield scrapy.Request(item['icon_url'],meta={'item':item}) 6 7 def file_path(self, request, response=None, info=None): 8 name = request.meta['item']['app_name'] 9 cate_name = request.meta['item']['cate_name']10 child_cate_name = request.meta['item']['child_cate_name']1112 path2 = r'/wandoujia/%s/%s' %(cate_name,child_cate_name)13 path = r'{}\{}.{}'.format(path2, name, 'jpg')14 return path2516 def item_completed(self,results,item,info):17 image_path = [x['path'] for ok,x in results if ok]18 if not image_path:19 raise DropItem('Item contains no images')20 return item
1BOT_NAME = 'wandoujia' 2SPIDER_MODULES = ['wandoujia.spiders'] 3NEWSPIDER_MODULE = 'wandoujia.spiders' 4 5MONGO_URL = 'localhost' 6MONGO_DB = 'wandoujia' 7 8# 是否遵循機(jī)器人規(guī)則 9ROBOTSTXT_OBEY = False10# 下載設(shè)置延遲 由于買(mǎi)的阿布云一秒只能請(qǐng)求5次,所以每個(gè)請(qǐng)求設(shè)置了 0.2s延遲11DOWNLOAD_DELAY = 0.21213DOWNLOADER_MIDDLEWARES = {14 'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,15 'scrapy_fake_useragent.middleware.RandomUserAgentMiddleware': 100, # 隨機(jī)UA16 'wandoujia.middlewares.AbuyunProxyMiddleware': 200 # 阿布云代理17 )1819ITEM_PIPELINES = {20 'wandoujia.pipelines.MongoPipeline': 300,21 'wandoujia.pipelines.ImagedownloadPipeline': 400,22}2324# URL不去重25DUPEFILTER_CLASS = 'scrapy.dupefilters.BaseDupeFilter'
主程序這里列出關(guān)鍵的部分:
1def __init__(self): 2 self.cate_url = 'https://www.wandoujia.com/category/app' 3 # 子分類(lèi)首頁(yè)url 4 self.url = 'https://www.wandoujia.com/category/' 5 # 子分類(lèi) ajax請(qǐng)求頁(yè)url 6 self.ajax_url = 'https://www.wandoujia.com/wdjweb/api/category/more?' 7 # 實(shí)例化分類(lèi)標(biāo)簽 8 self.wandou_category = Get_category() 9def start_requests(self):10 yield scrapy.Request(self.cate_url,callback=self.get_category)1112def get_category(self,response): 13 cate_content = self.wandou_category.parse_category(response)14 # ...
這里,首先定義幾個(gè) URL,包括:分類(lèi)頁(yè)面、子分類(lèi)首頁(yè)、子分類(lèi) AJAX 頁(yè),也就是第 2 頁(yè)開(kāi)始的 URL,然后又定義了一個(gè)類(lèi) Get_category() 專(zhuān)門(mén)用于提取全部的子分類(lèi) URL,稍后我們將展開(kāi)該類(lèi)的代碼。
程序從 start_requests 開(kāi)始運(yùn)行,解析首頁(yè)獲得響應(yīng),調(diào)用 get_category() 方法,然后使用 Get_category() 類(lèi)中的 parse_category() 方法提取出所有 URL,具體代碼如下:
1class Get_category(): 2 def parse_category(self, response): 3 category = response.css('.parent-cate') 4 data = [{ 5 'cate_name': item.css('.cate-link::text').extract_first(), 6 'cate_code': self.get_category_code(item), 7 'child_cate_codes': self.get_child_category(item), 8 } for item in category] 9 return data1011 # 獲取所有主分類(lèi)標(biāo)簽數(shù)值代碼12 def get_category_code(self, item):13 cate_url = item.css('.cate-link::attr("href")').extract_first()14 pattern = re.compile(r'.*/(\d+)') # 提取主類(lèi)標(biāo)簽代碼15 cate_code = re.search(pattern, cate_url)16 return cate_code.group(1)1718 # 獲取所有子分類(lèi)名稱(chēng)和編碼19 def get_child_category(self, item):20 child_cate = item.css('.child-cate a')21 child_cate_url = [{22 'child_cate_name': child.css('::text').extract_first(),23 'child_cate_code': self.get_child_category_code(child)24 } for child in child_cate]25 return child_cate_url2627 # 正則提取子分類(lèi)編碼28 def get_child_category_code(self, child):29 child_cate_url = child.css('::attr("href")').extract_first()30 pattern = re.compile(r'.*_(\d+)') # 提取小類(lèi)標(biāo)簽編號(hào)31 child_cate_code = re.search(pattern, child_cate_url)32 return child_cate_code.group(1)
Python資源分享qun 784758214 ,內(nèi)有安裝包,PDF,學(xué)習(xí)視頻,這里是Python學(xué)習(xí)者的聚集地,零基礎(chǔ),進(jìn)階,都?xì)g迎
這里,除了分類(lèi)名稱(chēng) cate_name 可以很方便地直接提取出來(lái),分類(lèi)編碼和子分類(lèi)的子分類(lèi)的名稱(chēng)和編碼,我們使用了 get_category_code() 等三個(gè)方法進(jìn)行提取。提取方法使用了 CSS 和正則表達(dá)式,比較簡(jiǎn)單。
最終提取的分類(lèi)名稱(chēng)和編碼結(jié)果如下,利用這些編碼,我們就可以構(gòu)造 URL 請(qǐng)求開(kāi)始提取每個(gè)子分類(lèi)下的 App 信息了。
1{'cate_name': '影音播放', 'cate_code': '5029', 'child_cate_codes': [ 2 {'child_cate_name': '視頻', 'child_cate_code': '716'}, 3 {'child_cate_name': '直播', 'child_cate_code': '1006'}, 4 ... 5 ]}, 6{'cate_name': '系統(tǒng)工具', 'cate_code': '5018', 'child_cate_codes': [ 7 {'child_cate_name': 'WiFi', 'child_cate_code': '895'}, 8 {'child_cate_name': '瀏覽器', 'child_cate_code': '599'}, 9 ...10 ]}, 11...
接著前面的 get_category() 繼續(xù)往下寫(xiě),提取 App 的信息:
1def get_category(self,response): 2 cate_content = self.wandou_category.parse_category(response) 3 # ... 4 for item in cate_content: 5 child_cate = item['child_cate_codes'] 6 for cate in child_cate: 7 cate_code = item['cate_code'] 8 cate_name = item['cate_name'] 9 child_cate_code = cate['child_cate_code']10 child_cate_name = cate['child_cate_name']1112 page = 1 # 設(shè)置爬取起始頁(yè)數(shù)13 if page == 1:14 # 構(gòu)造首頁(yè)url15 category_url = '{}{}_{}' .format(self.url, cate_code, child_cate_code)16 else:17 params = {18 'catId': cate_code, # 類(lèi)別19 'subCatId': child_cate_code, # 子類(lèi)別20 'page': page,21 }22 category_url = self.ajax_url + urlencode(params)23 dict = {'page':page,'cate_name':cate_name,'cate_code':cate_code,'child_cate_name':child_cate_name,'child_cate_code':child_cate_code}24 yield scrapy.Request(category_url,callback=self.parse,meta=dict)
這里,依次提取出全部的分類(lèi)名稱(chēng)和編碼,用于構(gòu)造請(qǐng)求的 URL。
由于首頁(yè)的 URL 和第 2 頁(yè)開(kāi)始的 URL 形式不同,所以使用了 if 語(yǔ)句分別進(jìn)行構(gòu)造。接下來(lái),請(qǐng)求該 URL 然后調(diào)用 self.parse() 方法進(jìn)行解析,這里使用了 meta 參數(shù)用于傳遞相關(guān)參數(shù)。
1def parse(self, response): 2 if len(response.body) >= 100: # 判斷該頁(yè)是否爬完,數(shù)值定為100是因?yàn)闊o(wú)內(nèi)容時(shí)長(zhǎng)度是87 3 page = response.meta['page'] 4 cate_name = response.meta['cate_name'] 5 cate_code = response.meta['cate_code'] 6 child_cate_name = response.meta['child_cate_name'] 7 child_cate_code = response.meta['child_cate_code'] 8 9 if page == 1:10 contents = response11 else:12 jsonresponse = json.loads(response.body_as_unicode())13 contents = jsonresponse['data']['content']14 # response 是json,json內(nèi)容是html,html 為文本不能直接使用.css 提取,要先轉(zhuǎn)換15 contents = scrapy.Selector(text=contents, type="html")1617 contents = contents.css('.card')18 for content in contents:19 # num += 120 item = WandoujiaItem()21 item['cate_name'] = cate_name22 item['child_cate_name'] = child_cate_name23 item['app_name'] = self.clean_name(content.css('.name::text').extract_first()) 24 item['install'] = content.css('.install-count::text').extract_first()25 item['volume'] = content.css('.meta span:last-child::text').extract_first()26 item['comment'] = content.css('.comment::text').extract_first().strip()27 item['icon_url'] = self.get_icon_url(content.css('.icon-wrap a img'),page)28 yield item2930 # 遞歸爬下一頁(yè)31 page += 132 params = {33 'catId': cate_code, # 大類(lèi)別34 'subCatId': child_cate_code, # 小類(lèi)別35 'page': page,36 }37 ajax_url = self.ajax_url + urlencode(params)38 dict = {'page':page,'cate_name':cate_name,'cate_code':cate_code,'child_cate_name':child_cate_name,'child_cate_code':child_cate_code}39 yield scrapy.Request(ajax_url,callback=self.parse,meta=dict)
最后,parse() 方法用來(lái)解析提取最終我們需要的 App 名稱(chēng)、安裝量等信息,解析完成一頁(yè)后,page 進(jìn)行遞增,然后重復(fù)調(diào)用 parse() 方法循環(huán)解析,直到解析完全部分類(lèi)的最后一頁(yè)。
最終,幾個(gè)小時(shí)后,我們就可以完成全部 App 信息的抓取,我這里得到 73,755 條信息和 72,150 個(gè)圖標(biāo),兩個(gè)數(shù)值不一樣是因?yàn)橛行?App 只有信息沒(méi)有圖標(biāo)。
圖標(biāo)下載:
下面將對(duì)提取的信息,進(jìn)行簡(jiǎn)單的探索性分析。
首先來(lái)看一下 App 的安裝量情況,畢竟 70000 多款 App,自然很感興趣哪些 App 使用地最多,哪些又使用地最少。
代碼實(shí)現(xiàn)如下:
1plt.style.use('ggplot') 2colors = '#6D6D6D' #字體顏色 3colorline = '#63AB47' #紅色CC2824 #豌豆莢綠 4fontsize_title = 20 5fontsize_text = 10 6 7# 下載量總排名 8def analysis_maxmin(data): 9 data_max = (data[:10]).sort_values(by='install_count')10 data_max['install_count'] = (data_max['install_count'] / 100000000).round(1)11 data_max.plot.barh(x='app_name',y='install_count',color=colorline)12 for y, x in enumerate(list((data_max['install_count']))):13 plt.text(x + 0.1, y - 0.08, '%s' %14 round(x, 1), ha='center', color=colors)1516 plt.title('安裝量最多的 10 款 App ?',color=colors)17 plt.xlabel('下載量(億次)')18 plt.ylabel('App')19 plt.tight_layout()20 # plt.savefig('安裝量最多的App.png',dpi=200)21 plt.show()
看了上圖,有兩個(gè)「沒(méi)想到」:
排名第一的居然是一款手機(jī)管理軟件
對(duì)豌豆莢網(wǎng)上的這個(gè)第一名感到意外,一是、好奇大家都那么愛(ài)手機(jī)清理或者怕中毒么?畢竟,我自己的手機(jī)都「裸奔」了好些年;二是、第一名居然不是鵝廠的其他產(chǎn)品,比如:微信或者QQ。
榜單放眼望去,以為會(huì)出現(xiàn)的沒(méi)有出現(xiàn),沒(méi)有想到的卻出現(xiàn)了
前十名中,居然出現(xiàn)了書(shū)旗小說(shuō)、印客這些比較少聽(tīng)過(guò)的名字,而國(guó)民 App 微信、支付寶等甚至都沒(méi)有出現(xiàn)在這個(gè)榜單中。
帶著疑問(wèn)和好奇,分別找到了「騰訊手機(jī)管家」和「微信」兩款 App 的主頁(yè):
騰訊手機(jī)管家下載和安裝量:
微信下載和安裝量:
這是什么情況???
騰訊管家 3 億多的下載量等同于安裝量,而微信 20 多億的下載量,只有區(qū)區(qū)一千多萬(wàn)的安裝量,兩組數(shù)據(jù)對(duì)比,大致反映了兩個(gè)問(wèn)題:
要么是騰訊管家的下載量實(shí)際并沒(méi)有那么多
不管是哪個(gè)問(wèn)題,都反映了一個(gè)問(wèn)題:該網(wǎng)站做得不夠走心啊。
為了證明這個(gè)觀點(diǎn),將前十名的安裝量和下載量都作了對(duì)比,發(fā)現(xiàn)很多 App 的安裝量和下載量是一樣的,也就是說(shuō):這些 App 的實(shí)際安裝量并沒(méi)有那么多,而如果這樣的話,那么這份榜單就有很大水分了。
難道,辛辛苦苦爬了那么久,就得到這樣的結(jié)果?
不死心,接著再看看安裝量最少的 App 是什么情況,這里找出了其中最少的 10 款:
掃了一眼,更加沒(méi)想到了:
「QQ 音樂(lè)」竟然是倒數(shù)第一,只有 3 次安裝量!
這和剛剛上市、市值千億的 QQ 音樂(lè)是同一款產(chǎn)品?
再次核實(shí)了一下:
沒(méi)有看錯(cuò),是寫(xiě)著 3人安裝!
這是已經(jīng)不走心到什么程度了?這個(gè)安裝量,鵝廠還能「用心做好音樂(lè)」?
說(shuō)實(shí)話,到這兒已經(jīng)不想再往下分析下去了,擔(dān)心爬扒出更多沒(méi)想到的東西,不過(guò)辛苦爬了這么久,還是再往下看看吧。
看了首尾,我們?cè)倏纯凑w,了解一下全部 App 的安裝數(shù)量分布,這里去除了有很大水分的前十名 App。
很驚訝地發(fā)現(xiàn),竟然有 多達(dá) 67,195 款,占總數(shù)的 94% 的 App 的安裝量不足 1萬(wàn)!
如果這個(gè)網(wǎng)站的所有數(shù)據(jù)都是真的話,那么上面排名第一的手機(jī)管家,它一款就差不多抵得上這 6 萬(wàn)多款 App 的安裝量!
對(duì)于多數(shù) App 開(kāi)發(fā)者,只能說(shuō):現(xiàn)實(shí)很殘酷,辛辛苦苦開(kāi)發(fā)出來(lái)的 App,用戶不超過(guò) 1萬(wàn)人的可能性高達(dá)近 95%。
代碼實(shí)現(xiàn)如下:
1def analysis_distribution(data): 2 data = data.loc[10:,:] 3 data['install_count'] = data['install_count'].apply(lambda x:x/10000) 4 bins = [0,1,10,100,1000,10000] 5 group_names = ['1萬(wàn)以下','1-10萬(wàn)','10-100萬(wàn)','100-1000萬(wàn)','1000萬(wàn)-1億'] 6 cats = pd.cut(data['install_count'],bins,labels=group_names) 7 cats = pd.value_counts(cats) 8 bar = Bar('App 下載數(shù)量分布','高達(dá) 94% 的 App 下載量低于1萬(wàn)') 9 bar.use_theme('macarons')10 bar.add(11 'App 數(shù)量',12 list(cats.index),13 list(cats.values),14 is_label_show = True,15 xaxis_interval = 0,16 is_splitline_show = 0,17 )18 bar.render(path='App下載數(shù)量分布.png',pixel_ration=1)
下面,我們來(lái)看看各分類(lèi)下的 App 情況,不再看安裝量,而看數(shù)量,以排出干擾。
可以看到 14 個(gè)大分類(lèi)中,每個(gè)分類(lèi)的 App 數(shù)量差距都不大,數(shù)量最多的「生活休閑」是「攝影圖像」的兩倍多一點(diǎn)。
接著,我們進(jìn)一步看看 88 個(gè)子分類(lèi)的 App 數(shù)量情況,篩選出數(shù)量最多和最少的 10 個(gè)子類(lèi):
可以發(fā)現(xiàn)兩點(diǎn)有意思的現(xiàn)象:
「收音機(jī)」類(lèi)別 App 數(shù)量最多,達(dá)到 1,300 多款
這個(gè)很意外,當(dāng)下收音機(jī)完全可以說(shuō)是個(gè)老古董了,居然還有那么人去開(kāi)發(fā)。
App 子類(lèi)數(shù)量差距較大
最多的「收音機(jī)」是最少的「動(dòng)態(tài)壁紙」近 20 倍,如果我是一個(gè) App 開(kāi)發(fā)者,那我更愿意去嘗試開(kāi)發(fā)些小眾類(lèi)的 App,競(jìng)爭(zhēng)小一點(diǎn),比如:「背單詞」、「小兒百科」這些。
看完了總體和分類(lèi)情況,突然想到一個(gè)問(wèn)題:這么多 App,有沒(méi)有重名的呢?
驚奇地發(fā)現(xiàn),叫「一鍵鎖屏」的 App 多達(dá) 40 款,這個(gè)功能 App 很難再想出別的名字了么? 現(xiàn)在很多手機(jī)都支持觸控鎖屏了,比一鍵鎖屏操作更加方便。
接下來(lái),我們簡(jiǎn)單對(duì)比下豌豆莢和酷安兩個(gè)網(wǎng)站的 App 情況。
二者最直觀的一個(gè)區(qū)別是在 App 數(shù)量上,豌豆莢擁有絕對(duì)的優(yōu)勢(shì),達(dá)到了酷安的十倍之多,那么我們自然感興趣:
豌豆莢是否包括了酷安上所有的 App ?
如果是,「你有的我都有,你沒(méi)有的我也有」,那么酷安就沒(méi)什么優(yōu)勢(shì)了。統(tǒng)計(jì)之后,發(fā)現(xiàn)豌豆莢 僅包括了 3,018 款,也就是一半左右,剩下的另一半則沒(méi)有包括。
這里面固然存在兩個(gè)平臺(tái)上 App 名稱(chēng)不一致的現(xiàn)象,但更有理由相信 酷安很多小眾的精品 App 是獨(dú)有的,豌豆莢里并沒(méi)有。
代碼實(shí)現(xiàn)如下:
1include = data3.shape[0] 2notinclude = data2.shape[0] - data3.shape[0] 3sizes= [include,notinclude] 4labels = [u'包含',u'不包含'] 5explode = [0,0.05] 6plt.pie( 7 sizes, 8 autopct = '%.1f%%', 9 labels = labels,10 colors = [colorline,'#7FC161'], # 豌豆莢綠11 shadow = False,12 startangle = 90,13 explode = explode,14 textprops = {'fontsize':14,'color':colors}15)16plt.title('豌豆莢僅包括酷安上一半的 App 數(shù)量',color=colorline,fontsize=16)17plt.axis('equal')18plt.axis('off')19plt.tight_layout()20plt.savefig('包含不保包含對(duì)比.png',dpi=200)21plt.show()
Python資源分享qun 784758214 ,內(nèi)有安裝包,PDF,學(xué)習(xí)視頻,這里是Python學(xué)習(xí)者的聚集地,零基礎(chǔ),進(jìn)階,都?xì)g迎
接下來(lái),我們看看所包含的 App 當(dāng)中,在兩個(gè)平臺(tái)上的下載量是怎么樣的:
可以看到,兩個(gè)平臺(tái)上 App 下載數(shù)量差距還是很明顯。
最后,我面再看看豌豆莢上沒(méi)有包括哪些APP:
發(fā)現(xiàn)很多神器都沒(méi)有包括,比如:RE、綠色守護(hù)、一個(gè)木函等等。豌豆莢和酷安的對(duì)比就到這里,如果用一句話來(lái)總結(jié),我可能會(huì)說(shuō):
豌豆莢太牛逼了, App 數(shù)量是酷安的十倍,所以我選酷安。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。