【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")
相关推荐
Logan Lie1 小时前
Web服务监听地址的取舍:0.0.0.0 vs 127.0.0.1
运维·后端
Y淑滢潇潇1 小时前
RHCE 防火墙实验
linux·运维·rhce
稻谷君W2 小时前
Ubuntu 远程访问 Win11 WSL2 并固定访问教程
linux·运维·ubuntu
泡沫·2 小时前
4.iSCSI 服务器
运维·服务器·数据库
悠悠121383 小时前
告别Zabbix?我用Netdata只花10分钟就搞定了50台服务器的秒级监控(保姆级实战)
运维·服务器·zabbix
天庭鸡腿哥3 小时前
大小只有4K的软件,可让系统瞬间丝滑!
运维·服务器·windows·microsoft·everything
虚伪的空想家3 小时前
华为昇腾Atlas 800 A2物理服务器开启VT-d模式
运维·服务器·ubuntu·kvm·vt-d·直通
学渣676563 小时前
服务器端口映射
运维·服务器
红袜子i3 小时前
【问题】实验室服务器恢复记录,一个主板挂两张显卡,
运维·服务器
S***q1923 小时前
DevOps在云中的云计算
运维·云计算·devops