数据可视化(五)基于网络爬虫制作可视化图表

  • 基于网络爬虫的可视化图表:golang,goquery
  • 案例:最近十年全国彩票销售变化情况
  • 案例:中国科学院院士分布
  • 数据可视化技术方案:基于 SVG (D3、Raphael)、基于 Canvas(Echarts)

我们身处大数据时代,几乎在所有工作例如商业技术、金融、科研教育等行业,以及日常生活中都可能需要涉及数据分析活动。横向来看数据分析的知识体系贯穿数据获取、数据存储、数据分析、数据挖掘、数据可视化等各大部分;按数据来源分,即可以是自己收集的数据,也可以采购数据或者基于公开数据集。

基于公开数据进行分析的话,必须提到的就是网络爬虫(web crawler),也被称作网络蜘蛛(spider)、自动索引程序(automatic indexer),搜索引擎(Google,百度等)就是大众日常生活中接触到的最典型、最强大的爬虫。

公开数据包括政府(统计局、央行、银监会、证监会等)、企业、社会组织和互联网上的个人发布信息等。在浩如烟海的互联网内容中,有价值信息犹如‘待字闺中’深藏的美女,等待有心人去挖掘。例如:

  • 案例:最近十年全国彩票销售变化情况 在线演示
  • 案例:中国科学院院士分布(出生地与籍贯)在线演示
  • 案例:美国航空入境旅客(出发地)变化情况 在线演示
中科院院士分布情况|201801
全国彩票销售情况

为了实现上述图表,相关技术方案的要点如下:

  • 开发语言:
    基于 Golang 实现爬虫基本功能,主要考虑 Go 语言 自身对于网络方面的强大支持,语言级 Goroutines 提供并发高性能支持。
  • HTML选择器: goquery jQuery-style HTML manipulation in Go
  • 数据存储: csv,PostgreSQL
  • 数据可视化:ECharts
基于网络爬虫制作可视化图表

案例

数据来源页面:

数据来源-专题

数据来源-内容

数据来源-翻页
数据来源页面-源代码

数据来源页面-源代码
//caipiao_task.go

func Handle_GMOF_CaiPiao_Month_BatchTask() {
    data := read_csv_caipiao("./data/caipiao_list.csv", ",")
    if data != nil {
        for i := range data {
            go Handle_GMOF_CaiPiao_Month_Task(url)
        }
        <-time.After(60 * time.Second)
    }
}

func Handle_GMOF_CaiPiao_Month_Task(url string) {
    if url != "" {
        myspider := init_GMOF_CaiPiao_Month_HTMLSpider(url)
        ctx, _ := myspider.Setup(nil)
        myspider.Spin(ctx)
    }
}

//caipiao_spider.go
package main

import (
    "log"
    "regexp"
    "strings"

    "github.com/PuerkitoBio/goquery"
    "github.com/celrenheit/spider"
)

type GMOF_CaiPiao_Month_HTMLSpider struct {
    title string `json:"title"`
    url   string `json:"url"`
    desc  string `json:"desc"`
}

func init_GMOF_CaiPiao_Month_HTMLSpider(url string) *GMOF_CaiPiao_Month_HTMLSpider {
    spider := NewGMOF_CaiPiao_Month_HTMLSpider()
    spider.url = url
    return spider
}

func (w *GMOF_CaiPiao_Month_HTMLSpider) Setup(ctx *spider.Context) (*spider.Context, error) {
    return spider.NewHTTPContext("GET", w.url, nil)
}

func (w *GMOF_CaiPiao_Month_HTMLSpider) Spin(ctx *spider.Context) error {
    if _, err := ctx.DoRequest(); err != nil {
        return err
    }

    html, err := ctx.HTMLParser()
    if err != nil {
        return err
    }

    caipiao := NewGMOF_CaiPiao_Month()

    //<title></title>
    caipiao.Title = html.Find("title").Eq(0).Text()
    caipiao.Title = Convert2String(caipiao.Title, GB18030)
    //class="TRS_Editor"
    html.Find(".TRS_Editor").Each(func(i int, s *goquery.Selection) {
        content := s.Find("p").Text()
        caipiao.Content = content

        if content != "" {
            content = Convert2String(content, GB18030)
            rows := strings.Split(content, "。")

            for _, value := range rows {
                //fmt.Printf("======arr[%d]=\n [%s] \n", index, value)
                if strings.Index(value, "全国彩票") > 0 {
                    reg := regexp.MustCompile(`全国共销售彩票([\d]+.[\d]+)\S+`)
                    result := reg.FindStringSubmatch(value)
                    if len(result) > 0 {
                        caipiao.Total = result[1]
                    }
                }
            }
        }
    })

    //id="appendix"
    html.Find("#appendix").Each(func(i int, s *goquery.Selection) {
        href, _ := s.Find("a").Eq(0).Attr("href") //附件
        caipiao.Attachid = href
    })

    //===== export data
    save_csv("./data/caipiao_result.csv", caipiao)
    return err
}

2017年11月份全国彩票销售情况,385.55
2017年10月份全国彩票销售情况,376.53
2017年9月份全国彩票销售情况,369.28
2017年8月份全国彩票销售情况,350.67
2017年7月份全国彩票销售情况,337.55
2017年6月份全国彩票销售情况,338.42

可视化图表:以 ECharts 为例

常见的图表库,本文案例使用 ECharts 作为图表组件

  • HighCharts:JavaScript 编写,开源许可证允许个人用户和非商业用途。
  • Baidu ECharts:底层画图基于 Canvas, BSD 许可证协议。
  • Kartograph:构建交互式地图轻量级类库。
//http://echarts.baidu.com/demo.html#line-gradient
data = [["2017年11月",385.55],["2017年10月",376.53],["2017年9月",369.28],["2017年8月",350.67],["2017年7月",337.55],["2017年6月",338.42],["2017年11月",385.55],["2017年10月",376.53],["2017年9月",369.28],["2017年8月",350.67],["2017年7月",337.55],["2017年6月",338.42],["2017年11月",385.55],["2017年10月",376.53],["2017年9月",369.28],["2017年8月",350.67],["2017年7月",337.55],["2017年6月",338.42],["2017年5月",376.95],["2017年4月",382.45],["2017年3月",379.33],["2017年2月",0],["2017年1月",291.61],["2016年12月",365.94],["2016年11月",344.82],["2016年10月",338.27],["2016年9月",320.71],["2016年8月",310.12],["2016年7月",324.03],["2016年6月",339.61],["2016年5月",346.19],["2016年4月",348.89],["2016年3月",356.88],["2016年2月",224.54],["2016年1月",326.41],["2015年12月",341.21],["2015年11月",306.30],["2015年10月",312.34],["2015年9月",290.78],["2015年8月",280.96],["2015年7月",270.47],["2015年6月",281.2371],["2015年5月",321.07],["2015年5月",321.07],["2015年4月",326.12],["2015年3月",308.12],["2015年2月",247.90],["2015年1月",392.33],["2014年12月",361.53],["2014年11月",341.18],["2014年10月",327.01],["2014年9月",322.52],["2014年8月",315.36],["2014年7月",372.09],["2014年6月",360.54],["2014年5月",307.94],["2014年4月",315.29],["2014年3月",328.74],["2014年2月",200.1],["2014年1月",271.49],["2013年12月",302.73],["2013年11月",274.16],["2013年10月",271.83],["2013年9月",257.62],["2013年8月",246.18],["2013年7月",243.65],["2013年6月",247.46],["2013年5月",273.41],["2013年4月",285.61],["2013年3月",273.37],["2013年2月",168.65],["2013年1月",248.59],["2012年12月",268.01],["2012年11月",237.06],["2012年10月",215.38],["2012年9月",205.12],["2012年8月",197.12],["2012年7月",201.98],["2012年6月",216.14],["2012年5月",236.16],["2012年4月",235.76],["2012年3月",235.79],["2012年2月",202.17],["2012年1月",164.54],["2011年12月",224.80],["2011年11月",210.08],["2011年10月",203.28],["2011年9月",196.44],["2011年8月",187.72],["2011年7月",182.05],["2011年6月",174.53],["2011年5月",187.28],["2011年3月",190.12],["2011年2月",112.92],["2011年1月",160.09],["2010年12月",171.89],["2010年11月",160.24],["2010年10月",149.95],["2010年9月",139.56],["2011年4月",186.50],["2010年8月",135.75],["2010年7月",132.74],["2010年6月",140.71],["2010年5月",144.38],["2010年4月",141.05],["2010年3月",132.52],["2010年2月",86.71],["2010年1月",126.99],["2009年12月",133.30],["2009年11月",117.05],["2009年10月",116.47],["2009年9月",111.73],["2009年8月",110.64],["2009年7月",107.87],["2009年6月",113.51],["2009年5月",121.59],["2009年4月",114.61],["2009年3月",114.49],["2009年2月",89.21],["2009年1月",74.33],["2008年12月",102.07],["2008年11月",94.09],["2008年10月",79.88],["2008年8月",84.66]];
var dateList = data.map(function (item) {
    return item[0];
});
var valueList = data.map(function (item) {
    return item[1];
});

option = {
    // Make gradient line here
    visualMap: [{
        show: false,
        type: 'continuous',
        seriesIndex: 0,
        min: 0,
        max: 400
    }, {
        show: false,
        type: 'continuous',
        seriesIndex: 1,
        dimension: 0,
        min: 0,
        max: dateList.length - 1
    }],
    title: [{
        left: 'center',
        text: 'Gradient along the y axis'
    }, {
        top: '55%',
        left: 'center',
        text: 'Gradient along the x axis'
    }],
    tooltip: {
        trigger: 'axis'
    },
    xAxis: [{
        data: dateList
    }, {
        data: dateList,
        gridIndex: 1
    }],
    yAxis: [{
        splitLine: {show: false}
    }, {
        splitLine: {show: false},
        gridIndex: 1
    }],
    grid: [{
        bottom: '60%'
    }, {
        top: '60%'
    }],
    series: [{
        type: 'line',
        showSymbol: false,
        data: valueList
    }, {
        type: 'line',
        showSymbol: false,
        data: valueList,
        xAxisIndex: 1,
        yAxisIndex: 1
    }]
};

最佳实践

  • 默认调色板(palette)
    [图片上传失败...(image-835cce-1515641952307)]
Navy    — #001f3f
Blue    — #0074d9
Aqua    — #7fdbff
Teal    — #39cccc
Olive   — #3d9970
Green   — #2ecc40
Lime    — #01ff70
Yellow  — #ffdc00
Orange  — #ff851b
Red     — #ff4136
Maroon  — #85144b
Fuchsia — #f012be
Purple  — #b10dc9
Black   — #111111
Gray    — #aaaaaa
Silver  — #dddddd
White   — #ffffff
  • 优化图表JS生成模板
    图表定型之后,可以通过模板固化配置,根据需要动态生成目标文件(html,js,svg等等),详见基于 Markdown 的 HTML 网页模板

  • 优化采集器 Goroutines "线程池"
    例如:PostgreSQL Exception: Open too many files

  • 优化数据存储
    例如:常用的 GIS 坐标库

扩展阅读:开源工具与案例

golang-based library

可视化图表案例

可视化图表技术方案

  • 基于 SVG : D3、Raphael

  • 基于 Canvas : Echarts

  • HighCharts
    国外开源产品,JavaScript 编写,自带主题、动态交互方便,目前公司新版业务视图、地图应用、交互式流量图等是基于这个库实现。
    不足:缺少中文文档,开源许可证只允许个人用户和非商业用途,规模应用存在法律风险。

  • Baidu ECharts
    最早源于百度各种业务系统报表需求,底层画图基于 Canvas 。2013年开源,完全免费的BSD协议。
    特点:拖拽重计算,第三方标准格式支持,中文社区支持
    实例:http://echarts.baidu.com/doc/example.html
    Github: https://github.com/ecomfe/echarts

  • Kartograph
    Kartograph 是个构建交互式地图的简单、轻量级类库。它包含两个库,一个用Python写的,用于产生漂亮和压缩的SVG地图,另一个是js类库用于前端展示地图用。

  • lchart(go-based)

扩展阅读:数据可视化

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

推荐阅读更多精彩内容