简介:这份资源面向GIS专业师生及需要处理空间数据的非专业用户,解决Google地球数字化得到的kml/kmz矢量无法直接在ArcGIS等平台使用的问题。包内共5个文件,包含两个tbx自定义工具箱、一份Python源码脚本、一份安装指南PDF和一份操作演示PPT,压缩包仅158KB,轻量易分发。其中tbx可直接添加到ArcGIS自定义工具箱中双击运行,py源码便于二次修改与学习转换逻辑,PDF与PPT则辅助理解安装与使用流程。目前已有2717人学习下载,说明该工具在kml转shp这一常见需求中具备较高实用性。读者可获得一套开箱即用的转换工具,同时通过源码与文档理解基于ArcGIS Python的实现思路,适合课程实验、项目数据预处理及日常空间数据格式转换场景。
1. 从 KML 到 SHP:为什么你导出的图层总在 ArcGIS 里“缺胳膊少腿”
手里拿到一个kml格式转shp格式神器.zip,多数人第一反应是双击解压、找个 exe 或脚本跑一下,然后拖进 ArcGIS 看结果。但真正在一线干过 GIS 数据交付的人都清楚,KML 和 SHP 之间隔着的不是一次格式转换,而是两套完全不同的数据模型:KML 是 Google Earth 生态里的 XML 描述语言,天生带样式、带三维、带网络链接;SHP 是 Esri 的经典矢量格式,一个图层只能装一种几何类型,属性字段名还被限制在 10 个字符以内。所以“神器”能不能用,关键不在它转得快不快,而在它有没有替你处理坐标系、几何类型拆分、字段截断和中文字段编码这几件事。这份资源适合手里有 Google Earth 标绘的路线、点位、行政区边界,需要落到 ArcGIS 或 QGIS 里做统计、出图、入库的从业者;如果你只是想把 KML 丢进 Google Earth 看一眼,那完全没必要转。下面按“它是什么、怎么用、坑在哪”的顺序拆开讲,中间会给出可抄作业的命令和参数。
2. 先搞懂 KML、KMZ 与 SHP 的几何映射关系
2.1 KML 的几何类型和 SHP 的“单类型”约束
KML 里一个<Placemark>可以装Point、LineString、Polygon、MultiGeometry,甚至一个文件里混着点、线、面。SHP 不行,一个.shp只能是一种几何类型,点图层、线图层、面图层必须分开存。这就是为什么很多人转完发现“点怎么跑到线图层里去了”——转换工具要么按第一个几何类型硬转,要么直接丢弃不匹配的要素。常见做法是转换前先按几何类型把 KML 拆成多个文件,或者选一个支持自动分层的工具。判断方法很简单:用文本编辑器打开 KML,搜<Point>、<LineString>、<Polygon>各出现多少次,心里先有数。
2.2 坐标系:KML 永远是 WGS84 经纬度
KML 规范强制使用 WGS84 地理坐标系,单位是度。SHP 的.prj文件可以定义任意投影,比如 CGCS2000 高斯克吕格、Web Mercator。转换时如果工具不写.prj,ArcGIS 会当成“未知坐标系”,你后续做面积量算、距离统计全是错的。我一般会在转换后立刻用ogrinfo看一眼:
ogrinfo -al -so output.shp输出里Layer SRS如果是(unknown),就得手动补.prj。补的方法是用 QGIS 打开后“另存为”,坐标系选EPSG:4326,或者用gdalsrsinfo生成:
gdalsrsinfo EPSG:4326 -o wkt > output.prj参数说明:-o wkt输出 WKT 格式,ArcGIS 和 QGIS 都认;EPSG:4326就是 WGS84 经纬度。注意别直接拿一个空.prj糊弄,字段内容不对照样报错。
2.3 属性字段:10 字符限制和中文字段名
SHP 的 DBF 字段名最长 10 个字符,超出部分会被截断,而且不支持中文名。KML 的<Data name="...">里经常是“路线名称”“采集时间”这种中文,转换后要么变乱码,要么变成Field1、Field2。常见做法是转换前先把 KML 里的字段名改成英文短名,或者转换后用 QGIS 字段计算器重命名。如果工具支持映射表,优先用映射表,别指望自动识别。
3. 用 GDAL/OGR 命令行完成 KML 转 SHP 的完整流程
3.1 环境准备与版本确认
这份kml格式转shp格式神器.zip里如果带的是 GDAL 封装工具,底层多半还是ogr2ogr。先确认版本,老版本对 KML 的MultiGeometry支持有差异:
ogr2ogr --version建议 GDAL 3.0 以上。如果输出是GDAL 2.x,遇到复杂 KML 可能丢要素。Windows 下可以用 OSGeo4W 装,macOS 用brew install gdal,Linux 直接apt install gdal-bin。
3.2 一条命令转点图层
假设 KML 里全是点,目标坐标系用 WGS84:
ogr2ogr -f "ESRI Shapefile" points.shp source.kml \ -nln points \ -a_srs EPSG:4326 \ -lco ENCODING=UTF-8逻辑说明:-f "ESRI Shapefile"指定输出格式;-nln points指定图层名,避免默认用文件名导致中文乱码;-a_srs EPSG:4326强制写入坐标系;-lco ENCODING=UTF-8让 DBF 用 UTF-8 编码,ArcGIS 10.2 以后能正常读中文。如果 KML 里混了几何类型,这条命令只会转出第一种,其余静默丢弃,所以下一步必须做类型检查。
3.3 按几何类型拆分再转
先用ogrinfo看 KML 里有哪些几何类型:
ogrinfo -al -so source.kml输出里Geometry:会列出Point、Line String、Polygon等。然后分别转:
ogr2ogr -f "ESRI Shapefile" lines.shp source.kml \ -where "OGR_GEOMETRY='LineString'" \ -nln lines -a_srs EPSG:4326 -lco ENCODING=UTF-8 ogr2ogr -f "ESRI Shapefile" polygons.shp source.kml \ -where "OGR_GEOMETRY='Polygon'" \ -nln polygons -a_srs EPSG:4326 -lco ENCODING=UTF-8参数说明:-where "OGR_GEOMETRY='LineString'"是 OGR 的几何类型过滤表达式,注意大小写和引号嵌套;LineString对应 KML 的<LineString>,Polygon对应<Polygon>。如果 KML 里是MultiGeometry包着线和面,这个过滤可能失效,需要先用ogr2ogr转成 GeoJSON 再处理,或者用 QGIS 手动炸开。
3.4 KMZ 的解压与直接读取
KMZ 就是 ZIP 压缩的 KML,GDAL 可以直接读,但有些版本需要先解压:
unzip source.kmz -d source_kmz ogr2ogr -f "ESRI Shapefile" output.shp source_kmz/doc.kml \ -a_srs EPSG:4326 -lco ENCODING=UTF-8注意 KMZ 里可能包含多个 KML 和图片资源,doc.kml是主文件,但名字不固定,解压后先ls看一眼。如果工具包里的“神器”是图形界面,这一步它应该自动做了,但你要知道它背后干了什么,出问题才能定位。
4. 避坑与排查:KML 转 SHP 最常见的五类翻车
4.1 转完要素数量对不上
现象:KML 里明明有 200 个点,SHP 属性表只有 150 条。原因:KML 里有MultiGeometry或嵌套<Folder>,工具只读了第一层。解决:用ogrinfo -al source.kml | grep -c "OGRFeature"数一下原始要素数,再和 SHP 对比;如果不等,改用 QGIS 的“按几何类型拆分”或先用ogr2ogr转 GeoJSON 再转 SHP。
4.2 中文属性变问号或乱码
现象:ArcGIS 打开属性表,“路线名称”显示成????。原因:DBF 编码不是 UTF-8,或者 ArcGIS 默认用系统编码读。解决:转换时加-lco ENCODING=UTF-8;如果已经转了,用 QGIS 打开后“导出要素为”重新选 UTF-8;ArcGIS 里可以用“转换坐标系”工具顺带重写编码,但最稳的还是重转。
4.3 坐标系丢失导致面积量算错误
现象:在 ArcGIS 里算面积,结果单位是“平方度”,数值小得离谱。原因:.prj缺失或写错。解决:用gdalsrsinfo EPSG:4326 -o wkt > output.prj补上;如果要做面积统计,建议转成投影坐标系,比如EPSG:4547(CGCS2000 3 度带),命令里把-a_srs换成-t_srs EPSG:4547,让 GDAL 自动做投影变换。
4.4 字段名被截断后无法识别
现象:KML 里“采集时间”变成Field1,“采集人”变成Field2。原因:SHP 字段名 10 字符限制加中文不支持。解决:转换前用文本编辑器批量替换 KML 里的<Data name="采集时间">为<Data name="collect_t">,或者转换后在 QGIS 里用“重构字段”重命名。别在 ArcGIS 里直接改,容易把 DBF 写坏。
4.5 大文件转换卡死或内存溢出
现象:几百 MB 的 KML 转 SHP 时工具无响应。原因:KML 是 XML,DOM 解析吃内存。解决:先用ogr2ogr加-skipfailures跳过错误要素,或者用-limit分批转;更稳的做法是先用ogr2ogr转成 GeoPackage(.gpkg),再从 GPKG 转 SHP,GPKG 对大数据量友好得多。
ogr2ogr -f "GPKG" temp.gpkg source.kml -a_srs EPSG:4326 ogr2ogr -f "ESRI Shapefile" output.shp temp.gpkg -lco ENCODING=UTF-85. 进阶:批量转换、字段映射与 QGIS 统计路线公里数
5.1 批量转换多个 KML/KMZ
手里有几十个 KML 要转,一个个敲命令不现实。写个 bash 循环:
for f in *.kml *.kmz; do base="${f%.*}" ogr2ogr -f "ESRI Shapefile" "${base}.shp" "$f" \ -a_srs EPSG:4326 -lco ENCODING=UTF-8 -skipfailures done逻辑说明:${f%.*}去掉扩展名作为输出名;-skipfailures保证单个文件出错不中断整个批次。如果 KMZ 需要先解压,在循环里加unzip -o "$f" -d "${base}_tmp",再转${base}_tmp/doc.kml。注意输出目录别和输入混在一起,否则下一轮循环会把.shp也当输入。
5.2 字段映射:把 KML 的 Data 转成规范字段
KML 的<Data name="...">在 OGR 里会变成属性字段,但名字可能带空格或特殊字符。转换前用 Python 的xml.etree批量重命名:
import xml.etree.ElementTree as ET tree = ET.parse('source.kml') ns = {'kml': 'http://www.opengis.net/kml/2.2'} for data in tree.iter('{http://www.opengis.net/kml/2.2}Data'): name = data.get('name') if name == '路线名称': data.set('name', 'route_name') elif name == '采集时间': data.set('name', 'collect_t') tree.write('source_fixed.kml', encoding='utf-8', xml_declaration=True)参数说明:ns是 KML 的命名空间,iter遍历所有Data节点;data.set('name', ...)直接改属性名。改完再走ogr2ogr,字段名就规范了。注意备份原文件,别直接覆盖。
5.3 在 QGIS 里统计 KML 路线公里数
转成 SHP 后,用 QGIS 打开线图层,字段计算器新建字段length_km,表达式:
length(transform($geometry, 'EPSG:4326', 'EPSG:4547')) / 1000逻辑说明:transform把 WGS84 经纬度转成 CGCS2000 3 度带投影,单位是米;length算长度;除以 1000 得公里。如果线图层是MultiLineString,先用“多部件转单部件”炸开,否则长度会算成整个多部件的总和。这一步是很多做路线统计的人卡住的地方——直接对经纬度算长度,结果单位是度,毫无意义。
5.4 验证转换结果是否可用
转完别急着关工具,做三件事:第一,用ogrinfo -al -so output.shp看要素数和几何类型;第二,在 QGIS 里叠加 Google Satellite 或天地图底图,看位置对不对;第三,打开属性表,确认中文字段和数值字段没乱。我自己的习惯是每次转完都跑一遍ogrinfo,确认Feature Count和原始 KML 的Placemark数量一致,不一致就回头查MultiGeometry。从那以后我每次拿到 KML 都先数一遍几何类型再动手,省得返工。希望帮到你。
本文还有配套的精品资源,点击获取