简介:这份全国矢量地图SHP文件包面向GIS从业者、地理科研人员及城市规划学习者,提供覆盖全国范围的行政边界、路网、河网与水系空间数据,可直接用于地图制作、空间分析与规划决策等场景。压缩包共113个文件,约10.49MB,以shp、shx、dbf、prj、sbn、sbx等Shapefile核心与索引文件为主,分别承载几何对象、属性表、坐标系统与空间索引信息,另含少量adf、xml、mxd等辅助文件,便于在ArcGIS、QGIS等软件中直接导入与可视化。资源涵盖省级、县级行政区划多边形,地级市与县级驻地位置点,以及各级河流水系和公路铁路线要素,属性中带有名称、行政级别、里程等字段,可支撑区域分布研究、公共服务设施布局、洪水预警与交通路径优化等分析。目前已有5828人学习下载,适合需要快速获取全国基础地理底图、开展空间查询与模型构建的用户参考使用。
1. 全国矢量地图 SHP 文件到底装了什么:从行政边界到水系路网的落地判断
做 GIS 项目的人大概都经历过这种时刻:底图一加载,省界缺一块、河流断成几截、路网只有主干道,汇报时被问“这数据哪来的”只能含糊其辞。全国矢量地图 SHP 文件这套资源,解决的就是这个尴尬——它把行政边界、路网、河网、水系四类基础地理要素打包成标准 Shapefile,拿到手就能往 QGIS、ArcGIS 或者 PostGIS 里灌。适合谁?做区域规划出图的、跑空间分析的、搭 WebGIS 底图的,以及需要一份离线可用、不依赖在线瓦片服务的从业者。SHP 作为 Esri 定义的开放格式,兼容性极强,但它的坑也恰恰藏在“看起来能用”这四个字里。下面按我实际拆包和入库的顺序,把这份资源从结构到用法讲透。
2. 拆包先看坐标系与图层结构:别让第一个 shp 就翻车
拿到压缩包,很多人第一反应是双击打开。我一般会先解压到独立目录,用命令行把文件清单和坐标系信息摸清楚,再决定怎么用。这一步花五分钟,能省后面两小时排查。
2.1 文件清单与命名规律
Shapefile 不是单个文件,而是一组同名文件:.shp存几何、.shx存索引、.dbf存属性、.prj存坐标系。全国矢量地图通常按要素类型分目录,常见结构是行政边界一个文件夹、路网一个、河网和水系各一个。解压后先跑一遍清单:
# 列出所有 shp 文件及其配套文件,确认没有缺 .prj 或 .dbf find ./全国矢量地图 -name "*.shp" -exec ls -lh {} \; # 单独检查每个图层的坐标系定义文件是否存在 find ./全国矢量地图 -name "*.prj" -exec cat {} \;逻辑说明:find按扩展名过滤,-exec ls -lh把每个 shp 的大小和权限打出来,方便判断图层是否完整。参数上,-name "*.shp"只匹配几何文件,但配套的.dbf、.prj必须同名同目录,缺一个都会导致属性表或坐标系丢失。如果某个图层没有.prj,QGIS 会提示“未知坐标系”,这时候不能瞎猜,得用下一步的坐标值反推。
2.2 用 ogrinfo 确认坐标系和要素数量
命令行工具 GDAL/OGR 是拆 GIS 资源的瑞士军刀。装好 GDAL 后,用ogrinfo看图层摘要:
# 查看单个图层的坐标系、几何类型、要素总数 ogrinfo -so -al ./全国矢量地图/行政边界/全国省界.shp # 批量查看所有图层的摘要,输出到文本方便对比 for f in $(find ./全国矢量地图 -name "*.shp"); do echo "===== $f =====" ogrinfo -so -al "$f" | grep -E "Layer name|Geometry|Feature Count|PROJCRS|GEOGCRS" done逻辑说明:-so只输出摘要不读几何,-al遍历所有图层。grep抓取图层名、几何类型、要素数和坐标系名称。参数上,如果输出里出现GEOGCRS且带WGS 84,说明是地理坐标系(经纬度);出现PROJCRS且带CGCS2000或Albers,说明是投影坐标系(米为单位)。全国范围数据常见的是CGCS2000地理坐标或Albers等积投影。这一步的结论直接决定后面要不要做坐标转换——如果行政边界是经纬度、路网是投影坐标,直接叠图必然错位。
2.3 属性表字段的取舍
SHP 的.dbf对字段名长度有限制(最多 10 个字符),中文资源里常见NAME、CODE、ADCODE这类缩写。用ogrinfo不带-so可以看前几条记录:
# 查看属性表字段定义和前 3 条记录 ogrinfo -al -fid 1 ./全国矢量地图/行政边界/全国省界.shp逻辑说明:-fid 1只读第一条要素,输出里Field段列出所有字段名和类型。如果字段名是乱码,多半是.dbf的编码问题(常见 GBK 或 UTF-8),需要在 QGIS 里手动指定编码,或者用ogr2ogr转换时加-lco ENCODING=UTF-8。这一步别跳过,属性字段决定了你后面能不能按行政区代码做关联查询。
3. 入库与坐标转换:把 SHP 灌进 PostGIS 的完整链路
文件能打开只是第一步,真正做分析得入库。PostGIS 是开源 GIS 分析的首选,下面从建库到导入再到坐标转换,走一遍可复现的流程。
3.1 建库与扩展启用
-- 创建专用数据库 CREATE DATABASE gis_basemap WITH ENCODING 'UTF8'; -- 连接到该库后启用 PostGIS 扩展 \c gis_basemap CREATE EXTENSION IF NOT EXISTS postgis; CREATE EXTENSION IF NOT EXISTS postgis_transform; -- 坐标转换需要 -- 确认 PostGIS 版本 SELECT PostGIS_Full_Version();逻辑说明:ENCODING 'UTF8'保证中文属性不乱码。postgis_transform扩展提供ST_Transform函数,做坐标系转换必须装。参数上,如果服务器是 PostgreSQL 12 以上,PostGIS 3.x 默认包含 transform 功能,但显式启用更稳妥。建完库先跑PostGIS_Full_Version()确认版本,避免后面函数不存在。
3.2 用 ogr2ogr 批量导入并指定 SRID
# 导入行政边界,指定源 SRID 为 4326(WGS84 经纬度),目标 SRID 为 4490(CGCS2000) ogr2ogr -f "PostgreSQL" PG:"host=localhost dbname=gis_basemap user=postgres password=yourpass" \ ./全国矢量地图/行政边界/全国省界.shp \ -nln admin_boundary \ -s_srs EPSG:4326 \ -t_srs EPSG:4490 \ -lco GEOMETRY_NAME=geom \ -lco FID=gid \ -lco PRECISION=NO \ -progress # 导入路网,假设源数据已是投影坐标,直接指定 SRID ogr2ogr -f "PostgreSQL" PG:"host=localhost dbname=gis_basemap user=postgres password=yourpass" \ ./全国矢量地图/路网/全国主要道路.shp \ -nln road_network \ -s_srs EPSG:4490 \ -lco GEOMETRY_NAME=geom \ -lco FID=gid \ -nlt MULTILINESTRING \ -progress逻辑说明:-nln指定目标表名,-s_srs是源坐标系,-t_srs是目标坐标系。-lco是图层创建选项,GEOMETRY_NAME=geom统一几何字段名,FID=gid用自增主键替代原 FID。-nlt MULTILINESTRING强制线要素类型,避免路网里混入点或面导致导入失败。参数上,PRECISION=NO关闭数值精度截断,保留原始坐标精度。如果导入报“SRID 不存在”,说明目标库的spatial_ref_sys表里没有对应 EPSG 码,需要手动插入或改用已有 SRID。
3.3 坐标转换的验证查询
导入后必须验证坐标是否正确,不能只看导入成功:
-- 检查行政边界的坐标系和范围 SELECT ST_SRID(geom) AS srid, ST_XMin(ST_Extent(geom)) AS xmin, ST_YMin(ST_Extent(geom)) AS ymin, ST_XMax(ST_Extent(geom)) AS xmax, ST_YMax(ST_Extent(geom)) AS ymax FROM admin_boundary; -- 如果范围值在 73-135 和 3-54 之间,说明是经纬度;如果在百万级,说明是投影坐标 -- 验证路网和行政边界是否在同一坐标系下 SELECT ST_SRID(geom) FROM road_network LIMIT 1;逻辑说明:ST_Extent返回图层外包框,ST_XMin等取出四至。全国经纬度范围大致是东经 73 到 135、北纬 3 到 54,如果输出值在这个区间,说明是地理坐标系;如果 X 值在几十万到几百万,说明是投影坐标(单位米)。两个图层 SRID 不一致时,用ST_Transform统一:
-- 把路网转换到与行政边界相同的坐标系 ALTER TABLE road_network ALTER COLUMN geom TYPE geometry(MultiLineString, 4490) USING ST_Transform(geom, 4490);参数上,4490是 CGCS2000 地理坐标的 EPSG 码,如果行政边界用的是 Albers 投影,这里要换成对应的投影 EPSG 码。转换前建议先备份表,ALTER COLUMN TYPE在大表上会重写全表,耗时较长。
4. 路网与水系的拓扑检查:别让断线和自相交毁掉分析
基础地理数据最怕的不是缺数据,而是几何有问题。路网断线、水系自相交、行政边界重叠,这些在出图时看不出来,一跑网络分析或叠加分析就报错。下面是我常用的检查流程。
4.1 用 ST_IsValid 批量筛查无效几何
-- 统计各图层的无效几何数量 SELECT 'admin_boundary' AS layer, COUNT(*) AS invalid_count FROM admin_boundary WHERE NOT ST_IsValid(geom) UNION ALL SELECT 'road_network', COUNT(*) FROM road_network WHERE NOT ST_IsValid(geom) UNION ALL SELECT 'river_network', COUNT(*) FROM river_network WHERE NOT ST_IsValid(geom); -- 查看具体无效原因 SELECT gid, ST_IsValidReason(geom) AS reason FROM road_network WHERE NOT ST_IsValid(geom) LIMIT 10;逻辑说明:ST_IsValid返回布尔值,ST_IsValidReason给出具体原因(如 Self-intersection、Ring Self-intersection)。参数上,路网常见的无效原因是自相交和重复节点,水系常见的是环未闭合。查出问题后,用ST_MakeValid修复:
-- 修复无效几何并更新回原表 UPDATE road_network SET geom = ST_MakeValid(geom) WHERE NOT ST_IsValid(geom);注意:ST_MakeValid可能把线要素转成多线或几何集合,修复后要检查几何类型是否一致,必要时用ST_CollectionExtract提取线要素。
4.2 路网连通性检查
网络分析要求路网在节点处连通,但 SHP 数据常见“看起来连着、实际有微小缝隙”的情况。用ST_Intersects和容差判断:
-- 找出与其他路段不相接的孤立路段(容差 0.0001 度) SELECT a.gid FROM road_network a WHERE NOT EXISTS ( SELECT 1 FROM road_network b WHERE a.gid <> b.gid AND ST_DWithin(a.geom, b.geom, 0.0001) );逻辑说明:ST_DWithin判断两个几何在指定距离内是否相交,容差0.0001度约等于 10 米(在赤道附近)。参数上,容差太大会把平行不相交的路误判为连通,太小则漏掉真实缝隙。我一般先用0.0001跑一遍,看孤立路段数量,如果占比超过 5%,说明数据本身断裂严重,需要回到源头处理或手动连接。
4.3 水系与行政边界的叠加验证
水系和行政边界叠加时,常见问题是河流穿过省界但属性表里没有对应省代码。用空间连接补全:
-- 给河网添加所在省代码字段 ALTER TABLE river_network ADD COLUMN province_code VARCHAR(10); UPDATE river_network r SET province_code = a.adcode FROM admin_boundary a WHERE ST_Intersects(r.geom, a.geom);逻辑说明:ST_Intersects判断河流与省界是否相交,UPDATE ... FROM把匹配的省代码写入河网表。参数上,如果一条河流跨多个省,这条语句只会写入其中一个匹配值,需要改用ST_Within或按长度占比拆分。这一步的坑在于:行政边界如果有重叠或缝隙,空间连接会漏掉部分河流,所以前面第 4.1 步的几何修复必须做在前面。
5. 避坑与常见问题:拆包到入库踩过的五个坑
这一章按「现象 → 原因 → 解决」写,都是我实际拆包时遇到过的。
坑一:QGIS 打开中文属性乱码。现象是.dbf里的省名字段显示为问号或方块。原因是 Shapefile 的.dbf默认用系统编码,中文 Windows 下是 GBK,而 QGIS 默认按 UTF-8 读。解决:在 QGIS 图层属性里把编码改为 GBK,或者用ogr2ogr转换时加-lco ENCODING=UTF-8重新导出。
坑二:导入 PostGIS 后坐标范围是百万级,但行政边界应该是经纬度。现象是ST_Extent输出 X 值在 500000 左右。原因是源数据本身就是投影坐标,但.prj文件缺失或错误,ogr2ogr按默认 SRID 处理了。解决:先用ogrinfo确认.prj内容,如果缺失,根据坐标范围反推投影类型(全国范围常见 Albers 或 Lambert),手动指定-s_srs。
坑三:路网导入后网络分析报“未连通”。现象是pgr_createTopology执行后大量路段孤立。原因是路网在节点处有微小缝隙,或者交叉口没有打断。解决:先用ST_DWithin查孤立路段,再用ST_Snap把节点吸附到容差范围内,或者用pgr_nodeNetwork在交叉口自动打断。
坑四:水系图层和行政边界叠加后面积对不上。现象是统计某省水域面积时结果偏小。原因是水系数据里湖泊和河流分开存储,河流是线要素没有面积,湖泊是面要素但可能被省界切割。解决:线状河流用ST_Buffer生成缓冲区再算面积,面状湖泊用ST_Intersection与省界求交后再ST_Area。
坑五:批量导入时部分图层报“字段名重复”。现象是ogr2ogr导入第二个图层时提示字段冲突。原因是多个 SHP 的.dbf里有同名字段(如NAME),PostgreSQL 不允许同表重复列名。解决:导入时用-select只选需要的字段,或者用-sql重命名字段。我一般会在导入前用ogrinfo把每个图层的字段列出来,手动映射。
6. 进阶用法:用 QGIS 表达式和 PostGIS 函数做批量出图与统计
数据入库只是起点,真正省时间的是把重复出图和统计自动化。这一章给两个我常用的技巧,一个在 QGIS 里用表达式批量标注,一个在 PostGIS 里用窗口函数做分省统计。
6.1 QGIS 表达式批量标注行政边界
在 QGIS 里加载admin_boundary图层,打开标注引擎,用表达式组合省名和代码:
-- QGIS 标注表达式 "NAME" || '\n' || "ADCODE"逻辑说明:||是字符串拼接,\n换行。参数上,如果字段名是中文,确保 QGIS 编码设置正确。这个表达式的好处是标注内容随属性表更新自动变化,不用手动改。更进一步,可以用CASE WHEN按区域分色:
-- 按区域字段设置不同颜色(在标注或符号系统中使用) CASE WHEN "REGION" = '华北' THEN color_rgb(255,200,200) WHEN "REGION" = '华东' THEN color_rgb(200,255,200) ELSE color_rgb(200,200,255) END6.2 PostGIS 窗口函数做分省路网密度统计
-- 统计每个省的路网总长度和密度(长度/面积) WITH province_stats AS ( SELECT a.adcode, a.name, SUM(ST_Length(r.geom)) AS road_length, ST_Area(a.geom) AS area FROM admin_boundary a LEFT JOIN road_network r ON ST_Intersects(a.geom, r.geom) GROUP BY a.adcode, a.name, a.geom ) SELECT adcode, name, ROUND(road_length::numeric, 2) AS road_km, ROUND((road_length / NULLIF(area, 0))::numeric, 4) AS density, RANK() OVER (ORDER BY road_length DESC) AS length_rank FROM province_stats ORDER BY length_rank;逻辑说明:WITH子句先按省聚合路网总长度和面积,LEFT JOIN保证没有路网的省也出现在结果里。NULLIF(area, 0)防止除零。RANK() OVER按路网长度排名。参数上,ST_Length返回的单位取决于坐标系——如果是投影坐标(米),结果就是米;如果是经纬度,需要用ST_Length(geom::geography)转成米。这一步的坑在于:ST_Intersects会把跨省的路段同时算进两个省,导致总长度偏大,严格统计应该用ST_Intersection裁剪后再算长度。
6.3 一个我常用的验证习惯
每次导入新数据,我会先跑一个“三查”:查 SRID 是否一致、查几何是否有效、查要素数量是否与源文件一致。三查通过再往下做分析。这个习惯是从一次汇报前夜发现省界少了一个省开始的——当时数据导入成功、QGIS 也能显示,但要素数量比源文件少了 3 条,原因是导入时-skipfailures静默跳过了无效几何。从那以后我每次导入都强制走一遍ogrinfo计数和 PostGIS 计数对比,不一致就停下来查。希望帮到你。
本文还有配套的精品资源,点击获取