爬取手机靓号-看手机号到底有多好
阅读文本需要5分钟
前几天分享了如何使用pyecharts,但是只是用一些简单的数据,感觉有一点不真实。今天就来实战演练一下。从爬虫,到数据清洗,到数据库,最后可视化,带你完成这个练手小项目
1
使用的库
pyquery
MongoDB
pyecharts
highcharts
2
总体思路
在集号吧这个网站上有全国各地的待售手机靓号,比如以8888888结尾的手机号等。在这个网站上可以看到这些号码、售价、出售人的位置,以及运营商等信息。很适合练手,并且不用深入的去爬取。而且相对来说比较好爬。所以先爬取所有的信息下来,再进行数据的清洗,最后使用pyecharts进行数据的展示
(来自:http://www.jihaoba.com/escrow/)
3
爬取数据
通过观察,可以清楚的发现这个网站只要我们简单的拼接链接就可以进行访问例如下面的链接
http://www.jihaoba.com/escrow/?&page=1
http://www.jihaoba.com/escrow/?&page=2
所以直接进行爬取,并且上图的审查元素可以看出,各个信息都是在一个class
里面的,因此使用pyquery
进行爬取
代码:
1from pyquery import PyQuery as pq
2import pymongo
3import logging
4
5client = pymongo.MongoClient('localhost', 27017)
6jihaoba = client['jihaoba']
7detail = jihaoba['detail']
8
9
10header = {
11 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0',
12 'Connection': 'close'}
13
14# 获取数据,参数为页数
15def get_phone(page):
16 url = 'http://www.jihaoba.com/escrow/?&page={}'.format(page)
17 try:
18 web_data = pq(url=url, headers=header)
19 phone_lis = web_data('.numbershow')
20 for item in phone_lis.items():
21 phone = item.find('.number').text()
22 price = item.find('.price span').text()
23 brand = item.find('.brand').text()
24 law = item.find('.law').text()
25 data = {
26 'phone': phone,#手机号
27 'price': price[1:],#价格
28 'band': brand,#运营商
29 'law': law,#简介
30 }
31 print(data)
32 detail.insert(data)
33 except:
34 logging.warning('连接的主机没有反应')
35 pass
因为这个网站的反爬措施做得不是很好,所以不需要使用很多的技巧去突破反爬,但是如果爬取速度过快还是会出现连接不上的情况,所以我这里直接pass跳过。
代码:
1if __name__ == '__main__':
2 pool = Pool()
3 pool.map(get_phone, [i for i in range(1, 1001)])
上面的主函数使用了多进程来提高效率
4
数据可视化
爬取数据只是第一步,接下来就要对数据进行处理展示了。从mongodb 中查找出数据,对数据进行清洗整理,然后使用pyecharts进行展示
1. 运营商占比
1import pymongo
2import charts
3import re
4from collections import Counter
5
6client = pymongo.MongoClient('localhost',27017)
7jihaoba = client['pyquery_jihaoba']
8detail = jihaoba['detail']
9#清洗运营商数据
10operator=[]
11for item in detail.find():
12 fir = item['band'][-2:]#获取运营商
13 sec = re.sub(r'\d+',"未知",fir)#将70 替换为"未知"
14 operator.append(sec)
15
16#字典化
17count_oprator = Counter(operator)
18dict_oprator = dict(count_oprator)
19print(dict_oprator)
20#highecharts展示
21option={
22 'chart':{'zoomType':'xy'},
23 'title':{'text':'运营商占比'},
24 'subtitle':{'text':'数据来源:集号吧'},
25 'plotOptions':{'column':{'dataLabels':{'enabled':True}}}, #设置数值可见
26}
27series = []
28for i in dict_oprator:
29 data ={
30 'name':i,
31 'type' :'column',
32 'data':[dict_oprator[i]]
33 }
34 series.append(data)
35charts.plot(series,options = option,show ='inline')
因为只有x轴只有4个有点少,用highcharts
做出的图会比较好看一点。在运行jupyter中运行后,可以看到下面的运营商的数据了
2.地理位置分布
通过处理归属地信息,获取到省份信息,进行统计展示
1addr=[]
2for item in detail.find():
3 addr.append(item['band'][:-2])#获取地点位置
4real_add=[]
5
6#因为包含"深圳170"这样的数据,所以进行处理,将数字替换掉
7for i in addr:
8 item = re.sub(r'\d','',i)
9 real_add.append(item)
10
11#展示
12data = dict_add
13geo = Geo("靓号分布图", "数据来自:集号吧", title_color="#fff",
14 title_pos="center", width=1000,
15 height=600, background_color='#404a59')
16attr, value = geo.cast(data)
17geo.add("", attr, value, visual_range=[0, 200], maptype='china',visual_text_color="#fff",
18 symbol_size=10, is_visualmap=True)
19geo#直接在notebook中显示
运行之后可以看到下面的经济分布图
(经济分布图)
3.价格前十的手机号码
因为有一些价格没有直接显示出来,而是说需要面议,所以将这些价格设置为零,然后将包含"万"的转换为乘10000,统一格式,方便比较
1
2def convert_price(str_price):
3 if str_price.find('万') > 0:
4 price = str_price[:-1]
5 price = float(price)
6 price = math.ceil(price * 10000)
7 return price
8 elif str_price =='电议':
9 return int(0)
10 else:
11 return math.ceil(float(str_price))
12
13price_dict = {}
14high_price = []
15for item in detail.find():
16 price = convert_price(item['price'])
17 key = item['phone']
18 value = price
19 price_dict[key] = value
20price_list = sorted(price_dict.items(), key=lambda x: x[1])
21high_price = price_list[-10:]
22
23
24price_list = []
25for i in high_price:
26 price_list.append(i[-1])
27price_list = list(reversed(price_list))
28
29x_axis =[]
30for i in high_price:
31 x_axis.append(i[0])
32x_axis = list(reversed(x_axis))
33
34bar = Bar("高价格前十表", "author:stormdony")
35bar.add("手机号", x_axis,price_list, mark_line=["min", "max"],mark_point=["average"],xaxis_interval=0,xaxis_rotate=-30,is_more_utils=True)
36bar
4.统计出现频率最高的数字
将手机号码的首位1去掉,然后统计出现最高频率的数字
1from collections import Counter
2# 统计出现频率最高的数字
3phone_list = ''
4num_dict={}
5for item in detail.find():
6 phone_list += (item['phone'][1:])
7num_dict = dict(Counter(phone_list))
8num_dict.pop('X')#删除“X”
9# print(num_dict)#字典化
10num_list = list(num_dict.keys())
11val_list = list(num_dict.values())
12
13bar = Bar("0-9出现频率最高统计图", "author:stormdony")
14bar.add("0-9频率", num_list,val_list, mark_line=["min", "max"],mark_point=["average"],xaxis_interval=0,xaxis_rotate=0,is_more_utils=True)
15bar
从这张图数字8出现的频率是最高的,数字4出现的频率是最低的。看来中国还是比较注重谐音
5
最后
这个demo在现实中的意义并不是很大,只是一个小的练手项目罢了。
最后厚着脸皮说一句:原创不易,请随手点赞、分享哈
推荐阅读