南通乡镇街道shp处理全流程:从解压到QGIS与坐标转换
2026/9/23 15:30:47 网站建设 项目流程

简介:面向地理信息系统使用者,这份压缩包提供南通市及下辖各区县、乡镇街道的矢量边界文件,适用于城市规划、地理信息可视化、区划统计等场景,可直接导入主流GIS平台使用。压缩包内共21个文件,包含矢量主文件、属性表、投影文件、索引文件等配套格式,能保证几何与属性数据完整加载,180KB的体积也便于快速获取。已有399人学习下载。数据经过整理制作,区分南通市区、各区县、各乡镇街道三个层级,可满足从宏观到微观的制图与查询需求,数据内含市域、区县和乡镇街道三级行政边界,既可用于整体市域分析,也能精细到乡镇街道尺度,节省大量搜寻时间,并附带后续数据问题支持,适合需要标准南通行政区划底图的科研、规划与项目人员。

1. 拿到“南通乡镇街道shp”之后,先别急着双击打开

你从公开渠道下载到“南通各乡镇、街道shp文件.rar”,第一反应可能是解压后扔进QGIS里看看边界长什么样。这个文件名的含义其实比表面复杂:rar压缩包里装的是一整套shapefile组件,而不是单张图片;真正决定它能不能用于制图、分析和Web发布的关键,是里边的坐标参考系统、DBF属性编码、行政区划字段结构,以及压缩包本身是否完整、解压后是否会被中文路径干扰。这篇内容会沿着“文件结构 — 验证解压 — QGIS预处理 — 批处理转换 — 自动巡检”的顺序,把这条链路完整走通。新手能照着命令做出可用shp,老手也可以从中提炼一套针对“省级/市级边界数据集”的处理模板。

2. rar里的shp不是单个文件:先理解Multi-file格式和坐标系

2.1 shapefile的三大件和若干附属文件

以“南通各乡镇、街道shp”为例,它实际是一组文件共用一个主文件名。最重要的三个是:

  • .shp:几何坐标本体,存储点、线或面;
  • .shx:几何索引,没有它很多软件拒绝读取;
  • .dbf:属性表,所有乡镇/街道名称、代码、面积统计字段都存在这里。

除此之外常见还有.prj(坐标系描述)、.cpg(DBF字符编码声明)、.sbn/.sbx(空间索引)、.qpj(QGIS专用投影描述)。如果你在解压后的目录里只看到一个.shp,那大概率是被邮件或网盘过滤掉了其他后缀,这种情况下应先解决文件缺失,而不是急着修复几何。

我一般会先用一个表格核对压缩包内的最小文件集,避免后续排查在错误方向上浪费时间。

扩展名必需性作用缺失后果
.shp必需几何坐标记录图层完全无法打开
.shx必需几何偏移索引部分软件报错“缺少.sbx”
.dbf必需属性字段内容能显示地图但打开属性表为空
.prj强烈建议空间参考描述图层被默认记为未知CRS
.cpg建议dbf编码声明中文乱码或读取失败
.qpj可选QGIS专用CRS补充不影响,QGIS会读.prj

2.2 乡镇和街道在属性表里怎么区分

行政区划数据通常带一个字符型字段,例如XZQDMXZQMCPACMC。乡镇、街道和开发区管委会在同一张表里混存,区分规则要看行政区划代码的第7到9位,通用国标代码中第7-9位表示乡级代码,比如320613001的末三位是某个街道,如果末位是“100”为主城区街道、其他为镇。不过不同来源的数据字段命名非常混乱,倒不一定按国标来。

更稳妥的做法是先打开dbf看一眼有哪些列,再决定筛选条件。可以先用QGIS加载或执行一下ogrinfo -so -al 文件名.shp查看字段列表。不要把“乡镇”和“街道”作为两套不同逻辑去处理,它们在本文件中大概率只是同一字段里的不同取值。

2.3 坐标系是决定面积和距离结果真正准确的前提

南通跨度和经度大约在120.8°到121.2°之间,纬度在31.9°到32.2°左右。如果数据自带.prj,常见有三种:CGCS2000地理坐标系(经纬度)、CGCS2000 3度分带投影坐标系、旧版西安80或WGS84。绝大多数从政府天地图分发的数据已经是CGCS2000,但你拿到手时未必能确认.prj内容正确。

投影坐标系的单位是米,适合算面积、算路网长度;地理坐标系单位是度,适合Web地图显示。要计算南通乡镇的行政面积,千万不能直接在WGS84经纬度上算,否则得到的“面积”单位是平方度,数值完全不可用。正确做法是统一转到一个适合江苏的投影坐标系,常见选EPSG:4529(CGCS2000 / 3-degree Gauss-Kruger zone 39),或者直接使用EPSG:3857做数量级估算。先明确这一点,后面的处理才谈得上可比性。

3. 用unrar和ogrinfo把rar包变成可信赖的shp目录

3.1 数据来源判断和下载前的检查

“南通各乡镇、街道shp文件.rar”这类文件经常出现在网盘、论坛和第三方GIS数据下载站。下载前要明确使用场景:如果只是做一张静态分布图,来源可靠即可;如果要用于项目交付或统计分析,建议从“天地图·江苏”或“全国地理信息资源目录服务系统”申请标准行政区划数据,避免因边界偏移造成问题。对于从论坛拿到的压缩包,我会先看一眼文件大小,通常全市乡镇级面数据在5MB到50MB之间,如果rar只有几百KB,大概率只是简化边界或缺少属性字段。

下载后不要用系统自带预览直接双击,先对压缩包做一次完整性和安全性检查。shp并不是可执行文件,但dbf里可能带公式或宏吗?一般不会,防的其实是解压时覆盖已有文件带来的路径混乱,以及压缩包内文件有中文名乱码。

3.2 用unrar按目录结构解压并处理中文名

Linux环境推荐用unrar7zip的p7zip-rar。下面是一套完整的解压链路:

# Ubuntu/Debian 安装 unrar 和 gdal-bin sudo apt update sudo apt install -y unrar gdal-bin # 测试压缩包完整性 unrar t 南通各乡镇、街道shp.rar # 列出压缩包内文件清单 unrar l 南通各乡镇、街道shp.rar # 解压到 output 目录,保留原目录结构 mkdir -p output unrar x -o+ 南通各乡镇、街道shp.rar output/

unrar t输出里如果出现CRC OK,说明文件没有被截断;出现CRC Failed时宁可重新下载。unrar l用于确认内部是否包含多层文件夹、是否存在同名shp分散在不同子目录的情况。x会保留压缩包内的目录路径,e则会把所有文件平铺到同一目录。对乡镇街道数据来说,我建议用x,因为一个rar里可能同时有“街道级”和“乡镇级”两套不同精度的边界,平铺后会把它们混在一起。

如果解压后文件名是类似Î÷³ÇÇø.shp的乱码,这是rar注释使用了GBK编码而系统区域设置为UTF-8导致的。可以通过设置本地环境变量再解压:

# 强制以GBK方式读取归档注释和文件名 LANG=zh_CN.GBK unrar x -o+ 南通各乡镇、街道shp.rar output/

如果系统没有GBK语言包,最省事的方法是改用Windows下的Bandizip或7-Zip解压,在解压选项里勾选“自动检测文件名编码”。这个问题在高版本GDAL中也有影响,所以一旦解压出现乱码,后续所有资源都会连带出问题。

unrar参数含义建议
x全路径解压保留目录层级
e忽略路径解压用于扁平目录
l列出压缩包内容解压前必做
t测试压缩包完整性解压前必做
-o+直接覆盖已有文件避免卡询问
-kb允许保留损坏文件不推荐,需人工复查
-p指定解压密码遇到加密包时使用

3.3 解压后立即用ogrinfo做一次冒烟测试

解压出来的shp是否能被GDAL正确识别,直接决定了后续能否进入Python、QGIS流程。运行:

ogrinfo -ro -so -al output/南通乡镇街道.shp

输出中重点看几项:

  • Geometry: PolygonMulti Polygon
  • Feature Count数量与南通乡镇街道实际数量是否接近(南通有约70多个乡级行政区,具体数量依年份略有浮动);
  • Layer SRS后是否出现CGCS2000,如果没有,则需要人为指定坐标系;
  • 属性字段里是否有包含“街道/镇/乡”的文本字段。

如果这里直接报Unable to open datasource,大概率是路径或文件名编码问题。先用ls -b看路径里是否有不可见字符,再用绝对路径重新执行。ogrinfo不对,之后所有代码都会跟着出错。

4. 在QGIS里把南通乡镇街道数据处理成能出图的图层

4.1 加载shp前先确认坐标参考和中文编码

QGIS加载shp最常规的方式是“图层 → 添加图层 → 添加矢量图层”,但实际上建议走“数据源管理器 → 矢量”选项卡,在这里可以预先设置编码。很多从公开下载站拿到的江苏数据,dbf编码是GBK,而QGIS默认可能识别为UTF-8,结果就是在属性表里看到 “通州区” 之类的中文乱码。

在数据源管理器中把“数据编码”改为UTF-8GBK后,先加载试一遍。如果还是乱码,关闭图层,打开dbf的.cpg文件确认编码声明。处理原则是:不修改shp文件本身,只让QGIS按正确编码读取。看到图层右下角显示EPSG:4490说明是CGCS2000地理坐标系,如果显示未知,需要右键图层 → 图层属性 → 源 → 分配坐标系。

实际操作中,南通数据可能会出现自动投影到WGS 84 / Pseudo-Mercator的情况。要确保面积计算正确,应先把项目CRS设置为EPSG:4529。在菜单“设置 → 选项 → 坐标参考系统”勾选“针对未知CRS始终弹出提示”,避免依赖QGIS自动猜测。

4.2 按区县筛选、统计字段并修正几何

打开属性表,用表达式选出特定区域。例如南通崇川区和海门区行政代码前缀不同,需要提取每个对象的乡镇级代码。假设字段叫XZQMC,筛选街道类型可以用:

"XZQMC" LIKE '%街道%'

这只是字符串匹配,更严谨的是在字段计算器里新写一个“乡镇级行政区划类型”字段:

if("XZQMC" LIKE '%街道%', '街道', if("XZQMC" LIKE '%镇%', '镇', '乡'))

字段计算器中的$area是项目CRS下的面积,直接用它算出的结果在EPSG:4326下不可信。我习惯在图层属性里复制这个shp,用“矢量几何 → 重新投影图层”输出成EPSG:4529的临时副本,再在字段计算器里用$area / 1000000得到平方千米。注意,这只是数值计算,真正决定精度的还是原始几何是否符合拓扑。

行政区划shp经常遇到两种问题:面与面之间有空隙或重叠,以及多部件几何里混入单部件。处理工具箱里有标准方案,我常用这几个算法:

QGIS处理算法算法ID用途
修复几何native:fixgeometries消除无效几何、修复自相交
删除重复几何native:deleteduplicategeometries去除同图形不同属性
消除native:eliminateselected按面积合并到相邻面
多环切割native:multiringbuffer不适用,这里仅举例
按位置选择native:selectbylocation用道路或点图层细化乡镇范围

修几何不是必做项,但只要后续做空间连接或拓扑叠加,就越早修越好。执行方法:处理工具箱 → 搜索“修复几何” → 选择输入图层,输出设为一个新的GeoPackage。修复后要素数量一般不变,但“无效几何”计数会被清零。

4.3 用PyQGIS脚本把修复几何纳入可重复流程

如果在QGIS里用鼠标点一遍流程,下次拿到另一份市级shp还要重复操作。可以用Python控制台写一段短脚本,把这套处理固化下来:

from qgis.core import QgsVectorLayer import processing src = QgsVectorLayer('output/南通乡镇街道.shp', 'nt', 'ogr') if not src.isValid(): raise RuntimeError('图层加载失败,先检查路径和编码') # 修复几何,并输出到GeoPackage out = 'output/nt_fixed.gpkg' params = { 'INPUT': src, 'OUTPUT': out, 'OUTPUT_TYPE': 3, # 对应“多部件”类型 } result = processing.run('native:fixgeometries', params) layer = QgsVectorLayer(result['OUTPUT'], 'fixed', 'ogr') print('修复后要素数:', layer.featureCount())

这段代码会从已有shp读取数据,修复后以GeoPackage格式输出。OUTPUT_TYPE参数在不同QGIS版本里不一定稳定,如果想要稳妥,可省略该参数,默认会尽量保持原几何类型。脚本的价值在于可重复执行,比如发现文件名编码问题后,不用重新走一遍界面流程。

5. 命令行和Python批量转换:南通shp转txt、kml、GeoJSON

5.1 ogr2ogr做投影转换和格式输出

GDAL工具里最常用的是ogr2ogr,它可以在不需要打开QGIS的前提下完成shp格式转换。这里使用最常见的“把乡镇shp转成GeoJSON并转成经纬度”操作:

# 将投影坐标系或未知坐标系强制转成WGS84,输出GeoJSON ogr2ogr -f GeoJSON -t_srs EPSG:4326 南通乡镇.geojson output/南通乡镇街道.shp # 输出到GeoPackage,并强制几何为MultiPolygon ogr2ogr -f GPKG -nlt PROMOTE_TO_MULTI 南通乡镇.gpkg output/南通乡镇街道.shp # 只保留指定字段,避免导出无关属性 ogr2ogr -f GeoJSON -select XZQMC,XZQDM 南通乡镇_简化.geojson output/南通乡镇街道.shp

-t_srs EPSG:4326会把源数据从任何已知CRS转到WGS84地理坐标系;-s_srs EPSG:4490可以在源文件缺少.prj时手动指定。-nlt PROMOTE_TO_MULTI会把所有Polygon提升为MultiPolygon,这能避免某些前端地图库对单个Polygon很挑剔。-select后接逗号分隔字段名,能有效精简GeoJSON体积和字段歧义。

5.2 geopandas读取、按区县筛选并导出KML/GeoJSON

Python侧可以用geopandas完成同样的工作,并且更适合在批量场景里做筛选、过滤和逻辑判断。以下脚本可以直接运行:

import geopandas as gpd import pandas as pd # 读取shp,注意指定编码;GDAL会自动读取.cpg,但手动指定更稳 gdf = gpd.read_file('output/南通乡镇街道.shp', encoding='utf-8') print('原始坐标系:', gdf.crs) # 强制转成WGS84经纬度,便于和通用地图底图叠加 gdf = gdf.to_crs(epsg=4326) # 选取南通市区的几个街道/镇合并为一个GeoJSON target = gdf[gdf['XZQMC'].str.contains('街道|镇', na=False)] target.to_file('南通市区.geojson', driver='GeoJSON', encoding='utf-8') # KML要求坐标必须为WGS84,否则Google Earth无法正确定位 target.to_file('南通乡镇.kml', driver='KML')

geopandasread_file底层也是GDAL,所以对shp的容错能力与ogrinfo一致。to_crs是延迟计算,不会修改原始数据;driver='KML'导出时如果字段名里含有非法XML字符,会报错,可先字段列重命名。KML对属性字段数量和名称有限制,不是所有shp都适合直接转KML,如果报错建议改转GeoJSON。

5.3 把属性表和安全区面积字段导出为txt

面向热词中“shp转txt”的需求,这里给一套可抄的完整脚本。它会把每个乡镇/街道的面积算成平方千米,以制表符分隔写入txt,同时保留一个WKT列以备后续看几何。

import geopandas as gpd # 用4529投影坐标系做面积计算 gdf = gpd.read_file('output/南通乡镇街道.shp', encoding='utf-8') gdf = gdf.to_crs(epsg=4529) # 添加面积字段(单位:km²) gdf['area_km2'] = gdf.geometry.area / 1_000_000 # 生成WKT文本,方便用普通文本工具校验 gdf['wkt'] = gdf.geometry.to_wkt() # 导出属性表,用UTF-8-BOM方便Excel直接打开 cols = ['XZQMC', 'XZQDM', 'area_km2'] gdf[cols].to_csv('乡镇面积.txt', sep='\t', index=False, encoding='utf-8-sig') # 输出GeoJSON同时保留面积字段 gdf.to_file('南通乡镇_带面积.geojson', driver='GeoJSON', encoding='utf-8')

这里面to_crs(epsg=4529)是关键,使用不同的CRS会导致面积值不同:在EPSG:4326下用area得到的是平方度,完全无意义;在EPSG:3857下得到的面积会比实际偏大,因为Web墨卡托在高纬度地区拉伸严重。江苏地区用高精度投影(如EPSG:4529)计算,乡镇面积误差通常在1%以内。encoding='utf-8-sig'是为了史学:不带BOM的utf-8在Excel里打开有概率中文乱码,这个细节在导出txt交付同行时很有用。

6. 一个验证技巧:用geopandas检查整个shp目录并输出txt报告

前面处理的是一个单独的shp,但rar包解压后可能出现三四十个shp,分散在不同目录。逐个打开检查不仅慢,还容易漏掉某个乱码文件。更实用的做法是写一个扫描器,把output目录下所有*.shp文件都读一遍,检查CRS、要素数、几何有效性,并生成一份txt报告。这样既能找出损坏文件,也能对比多个数据包的差异。

from pathlib import Path import geopandas as gpd root = Path('output') report_lines = [] for shp in sorted(root.rglob('*.shp')): try: gdf = gpd.read_file(shp, encoding='utf-8') valid = bool(gdf.geometry.is_valid.all()) crs = str(gdf.crs) report_lines.append( f"{shp.name}\t{len(gdf)}\t{crs}\t{valid}" ) except Exception as exc: report_lines.append(f"{shp.name}\t-\tERROR\t{type(exc).__name__}") with open('shp检查报告.txt', 'w', encoding='utf-8') as fh: fh.write("文件\t要素数\t坐标系\t几何有效\n") fh.write("\n".join(report_lines))

脚本的核心逻辑很简单:rglob递归寻找所有shp;read_file的异常捕获能识别出“文件被占用、字段编码错误、dbf缺失”等问题;is_valid.all()返回False时说明该文件中有部分面存在自相交或闭合错误,不能直接用于拓扑叠加。如果你发现某个shp在QGIS里能打开但检查报告里是无效几何,可以用前面第4节的修复几何算法归一化后再重新跑一遍扫描。

如果不满足于txt,还可以把这个报告写入GeoPackage,这样每个乡镇旁边都能挂上质量标签。做法是在循环里收集每个shp的中心点并附上质量属性,最后合并成一个gpd.GeoDataFrame导出为GeoPackage。这个思路适用于把多份shp合并成一个统一数据集,尤其适合“南通乡镇街道”这类需要反复对外提供切片数据的场景。实际执行时,最先需要解决的问题往往不是地理算法,而是把文件名、字段、编码统一:这份扫描报告就是用来摸清底数的最小工具集。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询