公共数据门户是什么,从哪里开始
data.go.kr是韩国政府与公共机构在一处开放其所持数据的网站,由行政安全部运营,依据《公共数据提供及利用促进法》。其中既有医院、药店等医疗机构信息,也有建筑物登记簿、行政洞人口、公共交通与气象数据。
提供形态主要有两种:文件数据(下载CSV、SHP等)与开放API(通过地址调用获取)。门户首页的热门数据与最新数据区域也并排放着这两个标签页。后文会看到,这个区分在实际开发中相当重要。
开始的步骤很简单:注册会员,在所需数据的详情页点击申请使用,然后在个人页面领取服务密钥。多数API即时或一日内通过审批。密钥以serviceKey=附加在URL查询串中。此时若不对密钥中的特殊字符做URL编码就会认证失败,因此务必在代码中编码后再拼接。
第一个陷阱:不拒绝未知参数,而是忽略
在制作把医院与药店位置放上地图的工具时,我接入了健康保险审查评价院的药店信息服务。为了只取首尔的数据加了地区参数,问题就出在这里。
传入Q0=首尔特别市后,总件数返回25,771条。首尔的药店不可能这么多,于是干脆去掉该参数重新调用,结果仍是25,771条。也就是说这个参数从一开始就没起任何作用。
原因在参数名称。Q0属于国立中央医疗院提供的另一个药店API,而审查评价院的药店信息服务使用sidoCd(市道代码),首尔是110000。正确传入后返回5,883条。
这里重要的不是数字差距,而是失败的方式。尽管传了错误参数,服务器既没返回400也没给出警告,而是以HTTP 200和规范的JSON结构作答,数据本身也确实是药店记录,只是范围是全国而非首尔。我在把首尔药店数放大4.4倍的同时,没有看到任何错误信号。
这类失败不会留在日志里,用眼睛也看不出来。翻看几条数据形态都正常,不会觉得有问题,往往要等到画到地图上、看到首尔以外的坐标混进来才发现。
所以第一步验证是比较总件数
自那以后,接入公共数据API的第一步验证我固定成了一件事:把不带过滤条件与带过滤条件的总件数并排打印出来。两个值相同,就说明这个过滤没生效。
我用同样的方法核对了医院API。不带过滤调用返回79,797条(全国),传入sidoCd=110000返回19,880条(首尔)。数值发生变化,说明这边过滤正常。药店那边数值相同,所以没生效。判定用不了一分钟。
总件数通常在响应的totalCount字段里,即便以numOfRows=1调用,该值仍按全量给出。因此可以一条数据都不取就比较总数。在搭建流水线之前、在翻看任何一行数据之前,先做这件事。
同样的原理适用于其他过滤条件。每多加一个市郡区、机构类别或诊疗科目的过滤,就看总件数是否减少。若不减少,那个过滤等同于不存在。
「门户上有」与「能用API获取」不是一回事
这是第二个常出偏差的地方。「那份数据门户上有」和「那份数据能用API拿到」是两句不同的话。
把制作一张地图所需的五项数据在门户上实际检索一遍,分野很清楚。医院、药店、建筑物登记簿有开放API,可以周期性调用;而行政洞边界与行政洞人口只以文件数据形式提供。以API检索边界会出现无关结果(比如干旱分析),边界多边形API根本不在其中。
这个差异决定了流水线设计。医院与药店不断有开业歇业,用API周期调用是对的;而行政洞边界与人口的数量固定为行政洞个数,下载一次文件装载即可。若把更新周期不同的资料用同一种方式处理,工作量只会无谓地增加。
所以在挑选数据时,问完「有没有」要紧接着问「以什么形态存在」。详情页地址以openapi.do结尾的是API,以fileData.do结尾的是文件。
| 所需资料 | 提供形态 | 数据集编号 |
|---|---|---|
| 医院信息(审查评价院) | 开放API | 15001698 |
| 药店信息(审查评价院) | 开放API | 15001673 |
| 建筑物登记簿(国土交通部建筑HUB) | 开放API | 15134735 |
| 行政洞边界(国土交通部普查边界) | 文件 | 15125055 |
| 行政洞人口(行政安全部) | 文件 | 15097972 |
把多个数据集连起来的键是什么
取了多份数据,最终总要拼接。在医疗机构这一侧,那把钥匙是疗养机号(ykiho)——健康保险审查评价院给每家疗养机构赋予的代码,医院API与药店API使用同一套体系,因此两个数据集可以直接连接。
若想用名称或地址来拼,必然会破。同一家机构常以不同写法出现(空格有无之类),地址也混杂着路名与地番两套体系。既然有代码,就不要用字符串匹配。
在其他领域也找同样的东西。建筑物一侧有登记簿键,行政区划有行政洞代码。在下载数据集之前先定下「要用什么把它和其他数据连起来」,后面返工的次数会明显减少。
实际接入时的顺序
整理一下顺序如下。第一,在门户找到数据,通过详情页地址确认是API还是文件。第二,申请使用后领取服务密钥,做URL编码再调用。第三,不带过滤调用一次、带过滤调用一次,比较总件数;若相同则说明参数名称有误,回去重看文档的请求变量表。
第四,确定连接键。第五,按更新周期把路径分开:变动的走API周期调用,固定的走文件一次性装载。第六,把装载后的总件数记录在某处。日后数值大幅变化时,这份记录就是判断「是源头变了还是我的调用变了」的依据。
最后,把各机构规格各不相同当作前提来对待。同样标着「药店信息」,提供机构不同参数名称就不同,而且有些API会静默忽略错误输入。读文档,但不要尽信文档;用总件数确认的习惯,最终会替你省下时间。
