1. 项目背景与核心价值
地理数据格式转换是GIS开发中的高频需求。在测绘、导航、遥感等行业,经常需要在GeoJSON和KML这两种主流地理数据格式之间进行转换。前者是WebGIS领域的通用JSON格式,后者则是Google Earth等传统地理软件的标配格式。
我开发的这个转换工具解决了三个痛点:一是现有转换工具要么功能单一要么收费昂贵;二是批量转换时缺乏自定义配置选项;三是转换后的数据经常出现属性丢失或坐标系错乱问题。通过Python实现的这个轻量级工具,可以实现:
- 保留所有属性字段的完整映射
- 支持自定义坐标系转换(如WGS84转GCJ02)
- 批量处理文件夹内所有文件
- 生成符合KML 2.2标准的输出文件
2. 技术实现解析
2.1 核心依赖库选择
选用pykml和geojson作为基础解析库,相比GDAL/OGR的方案更轻量。关键考量:
# 主要依赖 from pykml.factory import KML_ElementMaker as KML from geojson import Feature, FeatureCollection import xml.etree.ElementTree as ET选择理由:
pykml提供符合OGC标准的KML生成能力geojson库对GeoJSON规范支持完善- 避免GDAL带来的重型依赖
- 纯Python实现跨平台兼容性好
2.2 坐标转换处理
坐标系处理是最大难点,工具内置了三种处理模式:
- 直接复制坐标(默认)
- WGS84转GCJ02(通过第三方算法)
- 自定义转换函数接入
关键代码片段:
def convert_coords(coordinates, mode='direct'): if mode == 'gcj02': return [gcj02_encrypt(lon, lat) for lon,lat in coordinates] elif callable(mode): return [mode(lon,lat) for lon,lat in coordinates] else: return coordinates2.3 属性字段映射
采用深度遍历方式处理GeoJSON的properties对象,确保所有嵌套属性都能正确转换为KML的ExtendedData:
def props_to_extendeddata(properties): extendeddata = KML.ExtendedData() for key, value in properties.items(): if isinstance(value, dict): extendeddata.append(props_to_extendeddata(value)) else: extendeddata.append(KML.Data( KML.value(str(value)), name=key )) return extendeddata3. 完整使用指南
3.1 安装与基础使用
通过pip安装:
pip install geojson2kml单文件转换示例:
from geojson2kml import convert convert( input_path='input.geojson', output_path='output.kml', coord_convert='gcj02' )3.2 批量转换模式
处理整个文件夹:
from geojson2kml import batch_convert batch_convert( input_dir='./geojson_files', output_dir='./kml_output', naming_template='{filename}.kml' )3.3 高级配置项
通过config参数实现精细控制:
convert( input_path='input.geojson', output_path='output.kml', config={ 'name_field': 'title', # 使用指定字段作为Placemark名称 'description_template': '{type} @ {date}', # 描述模板 'line_width': 3, # 线型宽度 'polygon_color': '7dff0000' # KML颜色格式(ARGB) } )4. 性能优化方案
4.1 内存优化技巧
处理大型GeoJSON文件时:
- 使用ijson库流式解析
- 分块写入KML文件
- 禁用XML美化输出
优化后代码结构:
import ijson def stream_convert(input_path): with open(input_path, 'rb') as f: features = ijson.items(f, 'features.item') kml = KML.kml() doc = KML.Document() for feature in features: placemark = convert_feature(feature) doc.append(placemark) kml.append(doc) return ET.tostring(kml, encoding='utf-8')4.2 多进程加速
对于批量任务:
from multiprocessing import Pool def parallel_convert(file_list): with Pool(processes=4) as pool: pool.map(convert, file_list)5. 常见问题排查
5.1 坐标系异常
典型症状:
- 在Google Earth中位置偏移
- 高程数据异常
解决方案:
- 确认输入文件的CRS声明
- 检查
coord_convert参数设置 - 测试原始坐标是否WGS84
5.2 属性丢失
排查步骤:
- 检查properties字段类型(需为字典)
- 验证字段名是否含特殊字符
- 测试简单属性是否能正常转换
5.3 文件体积过大
优化建议:
- 使用
simplify参数进行几何简化 - 移除不需要的属性字段
- 考虑转换为KMZ压缩格式
6. 扩展应用场景
6.1 与QGIS集成
通过Python控制台调用:
import geojson2kml layer = iface.activeLayer() geojson2kml.convert( input_path=layer.source(), output_path='/output/path.kml' )6.2 Web服务集成
Flask API示例:
from flask import Flask, request import geojson2kml app = Flask(__name__) @app.route('/convert', methods=['POST']) def convert_api(): geojson = request.json kml = geojson2kml.convert(geojson=geojson) return kml, 200, {'Content-Type': 'application/vnd.google-earth.kml+xml'}6.3 自动化工作流
典型组合方案:
- 使用Watchdog监控文件夹
- 转换后自动上传到Google Drive
- 通过邮件发送结果通知
实现代码框架:
from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler class GeoJSONHandler(FileSystemEventHandler): def on_created(self, event): if event.src_path.endswith('.geojson'): convert(event.src_path) observer = Observer() observer.schedule(GeoJSONHandler(), path='./watch_folder') observer.start()7. 开发经验总结
在开发过程中有几个关键发现值得分享:
- KML的ExtendedData对特殊字符处理与GeoJSON不同,需要做HTML实体转义
- 多级嵌套的Polygon在转换时需要反转坐标顺序
- 使用lxml替代xml.etree可以获得更好的性能表现
对于需要处理复杂GIS数据转换的场景,建议:
- 始终保留原始GeoJSON备份
- 对大型数据集先进行采样测试
- 建立自动化测试验证关键属性