NodeJs结合数据可视化展示地铁客流量变化

1,131 阅读3分钟

起初是这样考虑的,虽然我们经常坐地铁通勤的同学能够直接的感受到地铁人多人少的变化,但是当这一变化形成可视化之后看起来是很恐怖的一件事。

上海三月份开始受疫情影响,地铁客流量断崖式下跌。要知道2月25号上海的地铁客流量达到1255.7万人,到3月8号的1036.5万,到3月12号降到325万。(数据来源:上海地铁shmetro)

我们要做的就是根据上海地铁shmetro的客流量数据形成一个折线图,体现近半年来地铁客流量的变化。

首先我们要获取每日客流量的数据,在全网范围内找了半天,发现每天公布客流量数据的只有上海地铁的官方微博,那么我们就要去找他的微博内容,要在微博内容中筛选出是客流量相关的博文,然后提取博文中的数据入库。

我们分析一下微博页面,发现通过接口weibo.com/ajax/status… 可以获取指定博主的博文列表。

尝试了一下发现获取到的内容太多,每天发布的博文几十条,大量的数据我们都用不到。我们只要找到类似 【地铁网络客流】7月11日上海地铁总客流为777.6万人次。 这样样的内容即可。

通过对博文分析,我们找出博文的关键词地铁网络客流、上海地铁总客流,两个关键词足以提取内容了。

使用微博的搜索接口 https://weibo.com/ajax/profile/searchblog

这里会用到三个参数

uid: '1742987497',  // 微博ID
page: 0// 内容分页
q: '【地铁网络客流】'  // 关键词

用到curl请求接口获取数据

let res = await this.ctx.curl('https://weibo.com/ajax/profile/searchblog', {
      headers: {
        cookie: '你的微博cookie'
       },
      dataType: 'json',
      method: 'get',
      data: {
        uid: '1742987497',
        feature: 0,
        page: page ? page : 0,
        q: '【地铁网络客流】'
      }
    })
    if (res.data.ok === 1) {
      this.handleData(res.data.data.list)
    } 
    return false

我们获取到数据后在handleData方法中进行提取,

由于我们获取到的数据是list,需要先进行遍历,然后通过遍历提取每一条的内容,通过正则表达式提取内容中的数据。

每一条的内容大概是这样【地铁网络客流】7月11日上海地铁总客流为777.6万人次

提取到的数据大概是这样 [7, 11, 777.6]

handleData (res) {
      res&&res.forEach(element => {
        if (element.text.includes('上海地铁总客流')) { // 这里加判断的原因是搜索到的内容不一定是说客流量数据的 ‍
          const reg= /(\d+(\.\d+)?)/g
          const arrStr = element.text.match(reg)
          const data = {
            metro_city:310000, // 这里加了城市编号是因为还做了其他城市的
            number: arrStr[2],
            day_str: `${arrStr[0]}${arrStr[1]}日`,
            city_name: '上海'
          }
          this.insert‍‍Data(data)  // 入库操作,
        }
      });
  }

相比获取到数据之后入库操作就很简单了,就不贴代码了。

可视化

我们用到了 @antv/g2

// 安装
cnpm install @antv/g2
//引入
import { Chart } from '@antv/g2'

Chart的基础配置 ChartCfg

container: chartRef.current,
autoFit: true,
height: 700,
padding: [30, 30, 50, 70]

创建 Chart 图表对象

const chart = new Chart(ChartCfg);

绑定数据,假设我们拿到的数据如下:

data = [
  {  
    city_name: "上海",
     day_no: 1642025212000,
     day_str: "1月12日",
     metro_city: "310000",
     number: 1168.1
  }
  ......
]

绑定数据调用方法为chart.data

chart.data(data)‍

格式化展示方式

 chart.scale({
        number: {
          formatter: (value) => {
            return value + '万';
          },
        },
      });

设置图表属性

chart.line()
     .position('day_str*number')
     .color('city_name')
     .shape('smooth');

渲染图表

chart.render()

如图:

WX20220712-103312@2x.png

目前收集了三个城市的地铁客流量,后面有时间了再扩展其他的城市

未解决问题:

因为微博API需要登录,微博cookie失效未重新登录问题。

线上地址:

www.ctoku.com/metro