數(shù)據(jù)可視化(五)基于網(wǎng)絡(luò)爬蟲制作可視化圖表

  • 基于網(wǎng)絡(luò)爬蟲的可視化圖表:golang,goquery
  • 案例:最近十年全國彩票銷售變化情況
  • 案例:中國科學(xué)院院士分布
  • 數(shù)據(jù)可視化技術(shù)方案:基于 SVG (D3昭躺、Raphael)、基于 Canvas(Echarts)

我們身處大數(shù)據(jù)時代毅哗,幾乎在所有工作例如商業(yè)技術(shù)撤卢、金融较幌、科研教育等行業(yè)弄兜,以及日常生活中都可能需要涉及數(shù)據(jù)分析活動。橫向來看數(shù)據(jù)分析的知識體系貫穿數(shù)據(jù)獲取正压、數(shù)據(jù)存儲欣福、數(shù)據(jù)分析、數(shù)據(jù)挖掘蔑匣、數(shù)據(jù)可視化等各大部分劣欢;按數(shù)據(jù)來源分棕诵,即可以是自己收集的數(shù)據(jù)裁良,也可以采購數(shù)據(jù)或者基于公開數(shù)據(jù)集凿将。

基于公開數(shù)據(jù)進(jìn)行分析的話,必須提到的就是網(wǎng)絡(luò)爬蟲(web crawler)价脾,也被稱作網(wǎng)絡(luò)蜘蛛(spider)牧抵、自動索引程序(automatic indexer),搜索引擎(Google侨把,百度等)就是大眾日常生活中接觸到的最典型犀变、最強(qiáng)大的爬蟲。

公開數(shù)據(jù)包括政府(統(tǒng)計局秋柄、央行获枝、銀監(jiān)會、證監(jiān)會等)骇笔、企業(yè)省店、社會組織和互聯(lián)網(wǎng)上的個人發(fā)布信息等。在浩如煙海的互聯(lián)網(wǎng)內(nèi)容中笨触,有價值信息猶如‘待字閨中’深藏的美女懦傍,等待有心人去挖掘。例如:

  • 案例:最近十年全國彩票銷售變化情況 在線演示
  • 案例:中國科學(xué)院院士分布(出生地與籍貫)在線演示
  • 案例:美國航空入境旅客(出發(fā)地)變化情況 在線演示
中科院院士分布情況|201801
全國彩票銷售情況

為了實現(xiàn)上述圖表芦劣,相關(guān)技術(shù)方案的要點(diǎn)如下:

  • 開發(fā)語言:
    基于 Golang 實現(xiàn)爬蟲基本功能粗俱,主要考慮 Go 語言 自身對于網(wǎng)絡(luò)方面的強(qiáng)大支持,語言級 Goroutines 提供并發(fā)高性能支持虚吟。
  • HTML選擇器: goquery jQuery-style HTML manipulation in Go
  • 數(shù)據(jù)存儲: csv,PostgreSQL
  • 數(shù)據(jù)可視化:ECharts
基于網(wǎng)絡(luò)爬蟲制作可視化圖表

案例

數(shù)據(jù)來源頁面:

數(shù)據(jù)來源-專題

數(shù)據(jù)來源-內(nèi)容

數(shù)據(jù)來源-翻頁
數(shù)據(jù)來源頁面-源代碼

數(shù)據(jù)來源頁面-源代碼
//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 編寫串慰,開源許可證允許個人用戶和非商業(yè)用途废麻。
  • Baidu ECharts:底層畫圖基于 Canvas, BSD 許可證協(xié)議。
  • Kartograph:構(gòu)建交互式地圖輕量級類庫模庐。
//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
    }]
};

最佳實踐

  • 默認(rèn)調(diào)色板(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
  • 優(yōu)化圖表JS生成模板
    圖表定型之后烛愧,可以通過模板固化配置,根據(jù)需要動態(tài)生成目標(biāo)文件(html,js,svg等等)掂碱,詳見基于 Markdown 的 HTML 網(wǎng)頁模板怜姿。

  • 優(yōu)化采集器 Goroutines "線程池"
    例如:PostgreSQL Exception: Open too many files

  • 優(yōu)化數(shù)據(jù)存儲
    例如:常用的 GIS 坐標(biāo)庫

擴(kuò)展閱讀:開源工具與案例

golang-based library

可視化圖表案例

可視化圖表技術(shù)方案

  • 基于 SVG : D3、Raphael

  • 基于 Canvas : Echarts

  • HighCharts
    國外開源產(chǎn)品疼燥,JavaScript 編寫沧卢,自帶主題、動態(tài)交互方便醉者,目前公司新版業(yè)務(wù)視圖但狭、地圖應(yīng)用披诗、交互式流量圖等是基于這個庫實現(xiàn)。
    不足:缺少中文文檔立磁,開源許可證只允許個人用戶和非商業(yè)用途呈队,規(guī)模應(yīng)用存在法律風(fēng)險。

  • Baidu ECharts
    最早源于百度各種業(yè)務(wù)系統(tǒng)報表需求唱歧,底層畫圖基于 Canvas 宪摧。2013年開源,完全免費(fèi)的BSD協(xié)議颅崩。
    特點(diǎn):拖拽重計算几于,第三方標(biāo)準(zhǔn)格式支持,中文社區(qū)支持
    實例:http://echarts.baidu.com/doc/example.html
    Github: https://github.com/ecomfe/echarts

  • Kartograph
    Kartograph 是個構(gòu)建交互式地圖的簡單沿后、輕量級類庫沿彭。它包含兩個庫,一個用Python寫的尖滚,用于產(chǎn)生漂亮和壓縮的SVG地圖喉刘,另一個是js類庫用于前端展示地圖用。

  • lchart(go-based)

擴(kuò)展閱讀:數(shù)據(jù)可視化

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末熔掺,一起剝皮案震驚了整個濱河市饱搏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌置逻,老刑警劉巖推沸,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異券坞,居然都是意外死亡鬓催,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門恨锚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宇驾,“玉大人,你說我怎么就攤上這事猴伶】紊幔” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵他挎,是天一觀的道長筝尾。 經(jīng)常有香客問我,道長办桨,這世上最難降的妖魔是什么筹淫? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮呢撞,結(jié)果婚禮上损姜,老公的妹妹穿的比我還像新娘饰剥。我一直安慰自己,他們只是感情好摧阅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布汰蓉。 她就那樣靜靜地躺著,像睡著了一般逸尖。 火紅的嫁衣襯著肌膚如雪古沥。 梳的紋絲不亂的頭發(fā)上瘸右,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天娇跟,我揣著相機(jī)與錄音,去河邊找鬼太颤。 笑死苞俘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的龄章。 我是一名探鬼主播吃谣,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼舀武,長吁一口氣:“原來是場噩夢啊……” “哼夏醉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起欠母,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤锚贱,失蹤者是張志新(化名)和其女友劉穎仔戈,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拧廊,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡监徘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吧碾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凰盔。...
    茶點(diǎn)故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖倦春,靈堂內(nèi)的尸體忽然破棺而出户敬,到底是詐尸還是另有隱情,我是刑警寧澤睁本,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布尿庐,位于F島的核電站,受9級特大地震影響添履,放射性物質(zhì)發(fā)生泄漏屁倔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一暮胧、第九天 我趴在偏房一處隱蔽的房頂上張望锐借。 院中可真熱鬧问麸,春花似錦、人聲如沸钞翔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽布轿。三九已至哮笆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間汰扭,已是汗流浹背稠肘。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萝毛,地道東北人项阴。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像笆包,于是被迫代替她去往敵國和親环揽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容