Python实现Shp转GeoJSON:格式详解与代码转换指南

落日邮差
落日邮差
发布时间:2026-10-13| 2人浏览过
原创

本文详细解析GeoJSON的矢量数据格式规范,涵盖点、线、面及多边形等要素的结构定义。通过Python脚本示例,演示如何将ArcGIS常用的Shp文件转换为适用于Web可视化的GeoJSON格式,并结合Kepler.gl实现数据可视化展示,为空间数据处理提供实用参考。

Shp转GeoJSON概述

简介

Shp格式是地理信息系统(GIS)中广泛使用的数据格式,主要应用于ArcGIS等桌面软件。然而,在进行基于网页的空间数据可视化时,系统通常仅支持GeoJSON格式。JSON(JavaScript Object Notation)作为一种轻量级、易解析的数据交换格式,通过键值对和嵌套结构表示数据,被广泛应用于各个领域。GeoJSON则是基于JSON语法规范,专门用于存储矢量地理数据的格式。本文将重点介绍GeoJSON的语法规则,并展示如何利用Python完成从Shp到GeoJSON格式的转换。

Shp转GeoJSON

GeoJSON格式规范详解

2.1 GeoJSON格式说明

GeoJSON本质上是JSON的一种特定应用,其基本结构如下:


{
 "type": "FeatureCollection",
 "features": []
}

一个完整的GeoJSON文件最外层是一个字典对象。若将整个文件视为自顶向下的树状结构,其根节点包含键值对 "type":"FeatureCollection",以及存放所有要素的键值对 "features":[]。所有的矢量要素均存储在该列表中,每个要素本身也是一个字典对象。接下来我们将逐一介绍各类矢量要素在GeoJSON中的规范格式:

点要素(Point):

对于单个点要素,其结构如下:


{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"Point",
  "coordinates":[经度,纬度]
  }
 }

其中,properties对应的值包含该要素属性表中按顺序存储的属性值;geometry对应的值中,type字段指明了要素的具体类型;coordinates字段传入一个包含两个元素的列表,第一个元素代表经度,第二个元素代表纬度。

多点要素(MultiPoint):

多点要素是点要素的特殊情况。其geometry下的type属性值为"MultiPoint",coordinates属性传入的是一个二维列表。最内层的列表定义了每个点的经纬度坐标,具体格式如下:


{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"MultiPoint",
  "coordinates":[[经度1,纬度1],
    [经度2,纬度2]
   ]
  }
  }

线要素(LineString):

线要素记录了一条线上所有折点的经纬度信息。只需按顺序连接这些折点,即可还原线的形态。在GeoJSON中,线要素与多点要素在coordinates属性的格式上相同,区别在于geometry属性中的type值需传入"LineString",示例如下:


{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"LineString",
  "coordinates":[[经度1,纬度1],
  [经度2,纬度2],
  [经度3,纬度3],
  [经度4,,纬度4]]
  }
 }

多线要素(MultiLineString):

多线要素由多个线要素组合而成,因此其coordinates传入三维列表以组合多条线。对应的geometry下type属性值为"MultiLineString",格式如下:


{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"MultiLineString",
  "coordinates":
  [
   [
    [经度1,纬度1],
    [经度2,纬度2],
    [经度3,纬度3],
    [经度4,纬度4]
   ],
   [
    [经度5,纬度5],
    [经度6,纬度6]
   ]
  ]
    }
 }

多边形要素(Polygon):

多边形要素记录了构成多边形所有边缘折点的经纬度信息。其coordinates属性值为"Polygon",geometry下type属性格式为三维列表。第三层列表中嵌套的所有列表记录的经纬度按顺序连接即构成一个多边形。需要注意的是,多边形首尾折点的经纬度必须相同,才能形成闭合的多边形,示例如下:


{"type":"Feature",
 "properties":{value1,value2},
 "geometry":{
  "type":"Polygon",
  "coordinates":[
      [
       [经度1,纬度1],
       [经度2,纬度2],
       [经度3,纬度3],
       [经度4,纬度4],
       [经度1,纬度1]
      ]
      ]
  }
 }

多多边形要素(MultiPolygon):

多多边形的格式为四维列表,其geometry下type属性传入"MultiPolygon"(注:原文拼写为MultiPloygon,此处修正为标准拼写或保留原意但指出规范)。由于多多边形要素存在几种特殊情况,下文将在geojson.io中进行对应GeoJSON数据的可视化,以便更直观地理解:

互不重叠的两个多边形:

以下是互不重叠的两个多边形的示例图:

对应的GeoJSON数据如下:


{
 "type": "Feature",
 "properties": {},
 "geometry": {
 "type": "MultiPolygon",
 "coordinates":
 [ 
  [
   [
    [102.74414062499999,36.217687122250574],
    [102.7001953125,35.585851593232356],
    [104.8590087890625,35.496456056584165],
    [104.96337890625,36.24427318493909],
    [102.74414062499999,36.217687122250574]
   ]
  ],
  [
   [
    [102.6397705078125,35.074964853989556],
    [103.0352783203125,34.23905366851639],
    [105.00732421875,34.24813554589752],
    [105.3973388671875,35.77771427205079],
    [104.556884765625,35.05698043137265],
    [102.711181640625,35.16931803601131],
    [102.6397705078125,35.074964853989556]
   ]
  ]
 ]
    }
}

从数据可以看出,当多个多边形不重叠时,直接将两个多边形要素对应的三维列表存放在最外层列表下即可。

互有重叠的两个多边形:

互有重叠的多个多边形要素格式与多个不重叠的多边形类似,效果如下:

 

对应的GeoJSON数据如下:


{
 "type": "Feature",
 "properties": {},
 "geometry": {
 "type": "MultiPolygon",
 "coordinates": [
  [
  [
   [101.6455078125,27.68352808378776],
   [114.78515624999999,27.68352808378776],
   [114.78515624999999, 35.209721645221386],
   [101.6455078125,35.209721645221386],
   [101.6455078125,27.68352808378776]
  ]
  ],
  [
  [
   [104.2822265625,30.107117887092357],
   [108.896484375,30.107117887092357],
   [108.896484375,33.76088200086917],
   [104.2822265625,33.76088200086917],
   [104.2822265625,30.107117887092357]
  ]
  ]
 ]
 }
}

有孔的多边形:

有孔的多边形在类别上同样归类到MultiPolygon。下面是一个示例图:

 

对应的GeoJSON数据如下。可以看出其与多个重叠多边形的区别在于,多边形矢量信息嵌套在第二层列表中,具体格式如下:


{
  "type": "Feature",
  "properties": {},
  "geometry": {
  "type": "MultiPolygon",
  "coordinates":
 [ 
  [
   [
    [101.6455078125,27.68352808378776],
    [114.78515624999999,27.68352808378776],
    [114.78515624999999,35.209721645221386],
    [101.6455078125,35.209721645221386],
    [101.6455078125,27.68352808378776]
   ],
   [
    [104.2822265625,30.107117887092357],
    [108.896484375,30.107117887092357],
    [108.896484375,33.76088200086917],
    [104.2822265625,33.76088200086917],
    [104.2822265625,30.107117887092357]
   ]
  ]
 ]
 }
}

Python实现Shp转换与可视化

2.2 将Shp格式转换为GeoJSON

在2.1节中,我们详细了解了矢量数据在GeoJSON中的具体表现形式。通过以下自编函数,以Shp文件名称(去除文件拓展名)、Shp文件编码、GeoJSON文件编码为输入参数,实现转换:


def Shp2JSON(filename,shp_encoding='utf-8',json_encoding='utf-8'):
 '''
 这个函数用于将shp文件转换为GeoJSON文件
 :param filename: shp文件对应的文件名(去除文件拓展名)
 :return:
 '''

 '''创建shp IO连接'''
 reader = shapefile.Reader(filename,encoding=shp_encoding)

 '''提取所有field部分内容'''
 fields = reader.fields[1:]

 '''提取所有field的名称'''
 field_names = [field[0] for field in fields]

 '''初始化要素列表'''
 buffer = []

 for sr in tqdm(reader.shapeRecords()):
  '''提取每一个矢量对象对应的属性值'''
  record = sr.record

  '''属性转换为列表'''
  record = [r.decode('gb2312','ignore') if isinstance(r, bytes)
     else r for r in record]

  '''对齐属性与对应数值的键值对'''
  atr = dict(zip(field_names, record))

  '''获取当前矢量对象的类型及矢量信息'''
  geom = sr.shape.__geo_interface__

  '''向要素列表追加新对象'''
  buffer.append(dict(type="Feature",
       geometry=geom,
       properties=atr))

 '''写出GeoJSON文件'''
 geojson = codecs.open(filename + "-geo.json","w", encoding=json_encoding)
 geojson.write(json.dumps({"type":"FeatureCollection",
        "features":buffer}) + '\n')
 geojson.close()
 print('转换成功!')

下面通过一个示例展示实际转换效果。使用的Shp数据为中国省份数据,在ArcGIS中的显示效果如下:

 


import shapefile
import json
import codecs

def Shp2JSON(filename,shp_encoding='utf-8',json_encoding='utf-8'):
 '''
 这个函数用于将shp文件转换为GeoJSON文件
 :param filename: shp文件对应的文件名(去除文件拓展名)
 :return:
 '''

 '''创建shp IO连接'''
 reader = shapefile.Reader(filename,encoding=shp_encoding)

 '''提取所有field部分内容'''
 fields = reader.fields[1:]

 '''提取所有field的名称'''
 field_names = [field[0] for field in fields]

 '''初始化要素列表'''
 buffer = []

 for sr in tqdm(reader.shapeRecords()):
  '''提取每一个矢量对象对应的属性值'''
  record = sr.record

  '''属性转换为列表'''
  record = [r.decode('gb2312','ignore') if isinstance(r, bytes)
     else r for r in record]

  '''对齐属性与对应数值的键值对'''
  atr = dict(zip(field_names, record))

  '''获取当前矢量对象的类型及矢量信息'''
  geom = sr.shape.__geo_interface__

  '''向要素列表追加新对象'''
  buffer.append(dict(type="Feature",
       geometry=geom,
       properties=atr))

 '''写出GeoJSON文件'''
 geojson = codecs.open(filename + "-geo.json","w", encoding=json_encoding)
 geojson.write(json.dumps({"type":"FeatureCollection",
        "features":buffer}) + '\n')
 geojson.close()
 print('转换成功!')


if __name__ == '__main__':
 import os
 os.chdir(r'C:\Users\hp\Desktop\飞线图素材')
 Shp2JSON(filename='bou2_4p.shp',
    shp_encoding='gbk',
    json_encoding='utf-8')

运行脚本后,同一目录下生成了对应的json文件:

 

将该文件导入Kepler.gl中进行可视化展示:


from keplergl import KeplerGl
import json
with open('bou2_4p.shp-geo.json') as b:
 data = json.load(b)
map1 = KeplerGl(height=700,data={'layer1':data});map1


总结

以上介绍了利用Python实现Shp格式向GeoJSON转换的方法,希望能对大家有所帮助。如有任何疑问,欢迎留言,小编会及时回复。感谢大家对本站的支持! 如果本文对您有帮助,欢迎转载,烦请注明出处,谢谢!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。