参考: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")