赞
踩
在处理地理空间数据时,KMZ 文件是一种常见的格式,用于存储地图和地理信息数据。KMZ 文件是 KML 文件的压缩版本,其中 KML(Keyhole Markup Language)用于描述地理数据的格式。本文将详细介绍如何使用 Python 处理 KMZ 文件,提取其中的地理数据,并将其可视化到地图上。本文的核心代码将涉及文件的解压、KML 文件的解析、GPS 数据的提取以及如何使用 Folium 库将数据展示到地图上。
KMZ 文件是 KML 文件的压缩版本,通常用于存储 Google Earth 或 Google Maps 中使用的地理信息数据。KMZ 文件可以包含一个或多个 KML 文件以及其他资源文件(如图片、图标等)。KML 文件是基于 XML 的格式,用于描述地理数据的标记、路径、区域等信息。
KML 文件由 XML 构成,用于存储地理数据,如地点标记、线条、区域、图像叠加等。KML 的基本结构包括:
在开始之前,确保你的 Python 环境中已经安装了以下依赖:
folium
:用于地图可视化xml.etree.ElementTree
:用于解析 XML 文件zipfile
:用于解压 KMZ 文件glob
:用于文件路径匹配可以使用以下命令安装所需的库:
pip install folium
import os
import glob
def find_kmz_files(directory):
# 使用 glob 模块查找指定目录下的所有 .kmz 文件
kmz_files = glob.glob(os.path.join(directory, '*.kmz'))
return kmz_files
.kmz
结尾的文件。glob
模块和通配符模式来匹配所有 KMZ 文件。import zipfile
def extract_kml_from_kmz(kmz_file_path):
# 解压 KMZ 文件
with zipfile.ZipFile(kmz_file_path, 'r') as kmz:
# 查找 KML 文件
kml_files = [name for name in kmz.namelist() if name.lower().endswith('.kml')]
if kml_files:
kml_file_path = kml_files[0]
kmz.extract(kml_file_path, os.path.dirname(kmz_file_path))
return os.path.join(os.path.dirname(kmz_file_path), kml_file_path)
return None
zipfile
模块打开 KMZ 文件,查找并解压 KML 文件。import xml.etree.ElementTree as ET def parse_kml(kml_file_path): gps_data = [] tree = ET.parse(kml_file_path) root = tree.getroot() # KML 的 XML namespace namespace = {'kml': 'http://earth.google.com/kml/2.2'} print(f"Root element: {root.tag}") # 查找所有 Placemark 元素 for placemark in root.findall('.//kml:Placemark', namespace): coordinates = placemark.find('.//kml:Point/kml:coordinates', namespace) if coordinates is not None: coords = coordinates.text.strip().split(',') if len(coords) >= 3: try: longitude = float(coords[0]) latitude = float(coords[1]) altitude = float(coords[2]) gps_data.append({ 'latitude': latitude, 'longitude': longitude, 'altitude': altitude }) except ValueError as e: print(f"Error parsing coordinates: {e}") return gps_data
xml.etree.ElementTree
解析 XML 格式的 KML 文件,通过查找 Placemark
元素和 coordinates
元素来获取地理数据。import folium from folium.features import CustomIcon def visualize_multiple_kmz_data(kmz_data_list): if not kmz_data_list: print("No GPS data available to visualize.") return # 计算所有经纬度的平均值,作为地图的中心 all_latitudes = [] all_longitudes = [] for kmz_data in kmz_data_list: latitudes = [data['latitude'] for data in kmz_data['gps_data']] longitudes = [data['longitude'] for data in kmz_data['gps_data']] all_latitudes.extend(latitudes) all_longitudes.extend(longitudes) avg_latitude = sum(all_latitudes) / len(all_latitudes) avg_longitude = sum(all_longitudes) / len(all_longitudes) map_center = [avg_latitude, avg_longitude] gps_map = folium.Map(location=map_center, zoom_start=14, tiles='OpenStreetMap') folium.TileLayer( tiles='https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', name='Google Satellite', attr='© Google' ).add_to(gps_map) folium.LayerControl().add_to(gps_map) # 为每个 KMZ 文件使用不同的颜色 colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple', 'white', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray'] for idx, kmz_data in enumerate(kmz_data_list): color = colors[idx % len(colors)] for data in kmz_data['gps_data']: folium.CircleMarker( [data['latitude'], data['longitude']], radius=0.5, # 半径大小 color=color, # 边框颜色 fill=True, fill_color=color, # 填充颜色 fill_opacity=0.8 ).add_to(gps_map) # 绘制路径线并添加箭头 for i in range(1, len(kmz_data['gps_data'])): start_point = kmz_data['gps_data'][i-1] end_point = kmz_data['gps_data'][i] # 绘制线条 folium.PolyLine( locations=[(start_point['latitude'], start_point['longitude']), (end_point['latitude'], end_point['longitude'])], color=color, weight=2 ).add_to(gps_map) # 添加箭头 folium.Marker( location=[(start_point['latitude'] + end_point['latitude']) / 2, (start_point['longitude'] + end_point['longitude']) / 2], icon=CustomIcon('https://upload.wikimedia.org/wikipedia/commons/e/e5/Black_triangle_pointing_right.svg', icon_size=(10, 10), icon_anchor=(5, 5)) ).add_to(gps_map) gps_map.save('multiple_kmz_map.html') print("GPS map saved as 'multiple_kmz_map.html'.")
folium.Map
创建地图,并添加地图图层。CircleMarker
的形式添加到地图上。绘制路径线,并在路径中添加箭头指示方向。
两个kmz文件:
其中一个kmz文件解压,会看到有一个kml文件:
kml文件打开,会看到一些关键信息,以下是部分信息截图:
import os import glob import folium import zipfile import xml.etree.ElementTree as ET from folium.features import CustomIcon def find_kmz_files(directory): kmz_files = glob.glob(os.path.join(directory, '*.kmz')) return kmz_files def extract_kml_from_kmz(kmz_file_path): with zipfile.ZipFile(kmz_file_path, 'r') as kmz: kml_files = [name for name in kmz.namelist() if name.lower().endswith('.kml')] if kml_files: kml_file_path = kml_files[0] kmz.extract(kml_file_path, os.path.dirname(kmz_file_path)) return os.path.join(os.path.dirname(kmz_file_path), kml_file_path) return None def parse_kml(kml_file_path): gps_data = [] tree = ET.parse(kml_file_path) root = tree.getroot() namespace = {'kml': 'http://earth.google.com/kml/2.2'} for placemark in root.findall('.//kml:Placemark', namespace): coordinates = placemark.find('.//kml:Point/kml:coordinates', namespace) if coordinates is not None: coords = coordinates.text.strip().split(',') if len(coords) >= 3: try: longitude = float(coords[0]) latitude = float(coords[1]) altitude = float(coords[2]) gps_data.append({ 'latitude': latitude, 'longitude': longitude, 'altitude': altitude }) except ValueError as e: print(f"Error parsing coordinates: {e}") return gps_data def visualize_multiple_kmz_data(kmz_data_list): if not kmz_data_list: print("No GPS data available to visualize.") return all_latitudes = [] all_longitudes = [] for kmz_data in kmz_data_list: latitudes = [data['latitude'] for data in kmz_data['gps_data']] longitudes = [data['longitude'] for data in kmz_data['gps_data']] all_latitudes.extend(latitudes) all_longitudes.extend(longitudes) avg_latitude = sum(all_latitudes) / len(all_latitudes) avg_longitude = sum(all_longitudes) / len(all_longitudes) map_center = [avg_latitude, avg_longitude] gps_map = folium.Map(location=map_center, zoom_start=14, tiles='OpenStreetMap') folium.TileLayer( tiles='https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}', name='Google Satellite', attr='© Google' ).add_to(gps_map) folium.LayerControl().add_to(gps_map) colors = ['red', 'blue', 'green', 'purple', 'orange', 'darkred', 'lightred', 'beige', 'darkblue', 'darkgreen', 'cadetblue', 'darkpurple', 'white', 'pink', 'lightblue', 'lightgreen', 'gray', 'black', 'lightgray'] for idx, kmz_data in enumerate(kmz_data_list): color = colors[idx % len(colors)] for data in kmz_data['gps_data']: folium.CircleMarker( [data['latitude'], data['longitude']], radius=0.5, color=color, fill=True, fill_color=color, fill_opacity=0.8 ).add_to(gps_map) for i in range(1, len(kmz_data['gps_data'])): start_point = kmz_data['gps_data'][i-1] end_point = kmz_data['gps_data'][i] folium.PolyLine( locations=[(start_point['latitude'], start_point['longitude']), (end_point['latitude'], end_point['longitude'])], color=color, weight=2 ).add_to(gps_map) folium.Marker( location=[(start_point['latitude'] + end_point['latitude']) / 2, (start_point['longitude'] + end_point['longitude']) / 2], icon=CustomIcon('https://upload.wikimedia.org/wikipedia/commons/e/e5/Black_triangle_pointing_right.svg', icon_size=(10, 10), icon_anchor=(5, 5)) ).add_to(gps_map) gps_map.save('multiple_kmz_map.html') print("GPS map saved as 'multiple_kmz_map.html'.") if __name__ == '__main__': directory_path = "F:\\notebookComputer\\20240723" kmz_files = find_kmz_files(directory_path) if kmz_files: kmz_data_list = [] for kmz_file_path in kmz_files: kml_file_path = extract_kml_from_kmz(kmz_file_path) if kml_file_path: parsed_gps_data = parse_kml(kml_file_path) print(f"Parsed GPS data: {parsed_gps_data}") kmz_data_list.append({ 'file_name': os.path.basename(kmz_file_path), 'gps_data': parsed_gps_data }) if kmz_data_list: visualize_multiple_kmz_data(kmz_data_list) else: print("No GPS data available to visualize.") else: print(f"No .kmz files found in directory: {directory_path}")
在代码执行完毕后,将会生成一个名为 multiple_kmz_map.html
的文件,该文件可以用浏览器打开以查看地图上的标记点和路径。地图将会显示所有 KMZ 文件中提取的 GPS 数据,每个文件的标记点使用不同的颜色表示。
multiple_kmz_map.html文件不好截图如下:
浏览器打开multiple_kmz_map.html文件效果图如下:
本文详细介绍了如何使用 Python 处理 KMZ 文件,提取其中的 GPS 数据,并通过 Folium 库将其可视化。通过将 KMZ 文件中的地理数据转换为地图标记点和路径线,我们可以更直观地分析和展示地理数据。未来的工作可以包括支持更多的地理数据格式、添加更多的地图样式和功能、以及优化代码的性能和可读性。根据需求,文章可以继续扩展,以包含更多的技术细节、优化建议和实际应用场景的分析。
欢迎点赞|关注|收藏|评论,您的肯定是我创作的动力 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。