【GIS】本地部署nominatim地理编码服务

参考:https://www.cnblogs.com/nonkicat/p/17222677.html

docker 部署命令

4.5 版本 docker 用不了,需要用 4.0 版本

复制代码
docker run -it   -e PBF_PATH=/data/你的osm文件.osm.pbf   -e FREEZE=true   -e POSTGRES_MAX_CONNECTIONS=100   -p 6666:8080   --name nominatim   -v /宿主机指向pdf目录:/data   -v /osm-maps/data:/nominatim/data   mediagis/nominatim:4.0

耐心等待建立索引

看到以下输出即成功

复制代码
2025-02-10 11:17:38.015 UTC [764] LOG:  listening on IPv4 address "0.0.0.0", port 5432
2025-02-10 11:17:38.015 UTC [764] LOG:  listening on IPv6 address "::", port 5432
2025-02-10 11:17:38.027 UTC [764] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2025-02-10 11:17:38.105 UTC [765] LOG:  database system was shut down at 2025-02-10 11:17:37 UTC
2025-02-10 11:17:38.118 UTC [764] LOG:  database system is ready to accept connections

查询

复制代码
$ keyword="人民大学"
$ curl "http://localhost:6666/search.php?q=${keyword}&polygon_geojson=1&format=jsonv2"

输出

json 复制代码
[
    {
        "place_id": 116078,
        "licence": "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
        "osm_type": "node",
        "osm_id": 7861046852,
        "boundingbox": [
            "39.960744",
            "39.970744",
            "116.3107286",
            "116.3207286"
        ],
        "lat": "39.965744",
        "lon": "116.3157286",
        "display_name": "人民大学, 北三环(四通桥), 中关村街道, 海淀区, 北京市, 100872, 中国",
        "place_rank": 30,
        "category": "railway",
        "type": "station",
        "importance": 0.11100000000000002,
        "geojson": {
            "type": "Point",
            "coordinates": [
                116.3157286,
                39.965744
            ]
        }
    },
    ...................
]

配套 python 代码查询

python 复制代码
import requests

def get_coordinates(keyword):
    """
    根据关键词查询地点的经纬度。
    
    参数:
        keyword (str): 查询的关键词(如地点名称)。
        
    返回:
        list: 包含地点名称和对应经纬度的字典列表。
              每个字典包含 "place_name", "latitude", "longitude"。
    """
    url = "http://localhost:6666/search.php"
    params = {
        "q": keyword,
        "polygon_geojson": 1,
        "format": "jsonv2"
    }
    
    try:
        # 发送 GET 请求
        response = requests.get(url, params=params)
        
        # 检查响应状态码是否为 200(成功)
        if response.status_code == 200:
            data = response.json()
            results = []
            
            # 遍历结果并提取经纬度
            for item in data:
                place_name = item.get("display_name", "未知地点")
                
                # 尝试从 geojson 提取经纬度
                try:
                    coordinates = item["geojson"]["coordinates"]
                    if item["geojson"]["type"] == "Point":
                        latitude = coordinates[1]
                        longitude = coordinates[0]
                    elif item["geojson"]["type"] == "Polygon":
                        # 如果是 Polygon,取第一个点作为代表
                        latitude = coordinates[0][0][1]
                        longitude = coordinates[0][0][0]
                    else:
                        # 如果类型未知,跳过该条目
                        print(f"未知的 GeoJSON 类型: {item['geojson']['type']},跳过地点: {place_name}")
                        continue
                except (KeyError, IndexError, TypeError):
                    # 如果 geojson 不可用,尝试使用 lat 和 lon 字段
                    try:
                        latitude = float(item["lat"])
                        longitude = float(item["lon"])
                    except KeyError:
                        print(f"无法提取经纬度信息,跳过地点: {place_name}")
                        continue
                
                # 添加到结果列表
                results.append({
                    "place_name": place_name,
                    "latitude": latitude,
                    "longitude": longitude
                })
            
            return results
        else:
            print(f"请求失败,状态码: {response.status_code}")
            return []
    except requests.exceptions.RequestException as e:
        print(f"网络请求出错: {e}")
        return []
    except ValueError as e:
        print(f"JSON 解析出错: {e}")
        return []


# 测试样例
keywords = [
    "北京大学",          # 大学
    "天安门广场",       # 广场
    "故宫博物院",       # 博物馆
    "北京站",           # 火车站
    "颐和园",           # 公园
    "中关村创业大街",   # 街道
    "清华大学",         # 大学
    "国家体育场",       # 体育场馆(鸟巢)
    "首都国际机场",     # 机场
    "人民大会堂"        
]

for keyword in keywords:
    print(f"查询关键词: {keyword}")
    coordinates = get_coordinates(keyword)
    if coordinates:
        for result in coordinates:
            print(f"地点名称: {result['place_name']}")
            print(f"纬度: {result['latitude']}, 经度: {result['longitude']}")
            print("-" * 40)
    else:
        print("未找到任何地点信息。")
    print("\n" + "=" * 80 + "\n")
相关推荐
小嘟嘟132 分钟前
第1章 Shell 脚本入门:从 “Hello World“ 到自动化执行的完整路径
linux·运维·自动化·shell
I · T · LUCKYBOOM4 分钟前
23.ssh远程连接、TCP策略
linux·运维·服务器·网络·tcp/ip·ssh
学Linux的语莫5 分钟前
LangGraph知识
运维·langchain
weixin_660096787 分钟前
tree命令的离线下载
linux·运维·tree
千百元7 分钟前
实时监控磁盘I/O性能
linux·运维·数据库
福尔摩斯张19 分钟前
C语言文件操作详解(一):文件的打开与关闭(详细)
java·linux·运维·服务器·c语言·数据结构·算法
minji...27 分钟前
Linux 进程控制(二) (进程等待wait/waitpid)
linux·运维·服务器·数据结构
我的offer在哪里27 分钟前
MySQL 高频细节问题(覆盖性能、存储、运维、故障排查,补充前文未深入的核心细节)
android·运维·mysql
云和数据.ChenGuang29 分钟前
运维工程师技术之MyCat中间件免费技术教程
运维·中间件·mycat·运维工程师·运维技术
wanhengidc30 分钟前
云手机 巨 椰 三角洲行动
运维·服务器·科技·游戏·智能手机