Nominatim免费的地址解析,逆地址解析,OpenStreetMap开源地图数据

国内的一些地址解析供应商的API都开始付费了,就想找个免费的地址解析和逆地址解析的应用,最终选择了Nominatim + OpenStreetMap


  • 一、选型

    • 1-1、数据源

    • 1-2、地理编码引擎

    • 2-1、初尝Nominatim

    • 2-2、OSM数据解析

    • 2-3、Nominatim和OSM数据关系映射

    • 2-4、举一反三

    • 2-5、Nominatim API解析

  • 三、安装

  • 四、关于数据源 (重要)

  • 五、替代方案

  • N、其它

    • N-1、place和placex

    • N-2、相关资料

    • N-3、测试覆盖

    • 逆地址解析



这篇文章将会从调研、选型、测试、应用全方面的解析,如果你也在找地址解析和逆地址解析的开源方案它一定会给你带来帮助

地址解析:通过一个地名(深圳),获取当前地方的经纬度、省市区级别 逆地址解析:通过经纬度,获取当前位置的名称、省市区级别


一、选型


1-1、数据源


对于地图解析这个应用来说,最重要不是软件部分,而是数据,只有数据全面了才有可能得出相对准确的结果。目前开源免费的全面的数据大概率只有 OpenStreetMap了,它是由各个国家的志愿者一起维护的数据

OpenStreetMap(后面简称OSM) 是一个众包的地图项目,旨在创建一个可自由编辑和使用的世界地图数据库。它由全球的志愿者贡献者更新和维护,提供了一个详细和准确的地理数据集合。OSM 数据包括道路、建筑物、自然特征、商业设施等(简单理解就是很多志愿者一起维护了一份地图数据


OpenStreeMap 相关文档链接 (后面会详解)

描述 地址
官网 https://www.openstreetmap.org
没有找到合适的中国数据,而且中国数据和台湾都是分开的,这必然不行,直接用亚洲的数据 https://download.openstreetmap.fr/extracts/
每一个地址都会有标签,标签很多想知道某个标签的含义,可去标签系统搜索,下面会讲解 https://taginfo.openstreetmap.org


1-2、地理编码引擎


调研时间:24年5月

开源方案 Nominatim Pelias Photon
支持数据源 OpenStreetMap OpenStreetMap、OpenAddresses、Geonames等 OpenStreetMap
核心功能 地理编码和逆地理编码 地理编码和逆地理编码,支持全文搜索 高效地进行地理编码和逆地理编码
开发语言 Python、PHP Twig Java
GitHub关注数 2.9K 3.1K 1.8K
GitHub最新版本时间 2024-03-07 2024-03-06
GitHub待解决问题数 92 242 57
GitHub活跃度 高(去年发布10个版本) 低(无正式版本) 中(去年发布2个版本)
GitHub代码贡献者数 90 28 49
系统对接 REST API REST API REST API


  1. Nominatim能满足功能需求,需要额外处理直辖市和港澳台问题
  2. Photon 不支持中文国际化,无法满足


Nominatim 是一个开源的地理编码引擎,专门用于从 OSM 数据中提取地理信息。它提供了两种主要功能:

  1. 地理编码:将地址转换为经纬度坐标
  2. 逆地理编码:将经纬度坐标转换为地址


Nominatim 的API其实已经研究过了是满足的,下面详细讲解它的API


2-1、初尝Nominatim


这个要VPN才可以访问

2-1-1、地址解析


请求地址

https://nominatim.openstreetmap.org/search?1=1&q=深圳市&format=geocodejson&addressdetails=1&accept-language=zh&zoom=8&limit=1


请求结果

{
    "type""FeatureCollection",
    "geocoding": {
        "version""0.1.0",
        "attribution""Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright",
        "licence""ODbL",
        "query""深圳市"
    },
    "features": [
        {
            "type""Feature",
            "properties": {
                "geocoding": {
                    "place_id"368109611,
                    "osm_type""relation",
                    "osm_id"3464353,
                    "osm_key""boundary",
                    "osm_value""administrative",
                    "type""city",
                    "label""深圳市, 广东省, 中国",
                    "name""深圳市",
                    "state""广东省",
                    "country""中国",
                    "country_code""cn",
                    "admin": {
                        "level5""深圳市",
                        "level4""广东省"
                    }
                }
            },
            "geometry": {
                "type""Point",
                "coordinates": [
                    114.0545429,
                    22.5445741
                ]
            }
        }
    ]
}


2-1-2、逆地址解析


请求地址

https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=43.767755&lon=87.51623&addressdetails=1&accept-language=zh&zoom=8&limit=1


请求结果

{
    "type""FeatureCollection",
    "geocoding": {
        "version""0.1.0",
        "attribution""Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright",
        "licence""ODbL",
        "query"""
    },
    "features": [
        {
            "type""Feature",
            "properties": {
                "geocoding": {
                    "place_id"190215046,
                    "osm_type""relation",
                    "osm_id"5663100,
                    "osm_key""boundary",
                    "osm_value""administrative",
                    "type""district",
                    "accuracy"0,
                    "label""沙依巴克区, 乌鲁木齐市, 新疆维吾尔自治区, 830000, 中国",
                    "name""沙依巴克区",
                    "postcode""830000",
                    "city""乌鲁木齐市",
                    "state""新疆维吾尔自治区",
                    "country""中国",
                    "country_code""cn",
                    "admin": {
                        "level6""沙依巴克区",
                        "level5""乌鲁木齐市",
                        "level4""新疆维吾尔自治区"
                    }
                }
            },
            "geometry": {
                "type""Point",
                "coordinates": [
                    87.46749,
                    43.726972
                ]
            }
        }
    ]
}


2-2、OSM数据解析


对于地图服务真正难的是数据,核心也还是OSM的数据,后面会讲怎么导入数据,这里先解析数据。把OSM的数据导入到 PostgreSQL后,它有两张重要的表,个人感觉对于一般应用来说,理解这两张表就够够了 (下面是我的理解,供参考)

  • place:place表维护的是每一条独立的数据(可以是一棵树、也可以是一条河、一个城市)
  • placex:因为地区是包含关系placex维护的是有关系的上下级数据

表字段很多,下面讲重要的,如果对这两张表结构感兴趣的可以参看下面的:==N-1==


2-2-1、place表


字段 描述
osm_id 数据的唯一id
osm_type 数据类型:N、R、W (对表500w数据 distinct + 搜索)
 
1.节点(Node):存储为一个经纬度坐标点。例如,一个节点可能表示一个具体的地理位置,如一座建筑物的角落或一棵树  
2.路径(Way):由一系列节点组成,每个节点都有其自己的经纬度坐标。路径可以表示线性特征(如道路)或闭合区域(如湖泊)  
 3.关系(Relation):由多个节点和路径组成,表示更复杂的地理特征和逻辑关系,如边界、多边形区域或路线
class 这两个字段是一起的 key=value,是对这条数据打的标签,目前有 9w+个key

highway=secondary
1. highway标签是用于任何类型道路的主要标签
2. highway=secondary 次要道路是连接重要城镇的道路

注:https://taginfo.openstreetmap.org   因为key=value 太多了,官方有专门维护描述

type
admin_level当前数据的等级,数据库有 1-15级  (抽样查看了每一层的数据,并不是特别的标准)
name当前数据的各种语言的描述,地址解析的时候我猜就是匹配这个字段
 
  eg:  
“name”=>”深圳市”, “name:af”=>”Shenzhen”, “name:ar”=>”شنجن (الصين)”, “name:az”=>”Şençjen”, “name:ba”=>”Шэньчжэнь”, “name:be”=>”Шэньчжэнь”,
geometry当前数据的经纬度,数据存在多种可能性,比如点、线、多线、多边形、几何图形 等

注:数据并不全是存的明文,有些是加密的,可以通过在线工具解密https://www.zaixianjisuan.com/dilicesuan/wkt%20_%20wkb%20_%20geojson%20convert%20online.html


geometry 存储数据样例

POINT(117.1767305 39.1448629)
LINESTRING(117.1847722 39.1481168117.1845921 39.1481353)
POLYGON((117.1829091 39.1494689117.182913 39.1494281117.1829335 39.1493904117.1829685 39.1493598117.1830143 39.1493394117.183066 39.1493315117.1831199 39.1493372117.1831478 39.1493482117.1831683 39.1493563117.183206 39.1493867117.1832286 39.1494251117.1832337 39.149467117.1832206 39.149508117.183191 39.1495433117.183148 39.1495691117.1830964 39.1495825117.183042 39.1495819117.1829924 39.1495681117.182951 39.1495428117.1829222 39.1495085117.1829091 39.1494689))


2-2-2、placex表


placex 表的关键信息,它很多字段和place表一样

字段名 描述
place_id 数据的唯一id
parent_place_id 上级id
importance 数据权重,匹配到多条数据,这个字段是排序规则之一
centroid 当前区域的中心点 (是个POINT类型的 经纬度,参看上面的 geometry)
postcode 邮编
country_code 国家编码 cn
osm_type 同 place表
osm_id 同 place表
class 同 place表
type 同 place表
admin_level 同 place表
name 同 place表
geometry 同 place表


这个表数据很重要,解析和逆解析都是对这个表进行搜索


2-3、Nominatim和OSM数据关系映射


Nominatim和OpenStreetMap 字段映射关系(从上面的返回值抽取稳定有用的字段)

Nominatim 返回字段 OpenStreeMap 字段(对应表 placex)
place_id place_id
osm_id osm_id
osm_type osm_type
osm_key class
osm_value type
admin[] 在 placex 表有个parent_place_id,一直向上取到 parent_place_id = 0

key = level + admin_level  
value = name -> ‘name’

postcodepostcode
labeladmin + postcode
geometrycentroid


2-4、举一反三


通过上面的分析得出2点

  1. Nominatim 就是一个地图搜索引擎,用的是OSM的数据
  2. Nominatim 不管是解析还是逆解析返回的都是 placex 表的某条数据(place_id)

通过对数据的分析和一些文档描述,大概知道了它搜索的逻辑地址解析就是去模糊匹配 name,逆地址解析就是拿入参的经纬度去找数据库距离最近权重最高的数据返回


地址解析SQL

SELECT
    place_id,
    ST_AsText(geometry) AS geometry
FROM placex
WHERE name -> 'name' ILIKE '%中国%'
AND importance IS NOT NULL
ORDER BY importance DESC 
LIMIT 1;


逆地址解析SQL

SELECT  
    place_id,
    ST_X(centroid) AS lon,
    ST_Y(centroid) AS lat,
    ST_Distance(geometry::geography, ST_SetSRID(ST_MakePoint(90.392926,30.014464), 4326)::geography) AS distance
FROM placex
WHERE 
    ST_Distance(geometry::geography, ST_SetSRID(ST_MakePoint(90.392926,30.014464), 4326)::geography) BETWEEN 1 AND 1000
ORDER BY
    distance ASC,
    importance DESC
LIMIT 1
;


测试结果和Nominatim返回的结果相似度90%+,但性能没法比,SQL运行结果很慢


2-5、Nominatim API解析


https://nominatim.openstreetmap.org/search?1=1&q=深圳市&format=geocodejson&addressdetails=1&accept-language=zh&zoom=8&limit=1
https://nominatim.openstreetmap.org/reverse?format=geocodejson&lat=43.767755&lon=87.51623&addressdetails=1&accept-language=zh&zoom=8&limit=1


上面这两个URL在绝大部分场景下,已经是最佳答案了,如果你还需要其它的请参考官方API文档

  • https://nominatim.org/release-docs/develop/api/Search/
  • https://nominatim.org/release-docs/develop/api/Reverse/


字段 描述
q 文本查询 (不和省、市、区 这些字段一起使用)
format 返回的数据格式,相信我 geocodejson 是最好的格式,因为它最接近数据库的数据
addressdetails 是否返回地址详情
accept-language zh  返回中文,不然可能会有少数民族文字
limit 限制返回条数(数据已经是按照权重排好序了,大部分场景只要一条数据,所以 limit=1)
zoom=8 返回的层级  4级基本是省份,5级基本是城市 (建议带上这个参数,不然极少数情况会出错,作者说的)
lat、lon 经纬度


三、安装


https://download.openstreetmap.fr/extracts/asia.osm.pbf  下载亚洲的 PBF文件  (先看四)

然后去你的服务上用docker安装(差不多要300G磁盘),执行过程大概4天半左右

docker run -d -it 
--shm-size=12g -e 
PBF_PATH=/nominatim/osm_data/下载下来的数据.pbf 
-e IMPORT_STYLE=address 
-e NOMINATIM_FLATNODE_FILE=/nominatim/flat_data/flatnode.file 
-p 8090:8080 -p 5432:5432 
-v /nominatim/flat_data:/nominatim/flat_data 
-v /nominatim/osm_data:/nominatim/osm_data 
--name planet mediagis/nominatim:4.4

官网dockert安装地址:https://github.com/mediagis/nominatim-docker/tree/master/4.4
非docker安装需要很多各种依赖较为麻烦


四、关于数据源 (重要)


尝试过的数据源

问题 数据范围 数据源
Nominatim不支持map和img格式 中国 https://download3.bbbike.org/osm/garmin/region/asia/china/
Nominatim不支持map和img格式 中国 https://download3.bbbike.org/osm/mapsforge/region/asia/china/
数据不全,部分数据有问题 中国 https://download.openstreetmap.fr/extracts/asia/china-latest.osm.pbf
数据不全,部分数据有问题 中国 https://download.geofabrik.de/asia.html
数据不全,部分数据有问题 中国 https://osmtoday.com/asia.html
完美 亚洲 https://download.openstreetmap.fr/extracts/asia.osm.pbf


数据源相关文章:

https://wiki.openstreetmap.org/wiki/Zh-hans:Planet.osm https://www.chinaflier.com/thread-202695-1-1.html https://github.com/osm-search/Nominatim/discussions/3434


尝试了很多的中国数据一直都不准,最后抱着试试的心理尝试了亚洲的数据,完美

  • 服务器:4核32G
  • 亚洲 pbf 15g
  • 导入时间 4天半
  • 消耗空间 277G
Nominatim免费的地址解析,逆地址解析,OpenStreetMap开源地图数据
在这里插入图片描述


五、替代方案


如果你只是需要简单的地址解析和逆地址解析,其实也不用如此大费周章,可以参看:

下一篇文章


N、其它


N-1、place和placex

CREATE TABLE "public"."place" (
  "osm_type" char(1COLLATE "pg_catalog"."default" NOT NULL,
  "osm_id" int8 NOT NULL,
  "class" text COLLATE "pg_catalog"."default" NOT NULL,
  "type" text COLLATE "pg_catalog"."default" NOT NULL,
  "admin_level" int2,
  "name" "public"."hstore",
  "address" "public"."hstore",
  "extratags" "public"."hstore",
  "geometry" geometry(GEOMETRY, 4326NOT NULL
)

CREATE TABLE "public"."placex" (
  "place_id" int8 NOT NULL,
  "parent_place_id" int8,
  "linked_place_id" int8,
  "importance" float8,
  "indexed_date" timestamp(6),
  "geometry_sector" int4,
  "rank_address" int2,
  "rank_search" int2,
  "partition" int2,
  "indexed_status" int2,
  "osm_type" char(1COLLATE "pg_catalog"."default" NOT NULL,
  "osm_id" int8 NOT NULL,
  "class" text COLLATE "pg_catalog"."default" NOT NULL,
  "type" text COLLATE "pg_catalog"."default" NOT NULL,
  "admin_level" int2,
  "name" "public"."hstore",
  "address" "public"."hstore",
  "extratags" "public"."hstore",
  "geometry" geometry(GEOMETRY, 4326NOT NULL,
  "wikipedia" text COLLATE "pg_catalog"."default",
  "token_info" jsonb,
  "country_code" varchar(2COLLATE "pg_catalog"."default",
  "housenumber" text COLLATE "pg_catalog"."default",
  "postcode" text COLLATE "pg_catalog"."default",
  "centroid" geometry(GEOMETRY, 4326)
)
;


N-2、相关资料


描述 地址
OSM 官网 https://www.openstreetmap.org
OSM官方对中国地图的描述 https://wiki.openstreetmap.org/wiki/Zh-hans:%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD
数据标签查询 https://taginfo.openstreetmap.org
Nominatim 地址解析API https://nominatim.org/release-docs/develop/api/Search/
Nominatim 逆地址解析API https://nominatim.org/release-docs/develop/api/Reverse/
Nominatim docker安装地址 https://github.com/mediagis/nominatim-docker/tree/master/4.4
官网API查询数据没有 level5问题 https://github.com/osm-search/Nominatim/issues/3437
官方说明只能导入 pbf、osm 格式 https://github.com/osm-search/Nominatim/discussions/3436
pbf、bz2、shp.zip 数据格式含义 https://download.geofabrik.de/technical.html
数据源 https://download.geofabrik.de/asia.html(福建省数据不是很准)
数据源 https://download3.bbbike.org/osm/garmin/region/asia/china/ (Nominatim不支持map和img格式)
数据源 https://osmtoday.com/asia.html (数据不全,部分数据有问题))
数据源 https://download.openstreetmap.fr/extracts/asia/china-latest.osm.pbf(数据不全,部分数据有问题)
百度提供的在线经纬度获取 https://api.map.baidu.com/lbsapi/getpoint/index.html
经纬度在线解析 https://www.zaixianjisuan.com/dilicesuan/wkt%20_%20wkb%20_%20geojson%20convert%20online.html
其它阅读 https://wiki.openstreetmap.org/wiki/Zh-hans:Planet.osm
https://www.chinaflier.com/thread-202695-1-1.html
https://github.com/osm-search/Nominatim/discussions/3434

N-3、测试覆盖


我此次的需求只需要精确到 省、市,直接用GPT列举出全部的市级以上的数据,然后再自己每个省份描点经纬度100个,再让GPT生成随机每个省的经纬度 1000个。

让自建API和腾讯API进行对比,问题如下


地址解析

  1. 香港、澳门,腾讯的是带了 【行政区】 后缀,且存在部分的繁体字
  2. 台湾 腾讯返回的都是简体字,自建地图大部分数据返回的是繁体字


逆地址解析

入参 自建 腾讯 百度
110.39119,20.091971 {longitude=110.3715545, latitude=20.0748919, nation=’中国’, province=’海南省’, city=’海口市’} {nation=’中国’, province=’中国区域’, city=”, district=”, street=”} 海南省海口市美兰区
101.808916,36.653178 {longitude=101.8128242, latitude=36.649104, nation=’中国’, province=’青海省’, city=’西宁市’} {nation=’中国’, province=’青海省’, city=’海东市’, district=’互助土族自治县’, street=”} 青海省西宁市城北区
91.276412,29.525961 {longitude=91.4130822, latitude=29.2551346, nation=’中国’, province=’西藏自治区’, city=’山南市’} {nation=’中国’, province=’西藏自治区’, city=’拉萨市’, district=’城关区’, street=”} 西藏自治区山南市扎囊县
113.795412,34.887975 {longitude=113.7888121, latitude=34.921496, nation=’中国’, province=’河南省’, city=’新乡市’} {nation=’中国’, province=’河南省’, city=’郑州市’, district=’惠济区’, street=”} 河南省郑州市惠济区
112.12054,40.707765 {longitude=112.120318174164, latitude=40.71081296482041, nation=’中国’, province=’内蒙古自治区’, city=’乌兰察布市’} {nation=’中国’, province=’内蒙古自治区’, city=’呼和浩特市’, district=’赛罕区’, street=”} 内蒙古自治区呼和浩特市赛罕区
113.273535,27.875086 {longitude=113.7001702, latitude=28.2178951, nation=’中国’, province=’湖南省’, city=’长沙市’} {nation=’中国’, province=’湖南省’, city=’株洲市’, district=’荷塘区’, street=”} 湖南省株洲市荷塘区X004(宋芷路)
101.885386,36.529808 {longitude=101.9975, latitude=36.399977, nation=’中国’, province=’青海省’, city=’海东市’} {nation=’中国’, province=’青海省’, city=’西宁市’, district=’湟中区’, street=”} 青海省西宁市湟中区
121.827422,24.73118 {longitude=120.9820179, latitude=23.9739374, nation=’中国’, province=’臺灣’, city=’臺灣’} {nation=’中国’, province=’台湾省’, city=’宜兰县’, district=’壮围乡’, street=”} 台湾省宜兰县


结论

1.现在的亚洲的数据和官网几乎一样 2.和腾讯比,也只有很少边界的地方存在误差


原文始发于微信公众号(小道仙97):Nominatim免费的地址解析,逆地址解析,OpenStreetMap开源地图数据

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/293212.html

(0)
李, 若俞的头像李, 若俞

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!