简介:这是一份搜集整理的GeoJSON地理数据合集,主要面向Web前端开发者、GIS分析人员及地图可视化爱好者,用于解决地理边界与地名坐标数据获取、格式转换不便的问题。GeoJSON基于JSON结构,支持点、线、面等几何类型,适合在浏览器端通过JavaScript直接解析渲染。压缩包共1102个文件,以1100个json格式的地理数据为主,另附1个csv坐标属性表和1个md说明文档,整体体积约156.12MB。数据覆盖全球多个国家与地区的行政区划、边界和经纬度信息,包括印度尼西亚、巴西、菲律宾、加拿大等不同层级的省级/市级GeoJSON,可直接用于地图渲染、空间查询、数据统计或前后端地理数据交互实验。目前已有584人学习下载。该合集省去了逐平台检索与格式转换的繁琐步骤,提供现成的开源数据,便于快速搭建交互式地图原型、验证GeoJSON解析流程,或者作为教学与项目开发的基础数据集,md文档也能帮助理解文件结构与属性字段。
1. 搜集来的GeoJSON数据打包成zip:比你想的更值得认真对待
拿到一个名为“搜集来的geojson数据_GeoJSON_data.zip”的压缩包,很多人的第一反应是解压、拖进地图工具、看一眼就跑。但作为常年跟地理数据打交道的人,我劝你停一下:这个zip里装的不是普通文件,而是一批带有空间坐标的GeoJSON数据。GeoJSON已经成为Web地图、GIS分析、数据可视化项目里最通用的交换格式,但正因为通用,也最容易在“搜集”过程中被悄悄污染——坐标系混乱、编码错误、要素重复、几何非法,随便一个都能让后续的渲染和分析结果变成一坨玄学。这篇文章就把我从解压到入库的完整路径讲清楚,覆盖文件校验、编码转换、坐标检查、合并去重、避坑排查,以及最后怎么把它变成能快速查询的本地数据源。适合正在做地图可视化、空间数据分析、爬虫数据清洗,或者刚拿到一堆陌生GeoJSON包准备二次开发的从业者,照着走能省下半天调试时间。
2. 拆开GeoJSON_data.zip之前:先搞懂GeoJSON的结构与坐标系
2.1 GeoJSON的数据组织:Feature、Geometry、Properties三件套
GeoJSON不是一种文件格式,而是一种基于JSON的空间数据编码规范。打开任何一个合法的GeoJSON文件,最外层通常是一个对象,它有一个type字段,取值可能是FeatureCollection、Feature、Point、LineString、Polygon等。日常搜集到的数据九成是FeatureCollection,里面是一个features数组,每个元素都是一个Feature对象。
一个标准的Feature长这样:
{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [116.397, 39.908] }, "properties": { "name": "故宫", "level": "cultural" } }注意geometry里的coordinates并不是随便填的。对Point来说它是一个两元素或三元素数组,分别代表经度、纬度(可选海拔);对LineString和Polygon则是一个嵌套数组,每一层的层级对应坐标轴数量。很多时候报错就出在“多拐了一层”或“少拐了一层”,例如把Polygon的坐标写成了[[[116.3,39.9], [116.4,39.9], ...]],但实际应该是[ [ [x,y], [x,y], ... ] ],第一个内层数组代表外环,后面可跟多个洞。写代码处理时,我一般会先递归检查嵌套深度,而不是直接取[0][0],否则遇到空坐标或异形多边形时直接翻车。
properties里面是属性字段,理论上任意JSON类型都可以,但实际因GeoJSON引擎而异。比如Leaftlet可以读取properties里的任意字段做弹窗,而Mapbox GL则要求属性值必须是字符串、数字或布尔值,不能嵌套对象。所以拿到压缩包里的文件,第一步不是看地图长得怎么样,而是用jq或Python把properties的键名全部拉出来,看看有没有会让你前端渲染崩坏的复杂类型。
2.2 坐标系与精度:为什么同一个点在不同软件里会飘
GeoJSON规范里默认使用WGS-84坐标系,也就是EPSG:4326,经纬度坐标,单位是十进制度。但现实很骨感,很多从第三方“搜集”来的数据,坐标可能来自GCJ-02(火星坐标)、BD-09(百度坐标),甚至更冷门的UTM投影坐标。如果你直接把UTM的七位数坐标当成经度丢进Web地图,点位会飞到非洲。判断坐标系最直接的方式是看数值范围——经度正常在-180到180,纬度在-90到90;如果看到x=452124.32, y=4412345.67这种六到七位数,基本就是投影坐标,必须先做反投影。
精度问题同样容易被忽略。GeoJSON里的浮点数经常出现117.23041532784142这样的长尾,这通常是从Shapefile或CAD文件转出来时保留了原始精度。对点数据来说,0.00001度大约对应1米,超出实际采集精度的位数除了撑大文件体积没有任何意义。我一般会在清洗阶段统一把经纬度四舍五入到6位小数(约0.1米精度),文件体积能缩水20%-30%,同时不影响后续空间分析。
下面这个Python脚本是mini版“GeoJSON体检”,直接拿来检查压缩包里所有文件的坐标系是否可疑:
import json, glob, os for f in glob.glob("*.geojson"): with open(f, encoding="utf-8") as fp: data = json.load(fp) for feat in data.get("features", []): coords = feat["geometry"]["coordinates"] # 递归取所有坐标点 pts = [] def walk(c): if isinstance(c[0], (int, float)): pts.append(c[:2]) else: for item in c: walk(item) walk(coords) for lon, lat in pts[:10]: # 每个文件看前10个点就够 if lon > 180 or lon < -180 or lat > 90 or lat < -90: print(f"{f}: 疑似非WGS84坐标,示例点({lon},{lat})") break这段脚本的思路是递归进入coordinates结构,取每个点坐标的前两个值判断范围。参数说明:pts[:10]限制只取前10个点,避免文件过大时遍历所有点导致程序卡死;walk函数递归处理任意深度的坐标嵌套,不管是Point还是MultiPolygon都能统一处理。如果某个文件被判定为疑似非WGS84,后续就要单独处理坐标系转换,千万不能跟其他文件混着合并。
3. 用命令行把GeoJSON数据zip包整理成可用的本地数据源
3.1 快速解压与校验文件完整性
拿到zip后我先不急着双击解压。Windows资源管理器自带解压对普通文件还好,但批量处理GeoJSON时,我更推荐命令行,因为可以顺便做完整性校验。zip本身有CRC32校验码,unzip命令在解压时会自动比对,如果文件损坏会直接报错,而图形化工具往往会静默解出一个残缺文件,坑非常大。
在Linux或macOS上:
unzip -l GeoJSON_data.zip # 只列内容,不解压 unzip -t GeoJSON_data.zip # 测试所有文件的完整性 unzip -o GeoJSON_data.zip -d data # 解压到data目录,-o表示覆盖参数说明:-l是list,先看压缩包里到底有什么,防止解压出同名目录覆盖已有文件;-t是test,逐文件读取并比对CRC,任何损坏都会在这里暴露;-d指定输出目录,强烈建议养成“解压到独立目录”的习惯,不要散落一堆GeoJSON在桌面或项目根目录。如果unzip -t输出里有bad CRC或者mismatch,这个文件就是坏的,直接放弃它,不要幻想能用修复工具救回来。如果是Windows且没有unzip,可以用PowerShell的Expand-Archive,但那个不测试完整性,所以我会先跑一遍Get-FileHash对比来源方提供的哈希值——但搜集来的数据往往没有源哈希,那就只能用unzip -t硬测。
3.2 批量转码为UTF-8并检查GeoJSON合法性
GeoJSON标准要求文件使用UTF-8编码,但很多从GIS软件直接导出的文件实际是GBK或GB2312,尤其属性字段里有中文时更容易踩坑。表现就是解压后在记事本里看没问题,但用Python读出来全是乱码,或者加载到网页地图后属性名变成一堆“锟斤拷”。解决办法是批量转码,这里用iconv最顺手:
for f in data/*.geojson; do # 先用file判断编码,常见的是UTF-8和GBK encoding=$(file -b --mime-encoding "$f") if [ "$encoding" != "utf-8" ] && [ "$encoding" != "us-ascii" ]; then iconv -f "$encoding" -t UTF-8 "$f" > "$f.tmp" && mv "$f.tmp" "$f" fi done这段脚本的逻辑:file -b --mime-encoding输出文件实际编码,常见的有utf-8、gbk、iso-8859-1等。如果不是UTF-8(ASCII是UTF-8子集,不用转),就用iconv转换。注意iconv遇到非法的输入序列会直接报错并生成半截文件,所以要用&&确保转换成功后再替换原文件,防止原文件被清空。如果你在Windows上不想装GNU工具,可以用Python的chardet库识别编码,但准确率不是100%,遇到混合中文编码时还是要人工抽查。
转码后还要验证GeoJSON合法性。json.load只能保证是合法JSON,不能保证是合法GeoJSON。简单起见,用一个在线验证器或本地库,我常用的是Python的geojson包:
import geojson from pathlib import Path for p in Path("data").glob("*.geojson"): with open(p, encoding="utf-8") as f: try: geojson.load(f) geojson.validate(f) # 注意:geojson库的validate是旧API,需重新读文件 print(f"{p.name}: OK") except Exception as e: print(f"{p.name}: {e}")注意这里有个坑:geojson.load(f)后文件指针已经到末尾,接着调用geojson.validate(f)会读到空内容,所以必须重新打开文件,或者先读字符串再解析。正确写法是:
text = p.read_text(encoding="utf-8") data = geojson.loads(text) geojson.validate(data)geojson.validate会检查type枚举、coordinates层级、Feature必填字段等,比裸json.load强得多。如果validation报出TypeError或者ValueError,基本就是坐标数组层级不对,比如Polygon的coordinates是三维数组,但数据里只有二维,那个文件后续处理肯定成问题,建议直接隔离。
3.3 用Python脚本统一合并多个GeoJSON文件
搜集来的zay包里很可能有几十个按区域或时间切割的小GeoJSON文件,直接拿给前端用会有大量HTTP请求,合并成单个FeatureCollection是常规操作。但合并不是简单拼接features数组,还要处理重复要素和属性不一致。下面是一个可复用的合并脚本:
import json, sys from pathlib import Path def merge_geojson(input_dir, output_file, dedupe_key=None): all_features = [] seen = set() for p in Path(input_dir).glob("*.geojson"): with open(p, encoding="utf-8") as f: data = json.load(f) if data.get("type") != "FeatureCollection": # 如果是单个Feature,包一层;如果是Geometry,跳过并告警 if data.get("type") == "Feature": all_features.append(data) else: print(f"跳过非FeatureCollection: {p.name}") continue for feat in data.get("features", []): if dedupe_key: key = json.dumps(feat.get("properties", {}).get(dedupe_key), ensure_ascii=False) else: key = json.dumps(feat.get("geometry"), sort_keys=True) if key in seen: continue seen.add(key) all_features.append(feat) merged = {"type": "FeatureCollection", "features": all_features} with open(output_file, "w", encoding="utf-8") as f: json.dump(merged, f, ensure_ascii=False) print(f"合并完成: {len(all_features)} 个要素 -> {output_file}") if __name__ == "__main__": merge_geojson("data", "merged.geojson", dedupe_key="id")参数说明:dedupe_key用于指定属性字段作为去重依据,如果原始数据有唯一ID(如id、fid、osm_id),用这个字段最可靠;如果没传,脚本默认用整个geometry对象做去重键,但这只对完全相同的要素有效,两个坐标有微小差异的重复点不会被去重。json.dumps中的sort_keys=True是为了让相同的坐标即使键顺序不同也能识别。ensure_ascii=False保证输出文件里的中文是明文而不是\uXXXX转义序列,方便其他工具读取。
合并后一定要检查要素数量,通常源文件里会有断头数据。靠len(all_features)输出能看出有没有明显暴增或骤减。如果发现合并后数量比所有源文件数量之和还大,说明有FeatureCollection嵌套了重复数组;如果小很多,说明去重键选得太宽,把不该去重的也吞了。这个脚本建议在项目里保存,以后每次拿到新的GeoJSON包都能复用。
4. 处理zip中的GeoJSON数据:避坑与常见问题排查
4.1 现象:中文属性乱码,QGIS里正常但浏览器里是“锟斤拷”
原因:文件实际是GBK或GB2312编码,但GeoJSON规范要求UTF-8。QGIS等桌面GIS对编码有自动嗅探能力,能容忍错误编码,而Web引擎按UTF-8解析,导致中文全乱。解决:按第3.2节的方式批量转码。如果转码后仍有乱码,多半是源文件里存在CP936和UTF-8混合内容,iconv会把已经UTF-8的段落再次误转。这时用Python的errors="replace"策略逐字节清洗,或者把文件读为二进制,按UTF-8解码失败后改用GBK尝试。我见过一个文件里同一个属性值前面是“北京市”,后面是“\u542f\u718a”这种JSON转义,这种只能写正则把\uXXXX还原,别无他法。
4.2 现象:QGIS能打开,但自己写的Python脚本说JSONDecodeError
原因:文件带有UTF-8 BOM(字节顺序标记),或者行尾是CRLF,甚至文件头有不可见字符。Python的json.load默认不接受BOM,需要指定encoding="utf-8-sig"读取。解决:统一在读取时使用utf-8-sig,或者先跑一次sed -i '1s/^\xEF\xBB\xBF//' file.geojson去掉BOM。另外注意,如果是Windows上用记事本另存过,行尾会变成CRLF,这不影响JSON解析,但会影响某些命令行工具的行号定位。我习惯在清洗阶段把所有GeoJSON统一用Python重新写出一次,写成LF、无BOM,彻底杜绝后续问题:
from pathlib import Path for p in Path("data").glob("*.geojson"): raw = p.read_bytes() # 去掉BOM if raw.startswith(b"\xef\xbb\xbf"): raw = raw[3:] # 统一换行符为LF text = raw.decode("utf-8").replace("\r\n", "\n") p.write_text(text, encoding="utf-8", newline="\n") print(f"清理完成: {p.name}")4.3 现象:文件上百MB,页面加载卡死,浏览器直接崩溃
原因:几何坐标精度太高,动辄15位小数,导致压缩包解压后文件膨胀;同时可能存在大量冗余几何点,比如一条线段中间隔0.5米就采一个点,实际0.1公里一个点也够。解决:使用simplify算法抽稀,同时降低坐标精度。shapely库的simplify是最常用方案:
from shapely.geometry import shape, mapping from shapely.geometry.base import BaseGeometry import json def simplify_geojson(infile, outfile, tolerance=0.0001): with open(infile, encoding="utf-8") as f: data = json.load(f) for feat in data["features"]: geom = shape(feat["geometry"]) simplified = geom.simplify(tolerance, preserve_topology=True) feat["geometry"] = mapping(simplified) with open(outfile, "w", encoding="utf-8") as f: json.dump(data, f, ensure_ascii=False) # tolerance=0.0001 约等于10米,适合市级尺度参数说明:tolerance是简化容差,单位与坐标相同。对经纬度数据,0.0001度约为10米;如果要精细到街区,用0.00001(约1米)。preserve_topology=True保证简化后不会出现自相交等几何拓扑错误,虽然速度稍慢,但对于底图数据值得。如果文件里只有点数据,简化没有意义,那就只做坐标舍入:[round(x,6) for x in coord]。
4.4 现象:zip文件解压时提示“伪加密”或“CRC校验失败”
原因:搜集来的zip包可能是某些人用工具强行修改过文件头,把普通zip标记为加密,但实际没有加密内容;也可能是文件在传输过程中损坏。Windows资源管理器对伪加密文件会直接弹框要求输入密码,此时不要瞎试密码,先查一下文件头。一个有效的排查方法是用zipinfo查看:
zipinfo -v GeoJSON_data.zip | grep -i "encrypt"如果输出显示file has no encryption但解压又要密码,那基本就是伪加密,修掉加密标志位即可。常见做法是用脚本把general purpose bit flag的第0位清零。这类文件如果真的损坏且没有备份,修复概率极低,所以我会建议做数据源的时候保留一份原始zip在冷存储,不要只留解压目录。伪加密是恶意或者打包工具bug产生,正常也不会遇到,遇到了直接换一个来源重新下载,比修复可靠。
4.5 现象:合并后地图上要素位置偏移了好几百米
原因:某个源文件使用了GCJ-02坐标系,而其他文件是WGS-84。这种“坐标漂移”肉眼可能在城市尺度下看不太出来,但叠加到道路或建筑边界时就暴露了。解决:识别出GCJ-02文件,单独做坐标纠偏。GCJ-02和WGS-84之间的转换没有公开的数学公式,常用方法是查表或者用反向偏移算法。这里给一个常见的纠偏片段(有效范围是中国大陆,注意不要用于其他地区):
import math def gcj02_to_wgs84(lng, lat): # 简化版:先转火星坐标再反算,精度约1米 a = 6378245.0 ee = 0.00669342162296594323 dlat = _transform_lat(lng - 105.0, lat - 35.0) dlng = _transform_lng(lng - 105.0, lat - 35.0) radlat = lat / 180.0 * math.pi magic = math.sin(radlat) magic = 1 - ee * magic * magic sqrtmagic = math.sqrt(magic) dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * math.pi) dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * math.pi) return lng + dlng, lat - dlat注意这是一个逆推近似,实际工程里我们一般用pyproj或coord_convert库,精度更高。这段代码仅用于让你理解原理:坐标漂移是系统性的,不是随机噪声,所以可以通过统一转换消除。在写批量处理脚本时,我一般先用几个已知城市的地标点手工比对坐标,确定偏移方向,再决定是否全部转坐标系。
5. 把整理后的GeoJSON zip变成可查询的本地数据库:一个提速技巧
数据清洗完,如果只是做一次性可视化,merged.geojson就够了。但如果是做Web服务或者反复查询某个区域内的要素,每次全量加载GeoJSON都是对CPU和内存的浪费。我的习惯是把它转成SQLite + Spatialite,或者直接引入tippecanoe切成矢量瓦片。
以SQLite为例,用ogr2ogr一行命令就能把GeoJSON导入到Spatialite:
ogr2ogr -f SQLite output.db merged.geojson -nln poi -lco SPATIALITE=YES -lco SRID=4326导入后可以用SQL直接做空间查询,比在Python里遍历GeoJSON快两个数量级。比如查故宫周围3公里的POI:
SELECT name FROM poi WHERE ST_DWithin(geom, ST_GeomFromText('POINT(116.397 39.908)', 4326), 0.03);这里的0.03对应约3公里,因为单位是度。如果你不需要空间索引,也可以只把properties展开成普通表,用普通SQL过滤。对于凌乱的数据源,这个转换本身又是一次强校验——ogr2ogr会跳过无法解析的要素,并输出警告日志,你正好可以把日志留下来当清洗清单。
我自己的习惯是最后跑一遍数据条数核对:源zip里每个文件的行数、合并后的总条数、入库后的总数,三者对不上就说明中间有丢失,宁可回头修数据也不带着脏数据上线。数据这条路,整洁比数量重要,一个坏坐标比少一条记录头疼得多。希望这篇清单一套走下来,能让你拿到“搜集来的geojson数据_GeoJSON_data.zip”这类包时不再心里发虚,半小时之内整理成能直接投入使用的本地数据源,省下的时间多睡会儿都比对着乱码抓头发强。希望帮到你。
本文还有配套的精品资源,点击获取