用 Python 按行政编码提取一条乡镇 GeoJSON 边界
效果与目标
拿到一个包含多个区域的 GeoJSON 文件后,项目可能只需要其中一个乡镇的轮廓。本文做一个小工具:输入文件、行政编码和输出文件,生成只包含匹配要素的 FeatureCollection。它保留匹配要素的属性和几何,不修改原始文件,也不请求地图接口。适合将已取得的数据整理成单区域文件,再交给地图工具使用。
本文实际使用吉林省通化市东昌区的一份本地数据,筛选编码 220502200 对应的环通乡。输入文件有 11 个要素,输出有 1 个;运行后比较过输出要素与输入中的匹配要素,属性和几何一致。该结果只说明这份文件和本次运行,不代表所有地区数据的覆盖、时效或边界精度。
数据和环境准备
准备一份可用的 GeoJSON 文件。本文示例来自地图数据项目已有的东昌区文件,文件名为 220502.json。它的顶层 type 是 FeatureCollection,features 是要素数组;各要素的 properties.code 为行政编码,properties.name 为名称,geometry 保存边界。该文件的环通乡几何类型为 Polygon;同一输入中也有 MultiPolygon,筛选时不需要转换几何。
先复制一份数据到工作目录,再进行操作。示例文件来自项目已有本地数据,文末公开入口不保证提供相同文件;读者需准备自己的兼容边界文件,实际字段和验证结果可能不同,不要把行政编码列表当作边界文件。准备 Python 3,无需安装第三方包。本文不推断数据坐标系或授权范围,叠加其他图层前应向数据提供方确认。
第一步:确认编码和文件结构
把 220502.json 和下面的 extract.py 放在同一个目录。打开 JSON,检查顶层 type 与 features,再查看目标要素的 properties.code。本例用字符串 220502200 做精确匹配,而不是按名称模糊搜索,避免同名区域误选;编码应保持字符串形式,以免丢失可能存在的前导零。
GeoJSON 的 FeatureCollection 可以包含多个 Feature。本工具只筛选数组,完整保留选中项的 properties 与 geometry,不会简化、多边形合并、重投影或计算面积。如果同一个编码对应多个要素,代码会全部保留,并在命令行显示数量;这不自动意味着数据有误,需要结合原数据核对。
第二步:保存完整代码
将以下代码保存为 extract.py:
import argparse
import json
from pathlib import Path
def main():
parser = argparse.ArgumentParser(description="按行政编码提取 GeoJSON 要素")
parser.add_argument("input", type=Path, help="输入 GeoJSON 文件")
parser.add_argument("code", help="要查找的行政编码")
parser.add_argument("output", type=Path, help="输出 GeoJSON 文件")
args = parser.parse_args()
if args.input.resolve() == args.output.resolve():
parser.error("输出路径不能与输入路径相同")
with args.input.open(encoding="utf-8") as file:
collection = json.load(file)
if collection.get("type") != "FeatureCollection" or not isinstance(collection.get("features"), list):
parser.error("输入必须是包含 features 数组的 FeatureCollection")
matches = [feature for feature in collection["features"]
if str((feature.get("properties") or {}).get("code", "")) == args.code]
if not matches:
parser.error(f"未找到编码 {args.code},没有写入输出文件")
result = {**collection, "features": matches}
with args.output.open("w", encoding="utf-8") as file:
json.dump(result, file, ensure_ascii=False, separators=(",", ":"))
print(f"找到 {len(matches)} 个要素,已写入 {args.output}")
if __name__ == "__main__":
main()
程序先阻止输入与输出指向同一路径,再检查顶层类型和数组,随后以 properties.code 精确筛选。找不到编码时通过参数错误退出,不创建输出文件;如果输出文件已经存在,正常匹配后会覆盖它,使用前请选一个新的输出文件名。输出保留输入集合中的其他顶层字段,并把 features 替换为匹配结果。
第三步:运行并检查结果
在这两个文件所在目录打开终端,运行:
python3 extract.py 220502.json 220502200 220502200.json
本次运行输出 找到 1 个要素,已写入 220502200.json。打开新文件,应看到 type 仍为 FeatureCollection,features 数组仅含一个要素,名称为环通乡、编码为 220502200,几何类型为 Polygon。可以把文件导入支持 GeoJSON 的地图软件检查轮廓;是否能正确叠加其他底图还取决于坐标系等信息。
再试一个输入中不存在的编码,例如:
python3 extract.py 220502.json 999999999 missing.json
程序应提示未找到编码并以非零状态退出,不创建 missing.json。本次也验证了这一失败路径。实际使用时应在干净的输出路径测试:如果同名旧文件本来就存在,失败不会删除它,不能仅凭文件存在判断本次成功。
常见问题
为什么找不到区域? 先检查输入文件是否为该区域的上级或目标要素集合,再查看实际编码字段是否叫 code、值是否完整。不同来源的属性名可能不同,需要按真实数据修改筛选逻辑。名称存在不代表编码一定相同,也不要用前缀匹配替代精确匹配。
输出能直接用于 ECharts 吗? 输出仍是 FeatureCollection,可作为后续地图接入的输入;具体显示还需要注册地图并配置图表,不能仅凭成功导出就认定所有地图组件或坐标系统均兼容。
文件含多个面或岛屿怎么办? 工具保留原始 Polygon 或 MultiPolygon,不拆分也不重新计算。遇到无效几何、缺失属性或格式错误时,应先核对来源并使用专门的 GIS 工具检查;本示例不是完整的 GeoJSON 合法性校验器。
数据与源码
地图数据入口:https://geojson.hxkj.vip/
既有地图示例项目:https://github.com/TangSY/echarts-map-demo
本文的 extract.py 完整代码已列在上面;它是本教程示例,并未声称已推送到上述仓库。

浙公网安备 33010602011771号