Geoskill: Geocoding Skill
Perform forward and reverse geocoding using Nominatim and Open-Meteo APIs, supporting single and batch requests with CSV input and output.
ruiduobao
@ruiduobao
What This Skill Does
Command-line tool for converting addresses to geographic coordinates and vice versa using Nominatim (OpenStreetMap) and Open-Meteo APIs. Supports single lookups, reverse geocoding, and batch processing from CSV files with automatic rate limiting and retry logic.
Replaces manual address lookups on mapping websites or building custom geocoding integrations by providing a unified CLI with multiple providers, batch CSV support, and built-in rate limit compliance.
When to Use It
- Convert a list of customer addresses from a CSV file into latitude/longitude coordinates for mapping
- Look up the street address for a set of GPS coordinates from a field survey
- Geocode city names quickly using the faster Open-Meteo provider without rate limits
- Batch reverse-geocode a CSV of coordinates to get display names for a location dataset
- Resume a failed batch geocoding job from the last successful row without restarting
Install
$ openclaw skills install @ruiduobao/geocoding-skillgeocoding-skill
Forward and reverse geocoding tool using Nominatim (OpenStreetMap) and Open-Meteo Geocoding API. Supports single and batch geocoding with rate limiting.
Features
- Forward Geocoding: Address → Latitude/Longitude
- Reverse Geocoding: Latitude/Longitude → Address
- Batch Processing: Geocode multiple addresses from CSV
- Multiple Providers: Nominatim (detailed) + Open-Meteo (fast, cities)
- Rate Limiting: Automatic 1 req/sec for Nominatim compliance
- CSV/JSON Output: Flexible output formats
Usage
# Forward geocode
python scripts\geocoding-skill.py geocode --address "Beijing, China"
# Reverse geocode
python scripts\geocoding-skill.py reverse --lat 39.9042 --lon 116.4074
# Batch geocode from CSV
python scripts\geocoding-skill.py batch --input addresses.csv --address_col "address"
# Use Open-Meteo (faster, good for cities)
python scripts\geocoding-skill.py geocode --address "Tokyo" --provider open-meteo
Parameters
| Parameter | Description | Default |
|---|---|---|
--address | Address to geocode | Required (geocode) |
--lat | Latitude (-90 to 90) | Required (reverse) |
--lon | Longitude (-180 to 180) | Required (reverse) |
--input | Input CSV file path | Required (batch) |
--address-col | Column name with addresses | Required (batch) |
--provider | Provider: nominatim or open-meteo | nominatim |
--output | Output file path | Auto-generated |
Data Sources
- Nominatim (https://nominatim.org/) — OpenStreetMap, ODbL
- Full address geocoding worldwide
- Rate limit: 1 request/second
- No API key required
- Open-Meteo Geocoding (https://open-meteo.com/) — CC BY 4.0
- City/country name lookup
- No rate limit
- No API key required
Installation
pip install requests>=2.28.0 tqdm numpy scipy
# Or: pip install -r scripts/requirements.txt
Dependencies
| Package | Purpose |
|---|---|
requests | HTTP requests to geocoding APIs |
tqdm | Progress bars for batch processing |
Providers Comparison
| Feature | Nominatim | Open-Meteo |
|---|---|---|
| Street address | ✅ | ❌ |
| City name | ✅ | ✅ |
| Country | ✅ | ✅ |
| Rate limit | 1 req/sec | None |
| Reverse geocoding | ✅ | ❌ (fallback to Nominatim) |
CSV Format Specification (Batch Input)
id,address
1,北京市天安门
2,上海市外滩
3,广州市天河区
For reverse geocoding batch:
id,lat,lon
1,39.9042,116.4074
2,31.2304,121.4737
Output Schema
| Column | Description |
|---|---|
id | Input row identifier |
address | Matched address (forward) |
lat | Latitude |
lon | Longitude |
display_name | Full display name |
confidence | Match confidence (0-1) |
Error Handling
| Error | Cause | Solution |
|---|---|---|
| Address not found | Ambiguous or non-existent address | Return empty result with confidence=0 |
| Network error | Connection failure | Auto-retry up to 3 times |
HTTP 429 | Rate limit exceeded | Wait and retry with backoff |
| CSV encoding error | Non-UTF-8 input | Convert to UTF-8 first |
Result Disambiguation
When multiple matches are found, all candidates are returned with confidence scores. The highest confidence match appears first. Filter by confidence >= 0.5 for reliable results.
Timeout Configuration
python scripts\geocoding-skill.py batch --input addresses.csv --timeout 60
Default timeout is 30 seconds per request. Increase for slow connections.
Resume Mechanism for Failed Batch Jobs
# Resume from last successful row
python scripts\geocoding-skill.py batch --input addresses.csv --resume --state-file .geocoding_state.json
The state file tracks completed rows, allowing interruption and resumption without reprocessing.
Encoding / Language Info
- Input CSV must be UTF-8 encoded
- For Nominatim, use
--languageparameter to specify preferred language:python scripts\geocoding-skill.py geocode --address "北京市" --language zh - Supported language codes:
en,zh,ja,ko,fr,de, etc.
Custom Nominatim Endpoint
# Use a self-hosted Nominatim instance
python scripts\geocoding-skill.py geocode --address "Beijing" --endpoint https://nominatim.example.com/search
Default endpoint: https://nominatim.openstreetmap.org/search
Region Biasing
# Prioritize results in China
python scripts\geocoding-skill.py geocode --address "Springfield" --countrycode us
Use --countrycode with ISO 3166-1 alpha-2 codes to bias results toward a specific country.
Accuracy Information
| Match Type | Typical Accuracy |
|---|---|
| Street address | 5-10 m |
| City name | ~1 km (city center) |
| Country | ~10 km (country centroid) |
| POI | Variable (10-100 m) |
Citation
@misc{nominatim,
title={Nominatim - OpenStreetMap reverse geocoding},
author={{OpenStreetMap contributors}},
year={2024},
url={https://nominatim.org/},
note={ODbL}
}
@misc{openmeteo2024geocoding,
title={Open-Meteo Geocoding API},
author={{Open-Meteo}},
year={2024},
url={https://open-meteo.com/en/docs/geocoding-api},
note={CC BY 4.0}
}
Visualization Guidance
import pandas as pd
import folium
df = pd.read_csv("geocoded_results.csv")
m = folium.Map(location=[df["lat"].mean(), df["lon"].mean()], zoom_start=4)
for _, row in df.iterrows():
folium.Marker(
location=[row["lat"], row["lon"]],
popup=row["display_name"],
tooltip=str(row["id"])
).add_to(m)
m.save("geocoded_map.html")
Troubleshooting
| Error | Cause | Solution |
|---|---|---|
ConnectionError | Network issue | Check internet, retry |
HTTP 429 | Rate limit | Wait 60s, retry |
ValueError | Invalid input | Check parameter format |
| Empty output | No data | Try different parameters |
ModuleNotFoundError | Missing dep | Run pip install |
Advanced Usage
Batch Geocoding with Resume
python scripts\geocoding-skill.py batch --input addresses.csv --output geocoded.json --resume
CI/CD Integration (GitHub Actions)
# .github/workflows/geocode-update.yml
name: Geocode Addresses
on:
push:
paths: ['data/addresses.csv']
jobs:
geocode:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install requests
- run: |
python scripts\geocoding-skill.py batch \
--input data/addresses.csv \
--output data/geocoded.json --resume
PostGIS Import
python scripts\geocoding-skill.py batch --input addresses.csv --output geocoded.json
# Convert to CSV and import
python -c "
import json, csv
data = json.load(open('geocoded.json'))
with open('geocoded.csv', 'w', newline='') as f:
w = csv.DictWriter(f, fieldnames=['input', 'lat', 'lon', 'display_name'])
w.writeheader()
for r in data:
w.writerow({'input': r['input'], 'lat': r['lat'], 'lon': r['lon'], 'display_name': r['display_name']})
"
psql -d gis_db -c "\COPY geocoded_addresses FROM 'geocoded.csv' CSV HEADER"
Performance Tips
- Use
--resumeto continue interrupted batch jobs - Add
--delay 1to respect Nominatim rate limit (1 req/sec) - For >10k addresses, consider self-hosted Nominatim with
--endpoint
中文说明
基于 Nominatim(OpenStreetMap)和 Open-Meteo 的正向/反向地理编码工具,支持单条和批量地理编码。
安装
pip install requests>=2.28.0 tqdm numpy scipy
# 或: pip install -r scripts/requirements.txt
依赖
| 包 | 用途 |
|---|---|
requests | 地理编码 API 的 HTTP 请求 |
tqdm | 批量处理进度条 |
CSV 格式规范(批量输入)
id,address
1,北京市天安门
2,上海市外滩
3,广州市天河区
反向地理编码批量输入:
id,lat,lon
1,39.9042,116.4074
2,31.2304,121.4737
输出结构
| 列名 | 说明 |
|---|---|
id | 输入行标识 |
address | 匹配地址(正向) |
lat | 纬度 |
lon | 经度 |
display_name | 完整显示名称 |
confidence | 匹配置信度(0-1) |
错误处理
| 错误 | 原因 | 解决方案 |
|---|---|---|
| 地址未找到 | 模糊或不存在的地址 | 返回空结果,confidence=0 |
| 网络错误 | 连接失败 | 自动重试最多 3 次 |
HTTP 429 | 超出速率限制 | 等待后重试 |
| CSV 编码错误 | 非 UTF-8 输入 | 先转换为 UTF-8 |
结果消歧义
找到多个匹配时,返回所有候选结果及置信度分数。最高置信度匹配排在首位。筛选 confidence >= 0.5 获取可靠结果。
超时配置
python scripts\geocoding-skill.py batch --input addresses.csv --timeout 60
默认超时 30 秒/请求。网络较慢时增加超时时间。
失败批量任务恢复机制
# 从上次成功行恢复
python scripts\geocoding-skill.py batch --input addresses.csv --resume --state-file .geocoding_state.json
状态文件跟踪已完成行,支持中断后恢复,无需重新处理。
编码/语言信息
- 输入 CSV 必须为 UTF-8 编码
- Nominatim 使用
--language参数指定首选语言:python scripts\geocoding-skill.py geocode --address "北京市" --language zh - 支持的语言代码:
en、zh、ja、ko、fr、de等
自定义 Nominatim 端点
# 使用自托管 Nominatim 实例
python scripts\geocoding-skill.py geocode --address "Beijing" --endpoint https://nominatim.example.com/search
默认端点:https://nominatim.openstreetmap.org/search
区域偏好
# 优先返回中国结果
python scripts\geocoding-skill.py geocode --address "Springfield" --countrycode us
使用 ISO 3166-1 alpha-2 代码指定 --countrycode 以偏向特定国家。
精度信息
| 匹配类型 | 典型精度 |
|---|---|
| 街道地址 | 5-10 米 |
| 城市名 | ~1 公里(城市中心) |
| 国家 | ~10 公里(国家质心) |
| POI | 变化较大(10-100 米) |
引用格式
@misc{nominatim,
title={Nominatim - OpenStreetMap reverse geocoding},
author={{OpenStreetMap contributors}},
year={2024},
url={https://nominatim.org/},
note={ODbL}
}
@misc{openmeteo2024geocoding,
title={Open-Meteo Geocoding API},
author={{Open-Meteo}},
year={2024},
url={https://open-meteo.com/en/docs/geocoding-api},
note={CC BY 4.0}
}
可视化指南
import pandas as pd
import folium
df = pd.read_csv("geocoded_results.csv")
m = folium.Map(location=[df["lat"].mean(), df["lon"].mean()], zoom_start=4)
for _, row in df.iterrows():
folium.Marker(
location=[row["lat"], row["lon"]],
popup=row["display_name"],
tooltip=str(row["id"])
).add_to(m)
m.save("geocoded_map.html")
故障排除
| 错误 | 原因 | 解决方案 |
|---|---|---|
ConnectionError | 网络问题 | 检查网络,重试 |
HTTP 429 | 速率限制 | 等待 60 秒后重试 |
ValueError | 无效输入 | 检查参数格式 |
| 空输出 | 无数据 | 尝试不同参数 |
ModuleNotFoundError | 缺少依赖 | 运行 pip install |
基于 Nominatim(OpenStreetMap)和 Open-Meteo 的正向/反向地理编码工具,支持单条和批量地理编码。
功能特性
- 正向地理编码:地址 → 经纬度
- 反向地理编码:经纬度 → 地址
- 批量处理:从 CSV 文件批量地理编码
- 多提供者:Nominatim(详细)+ Open-Meteo(快速,城市级)
- 速率限制:自动 1 请求/秒,符合 Nominatim 使用条款
- CSV/JSON 输出:灵活输出格式
使用方法
# 正向地理编码
python scripts\geocoding-skill.py geocode --address "北京市天安门"
# 反向地理编码
python scripts\geocoding-skill.py reverse --lat 39.9042 --lon 116.4074
# 批量地理编码
python scripts\geocoding-skill.py batch --input addresses.csv --address_col "address"
# 使用 Open-Meteo(更快,适合城市名)
python scripts\geocoding-skill.py geocode --address "Tokyo" --provider open-meteo
数据来源
- Nominatim (https://nominatim.org/) — OpenStreetMap,ODbL
- 全球完整地址地理编码
- 速率限制:1 请求/秒
- 无需 API key
- Open-Meteo 地理编码 (https://open-meteo.com/) — CC BY 4.0
- 城市/国家名称查询
- 无速率限制
- 无需 API key
提供者对比
| 功能 | Nominatim | Open-Meteo |
|---|---|---|
| 街道地址 | ✅ | ❌ |
| 城市名 | ✅ | ✅ |
| 国家 | ✅ | ✅ |
| 速率限制 | 1 请求/秒 | 无限制 |
| 反向地理编码 | ✅ | ❌(回退到 Nominatim) |
Top skills in this category
Skill Vetter
@spclaudehomeSecurity-first skill vetting for AI agents. Use before installing any skill from ClawdHub, GitHub, or other sources. Checks for red flags, permission scope, and suspicious patterns.
Github
@steipeteInteract with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Humanizer
@biostartechnologyRemove signs of AI-generated writing from text. Use when editing or reviewing text to make it sound more natural and human-written. Based on Wikipedia's comprehensive "Signs of AI writing" guide. Detects and fixes patterns including: inflated symbolism, promotional language, superficial -ing analyses, vague attributions, em dash overuse, rule of three, AI vocabulary words, negative parallelisms, and excessive conjunctive phrases.
Free Ride - Unlimited free AI
@shaivpidadiManages free AI models from OpenRouter for OpenClaw. Automatically ranks models by quality, configures fallbacks for rate-limit handling, and updates opencla...
Elite Longterm Memory
@nextfrontierbuildsUltimate AI agent memory system for Cursor, Claude, ChatGPT & Copilot. WAL protocol + vector search + git-notes + cloud backup. Never lose context again. Vibe-coding ready.