【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")
相关推荐
YH行业报告分析19 分钟前
2026电缆铺设设备市场:自动化敷设与电网升级驱动增长
运维·自动化
ajassi20001 小时前
AI语音智能体开发日记(十八)智能体服务器xiaozhi-esp32-server源码部署指南
运维·服务器·人工智能·ai·ai编程
‎ദ്ദിᵔ.˛.ᵔ₎1 小时前
linux 进程信号(下)
linux·运维·服务器
Mikko72 小时前
Linux 磁盘满了但 du 找不到?LVM 扩容 df 不变?fstab 写错开不了机?三台真机实测磁盘排查
linux·运维·centos
蓝胖的四次元口袋2 小时前
Jenkins知识梳理(2)
运维·jenkins
yumgpkpm2 小时前
Acceldata ODP 3.3.6.4 vs CDP Private Cloud Base 7.3.2 对比
大数据·运维·服务器·hadoop·华为·zookeeper·hbase
Liuqy-052 小时前
特殊进程——孤儿、僵尸、守护进程
linux·运维·服务器
考研保研资料分享3 小时前
自动化控制保研经验合辑:上交夏令营、北工大预推免与跨专业面试复盘(2025)
运维·面试·自动化
乐维_lwops3 小时前
2026选择运维监控系统时应该重点考察哪些功能?
大数据·运维·人工智能