实录国内4级(省级、地级、县级、乡级)城市geoHash

背景:因工作需求 需要通过经纬度确定所在城市,还要离线实现,翻阅资料了解到geoHash编码 可以满足需求,但是翻遍了网络 也 下了不少收费的数据,最多的只满足到 3级范围,

3级范围 实测中会出现偏差无法满足需求,故 需要使用4级geoHash的数据

geoHash算法采用:https://github.com/GongDexing/Geohash

这里主要说明 如何采集数据

首先找到 需要的 省级、地级、县级、乡级 数据 :https://github.com/modood/Administrative-divisions-of-China

这边数据还有 第5级 村级 这边使用不到,就采用了 乡级 数据

接下来就是编码流程了

通过 4级城市数据json,得到4个列表 provinceList,cityList,areaList,streetList

遍历streetList列表 (41614条)

依次使用OkHttp调用百度的WebAPI 进行编码查询 ( 百度API文档:http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding

获取到对应乡级城市的经纬度 使用geoHash算法得到geoHash值 然后按需要的格式 保存到文件中

*** 这里有个注意事项:百度WebAPI地理编码配额 如果超出配额 请求就会返回错误 导致经纬度获取失败

得到的数据列表

输出的数据足有41615条,占4.24M

这么多在数据 直接放在 App中 显然是不合适的,测试过程中将 这41615条数据写入数据库 耗时近 20s  进而开启 简化 之路

简化思路

1.经纬度当前过长 有12位之多,但是 实际上 精确到后第6位时 就已经达到米级了,所以只需要 保留小数点后6位 即可  处理后 --> 3.59M 

2.项目中使用到的 城市展示 那直接把 乡,区,省 过滤输出 ,同时精简编号 到区级编号 也就是前6位 (使用 乡级数据 是为了更精准的判断 所在的城市是哪里,如果直接使用 区级 数据,那相邻的城市区域很容易出现计算错误的情况),

注意到有些 地级 名称为 “市辖区”、“省直辖县级行政区划”、“自治区直辖县级行政区划” ,那这就直接使用省份的名称,这一步处理后 -->2.08M

3.注意到 需求只要求 精准显示到 地级市  就可以了 ,那再进一步简化 ,将同一地级市 的经纬度、geoHash ,合并到一起 ,这样的话,数据 将由 目前的41615条 压到 343条  大小:1.28M 

 

*** 在简化过程中 发现有geoHash重复的情况,分析原因 是 百度API返回的经纬度问题 四个街道 地图明明差很远 按是返回的经纬度是一样的  目前过滤掉了1999条重复经纬度的数据,以后看百度有更新的话 再测试更新数据吧

例:

深圳市宝安区燕罗街道:showLocation&&showLocation({"status":0,"result":{"location":{"lng":113.89042744066019,"lat":22.560032908924556},"precise":0,"confidence":20,"comprehension":100,"level":"区县"}})
深圳市宝安区新桥街道:showLocation&&showLocation({"status":0,"result":{"location":{"lng":113.89042744066019,"lat":22.560032908924556},"precise":0,"confidence":20,"comprehension":100,"level":"区县"}})
深圳市宝安区福海街道:showLocation&&showLocation({"status":0,"result":{"location":{"lng":113.89042744066019,"lat":22.560032908924556},"precise":0,"confidence":20,"comprehension":100,"level":"区县"}})
深圳市宝安区航城街道:showLocation&&showLocation({"status":0,"result":{"location":{"lng":113.89042744066019,"lat":22.560032908924556},"precise":0,"confidence":20,"comprehension":100,"level":"区县"}})

App最终实测 写入本地数据库 用法1-2秒  终

原始数据以及简化后的数据打包:https://download.csdn.net/download/a87024341/16133365

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
geohash简介: geohash是一种地址编码,它能把二维的经纬度编码成一维的字符串。geohash有以下几个特点: 首先,geohash用一个字符串表示经度和纬度两个坐标。某些情况下无法在两列上同时应用索引 (例如MySQL 4之前的版本,Google App Engine的数据层等),利用geohash,只需在一列上应用索引即可。 其次,geohash表示的并不是一个点,而是一个矩形区域。比如编码wx4g0ec19,它表示的是一个矩形区域。 使用者可以发布地址编码,既能表明自己位于北海公园附近,又不至于暴露自己的精确坐标,有助于隐私保护。 第三,编码的前缀可以表示更大的区域。例如wx4g0ec1,它的前缀wx4g0e表示包含编码wx4g0ec1在内的更大范围。 这个特性可以用于附近地点搜索。首先根据用户当前坐标计算geohash(例如wx4g0ec1)然后取其前缀进行查询 (SELECT * FROM place WHERE geohash LIKE 'wx4g0e%'),即可查询附近的所有地点。Geohash比直接用经纬度的高效很多。用途: 移动互联网,lbs可以说是一个基础应用,geohash对于解决附近地点搜索提供了一个有效的解决方案。扩展: 这个php扩展,提供了三个函数:/**     *  $latitude    //纬度     *  $longitude   //经度     *  $precision   //精密度, 默认是12     *  返回 $precision 长度的 string     */    geohash_encode($latitude, $longitude, $precision=12);      /**     *  $hash    //geohash_encode后的值     *  返回 array // Array     *                    (     *                        [latitude] => 39.416916975752     *                        [longitude] => 100.92223992571     *                        [north] => 39.416917059571     *                        [east] => 100.92224009335     *                        [south] => 100.92223992571     *                        [west] => 100.92223975807     *                    )     */    geohash_decode($hash);    /**     *  $hash    //geohash_encode后的值     *  返回 在$hash 8个 (东南西北各二个)附近的hash值     */    geohash_neighbors($hash); 标签:geohash

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值