爬虫简单分析十一热门旅游景点分布

先上两张图:

十一热门景点前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和内存优化这些之前都没接触过),究竟里边的坑有多深还不得而知,日后肯定要再继续学习。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容