分享

利用FME实现城市高德路况抓取及增量更新——以深圳为例

 南柯一梦350 2019-04-30

参赛单元:互联网、大数据及云计算

 

 

前言

继续我的【零编码】系列。

简单是美。虽为“码农”,但本身还是个GISer,所以在进行数据处理,尤其是GIS数据时,我更喜欢使用少量甚至零编码来实现。方法千万条,简单第一条,而FME无疑为我提供了这样的便利。简单、高效、实用而不失优雅。可以说我大部分的数据处理工作基本都是利用FME完成的。

前段时间有个搞城市研究的朋友需要对城市大尺度范围内的路网通行效率进行研究,他对高德的路况数据垂涎三尺,但苦于不好下手。见猎心喜,一时技痒,心想何不利用FME来实现一个呢。

说到爬虫,无非是获取,解析(处理),入库(存储)三部曲。高德路况的获取流程也不外如是,不同的只是工具。而我偏爱于FME,首选的自然是它。既能少量甚至零编码,效率还贼高,何乐而不用呢。

由于本人是在深圳工作,恰巧朋友关注的也是深圳路况,就拿深圳做案例。下面正式进入主题。

一、总体流程

工作总体流程大体上分准备、建模、入库及优化四个阶段。

准备阶段主要是做一些基础准备工作,以便后续阶段的顺利进行。

建模阶段主要是根据高德API参数来划分网格,然后进行Http数据请求,最后根据数据结构来进行数据解析。

入库阶段主要定义最小增量更新单元,最后进行数据入库。

优化阶段主要是就存储、数据请求以及解析三个方面进行优化提升处理。

二、准备工作

2.1 申请Key

在使用高德路况API前您需先申请Key,若无高德地图API账号需要先申请账号。高德API网站上有详细说明,不多说。

2.2 深圳边界数据

准备深圳的边界数据,如为Polyline类型,最好是先转换成Polygon类型,以方便进行空间分析(过滤);同时,坐标需要转换为高德地图使用的GCJ02坐标。本文默认边界数据为Polygon类型,并且为GCJ02坐标,不多做处理。

2.3 建立空间数据库

本文使用的是PostgreSQL数据库,9.5及以上版本即可。在PostgreSQL建立名为traffic_status的数据库,并添加扩展postgis。

三、建立模型

3.1 模型参数

老规矩,开始前先确定模型参数。

  • Url:通过矩形区域获取交通态势。
  • Key:申请的高德Web服务API类型Key。
  • Size:因高德API规定矩形对角线不能超过10公里,按照1°约111千米计算,可设置网格的大小不超过0.0637°。当然也不能设置太小,太小会造成过多请求,降低效率。
  • Level:道路等级,设置为6是获取所有类型道路的路况。具体参考API参数说明。

3.2 划分网格

① 用2DGridAccumulator对边界数据创建m×n的网格,当Size设定为0.0637°时,有98个。

② 用SpatialFilter过滤深圳境外的网格,以减少不必要的API请求,提高解析效率,过滤后剩71个,减少量将近30%,如图3-3所示。

3.3 路况获取

① 用BoundsExtractor提取每个网格的四至坐标参数,从而拼接成rectangle请求参数。

② 用HTTPCaller进行数据请求。值得一提的是,一定要把extensions参数设为all,否则请求下来的只是一些基本的数据,也就没后面什么事了。

3.4 路况解析

① 用JSONFragmenter解析返回的json,选择需要暴露(保留)的字段。

② 用DuplicateFilter去除重复项,字段选polyline。

③ 结合AttributeSplitterListExploder对polyline字段进行分解、炸开、再分解,以获取polyline的节点坐标。关于polyline坐标样式具体可参考API说明。

④ 用VertexCreator创建polyline节点,Mode一定要选用Replace with Point,即用点来替换原来的网格。

⑤ 用LineBuilder构建路段,注意要使用polyline来进行分段。

3.5 路况可视化

FeatureColorSetter根据不同路况给路段赋以红、黄、绿、灰等颜色,非必要步骤,仅为可视化及查看数据所用。

3.6 工作流程

至此,一次路况获取、解析并可视化的完整流程如下:

四、增量更新

所谓增量更新,当然是有变化才更新,不变化不更新。这里变化的主要就是路况和因道路动态分段而引起的路段(即上面提到的polyline字段)变化。而路况一直都是在变化的,反正都要存,也谈不上增量不增量的。唯一要考虑的就是路段。

观察不同时刻,高德返回来的路段总量是不完全一样的,这里的总量不单单指路段的总数,还包括了路段的总长度。为了能获取全量的道路数据,而又不想耗费大量的空间来存储路段数据,这里考虑使用增量更新。

4.1 增量更新时间

既然要更新,当然离不开时间标签。为了统一数据获取时间,我把DateTimeStamper放在流程最开始的地方。

4.2 定义最小单元

据我观察,高德路况的道路节点的固定不变的。也就是说,一条完整的道路,如深南大道,其节点的总数和节点的坐标是固定不变的;变化的只是因道路动态分段而引起的路段节点数量的多少。这就有了增量更新的可能。

① 为了更好的实现增量更新,先用Chopper把所有路段全部拆分为由两个节点组成的线段,本文称之为最小单元(长度不一定相等)。值得注意的是,由于可能某些路段本身就是最小单元,所以Chopped和Untouched都要跟后面的转换器连接。

② 利用CRCCalculator生成最小单元ID,而由高德路况生成的深圳路网约有7W+ 最小单元,不存在校验码重复的情况,其他城市的未曾验证。

4.3 入库更新

① 用DuplicateFilter移除ID重复的最小单元。

② 用SpatialFilter过滤与边界外的最小单元,只保留深圳境内的。PS:与边界相交的最小单元不能打断,以保持其完整性。

③ 实时路况数据与空间无关,存入status表。

④ 因FME不支持upsert操作符,这里先把最小单元存入chopper_temp表了,最后再更新进chopper表,前提是要先在数据库里把chopper表建好。PS:chopper_temp的Table Handing使用Drop and Create。

4.4 工作流程

至此,加入增量更新后的工作流程如下:

五、进阶提升

5.1 存储优化

① 时间效率上,上面on conflict do nothing是采用类似于upsert的写法,但效率不算太高,可以改为where not exists …的方式,效率会更高一些。

② 空间效率上,还可以优化数据结构,以节省空间。这些都是数据库方面的问题了,这里不多做讨论。

5.2 请求优化

Http数据请求也有进一步的优化空间。

在执行多次工作流程后,基本上能取得深圳市境内全量的路况路网数据。那么,就可以利用数据库里的所有最小单元来过滤原来的网格,把与最小单元不相交的网格去掉,这样剩下来有效网格减至59个,减少量达40%,如图5-1所示。而如果再加入人工干预的话,网格还可以进一步减少至49/50个左右,也就是说,能减少了一半的数据请求过程。

5.3 零编码之上

零编码虽然方便,但毕竟中间过程较多,造成多余的计算,影响效率。而如果能结合少量的编码,不但可以提高效率,还可以让整个流程更加优雅。

如图5-2和图5-3所示,短短十几行代码,就可以用PythonCaller来代替AttributeSplitterListExploderVertexCreatorLineBuilderChopper等转换器的工作,效率的提高也是显而易见。

5.4 工作流程

经过系列优化后的最终工作流程如下:

总结

本文利用FME,提供了一种行之有效的高德路况抓取和更新的技术方案。从如何建立抓取和解析模型,到如何实现增量更新,再到如何进行存储过程优化、获取请求优化和解析过程优化等等,由浅入深,逐步介绍了整个路况抓取和更新的工作流程,为存储更新路况数据做好准备。而至于如何分析和应用这些路况数据,且听下回分解了。

当然高德路况的抓取的方法有很多,可能不少朋友上来就是直接编码实现了。我这人嘛,一个字,懒,能不编码的事情就尽量不编码,而FME就比较对我的脾性了。写本文的目的,是希望能对想要而不知如何抓取高德的朋友提供思路,也希望能对想要学习或同样热衷于FME的朋友有所帮助。

本篇到此结束。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多