先上两张图:
十一热门景点前10景点分布(mark点标注)
样本数据间的方差貌似有点大。。点与点之间的差别确实有点大。。
本不是搞统计学或者数据挖掘的,只是一个不称职的小前端,所以请忽略下文中不严谨的统计方法:)
1500个热门景点的分布图(有的点确实很小..)
前几天就在简书上看到一篇关于十一黄金周旅游热点分布的爬虫+数据可视化的文章,一时兴趣,觉得学了一段时间爬虫了自己也可以做,所以就花了点时间做了这个项目。爬虫用的是python+scrapy框架,数据库存储使用的mongodb,数据可视化用的是js+echarts。
首先,我们需要获取数据,选取某哪儿旅游网站作为爬取对象,经过一顿分析后开始动手写爬虫代码,说实话这个网站的页面结构比较规整,爬起来也比较方便顺手。。分析获取下一页链接的方法(好几种方法,也可以用selenium)。
try:
current_page = selector.xpath('//div[@id="pager-container"]/div/em/text()').extract()[0]
except:
return
yield Request(url='http://piao.qunar.com/ticket/list.htm?keyword=%E4%B8%AD%E5%9B%BD&page='+str(int(current_page)+1),callback=self.parse)
选取的范围是爬虫热门景点的前100页,每个页面15个,共1500个景点。爬取的数据存放到本地的mongodb中。业务逻辑很简单,代码就没有必要再贴上来了。。。爬虫成果:
爬到数据后就是数据可视化的过程了。之前写过一两个echarts的页面,所以写起来也比较快了。首先可以先做一个热门景点的排行情况的图,参考的指标是网站中每个景点的售出票的数量,然后进行排序,将mongodb中的数据处理成“景点名-xxx,售票数量-xxx”这样的对应关系如下图:
之后就是对echarts的的配置项进行设置,筛选出前20名的热门景点。配置项series如下
series : [
{
"name":"热门景点排行榜",
"type":"bar",
"data":data.sort(function(a,b){
return b.value-a.value
}).slice(0,21).sort(function(a,b){
return a.value-b.value
}),
itemStyle : { normal: {label : {show: true,position: 'right',fontSize:18}}}
}
]
先来一个条形图:
条形图比较直观的反映出排行的情况。
再从另外一个角度分析下,来看看每个省份的热门景点各有多少。简单的进行处理数据,然后用条形图展示:
可以看到排名前三的分别是四川、陕西和福建。
同样的处理方法,我们也可以对城市的热门景点进行统计,统计结果如下:
如果不考虑统计学原理,只为了好玩,还可以将这前10名的信息汇总成饼状图:
热门景点最多的省份-广东。
家乡河南热门景点有63个:)
热门景点最多的城市-北京。
郑州居然有16个热门景点。。没想到
再就是开头的那两张图了,之前公司做过类似姓氏迁徙的echarts图表(迁徙的图比单纯的地图分布的图表要复杂的多。。还要考虑数据量大影响渲染性能的问题,跟着公司大牛学了不少),配置项熟悉了后,进行配置。
地图除了每个点及点对应的值,还需要点对应的坐标,所以我们需要两组数据,一组是值得集合,一种是坐标的集合。值的集合:
var data = [{
"name": "稻城亚丁",
"value": 17857
}, {
"name": "秦始皇陵博物院(兵马俑)",
"value": 12571
}, {
"name": "鼓浪屿",
"value": 4346
}, {
"name": "天门山国家森林公园",
"value": 4145
},
坐标的集合:
var geoCoordMap = {
"稻城亚丁": [100.324691, 28.540034],
"秦始皇陵博物院(兵马俑)": [109.266029, 34.386024],
"鼓浪屿": [118.073486, 24.452261],
"天门山国家森林公园": [110.482089, 29.072408],
"颐和园": [116.276887, 39.999497],
"故宫": [116.403347, 39.922148],
"八达岭长城": [116.03293, 40.369733],
"布达拉宫": [91.125491, 29.660076],
"长隆野生动物世界": [113.335765, 23.0003],
"黄山风景区": [118.193977, 30.097967],
"长隆水上乐园": [113.331236, 23.005835],
...
地图的配置:
var convertData = function (data) {
var res = [];
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name];
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value)
});
}
}
return res;
};
option = {
backgroundColor: '#404a59',
title: {
text: '十一黄金周热门旅游景点分布图',
left: 'center',
top:50,
textStyle: {
color: '#fff',
fontSize:24
}
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
y: 'bottom',
x: 'right',
data: ['pm2.5'],
textStyle: {
color: '#fff'
}
},
geo: {
map: 'china',
label: {
emphasis: {
show: false
}
},
roam: true,
itemStyle: {
normal: {
areaColor: '#323c48',
borderColor: '#111'
},
emphasis: {
areaColor: '#2a333d'
}
}
},
tooltip:{
trigger: 'item',
formatter:function(params) { //自定义tooltip
console.log(params)
var res = params.name+'<br/>';
var myseries = option.series;
for(var j=0;j<myseries[0].data.length;j++){
if(myseries[0].data[j].name==params.name){
res+='人气值' +' : '+myseries[0].data[j].value[2]+'</br>';
}
}
return res;
}
},
series: [{
name: '热门景点',
type: 'scatter',
coordinateSystem: 'geo',
data: convertData(data),
symbolSize: function (val) {
return val[2] / 600;
},
label: {
normal: {
formatter: '{b}',
position: 'down',
show: false
},
emphasis: {
show: true
}
},
itemStyle: {
normal: {
color: '#ddb926'
}
}
},
{
name: 'Top 10',
type: 'effectScatter',
coordinateSystem: 'geo',
data: convertData(data.sort(function (a, b) {
return b.value - a.value;
}).slice(0, 11)),
symbolSize: function (val) {
return val[2] / 600;
},
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
},
hoverAnimation: true,
label: {
normal: {
formatter: '{b}',
position: 'right',
show: false
}
},
itemStyle: {
normal: {
color: '#f4e925',
shadowBlur: 10,
shadowColor: '#333'
}
},
zlevel: 1
}
]
};
然后得到分布图:
以上就是所有可视化的展示内容。
后记:
断断续续学习python爬虫快两个月了,也写了几个爬虫的项目:91图片(大概2w多张)、腾讯公益《活着》活动的展示页(大概6k张图片)、天堂网(公司让爬的。。也不知道要这些数据有何用)大概2w多的有效用户信息、逼乎(水管太小,只爬了大概3w多的用户信息先作罢)、网易云音乐(爬接口爬了1w多用户)。现在简单的爬虫可以说是应付得来了,但是至于分布式队列,上redis那一套也只是试验了试验并没有深入的爬取,像redis上亿数据量去重优化(加布隆过滤器)这种技术点没有深入学习只是那别人的直接用(主要还是redis和内存优化这些之前都没接触过),究竟里边的坑有多深还不得而知,日后肯定要再继续学习。