逆向解析:从公开GIS服务中高效获取城市控规数据 1. 从公开GIS服务获取城市控规数据的核心思路很多城市的规划部门都会提供在线GIS服务方便公众查询控规数据。但这些系统通常只支持单点查询不提供批量下载功能。逆向解析的核心思路是通过浏览器开发者工具分析网络请求找到数据接口的调用规律然后用代码模拟这些请求实现批量获取。我去年参与一个城市更新项目时需要获取东莞全市的控规数据。当时发现东莞控规查询系统http://120.86.191.153/DG.GisClient/default.aspx就是典型的ArcGIS Server架构。这类系统有个特点当你点击地图查询时浏览器会向后台发送包含坐标参数的请求返回JSON格式的地块信息。实际操作中我发现几个关键点系统使用RESTful API接口URL结构清晰可预测返回数据包含完整的空间几何信息和属性字段通过修改请求参数可以实现不同区域的数据获取需要处理坐标系转换和分页请求的问题2. 逆向分析ArcGIS REST API接口2.1 定位关键数据接口打开Chrome开发者工具F12切换到Network面板勾选Preserve log。在地图上点击任意地块时会发现一个关键的identify请求http://120.86.191.153:6080/arcgis/rest/services/KGCX/KGCX/MapServer/identify ?geometry12710257,2593523 geometryTypeesriGeometryPoint layersvisible:20 tolerance2 mapExtent12708661,2592799,12710891,2594657 imageDisplay1115,929,96 fjson tokensmLb_QfiJj_0mBbVF32JNFpCvn2PlHdRTRNRkwpRV_HB26u84puTMkLZWYjXTKbk8cucgJVlATcJUX9KvqM5Ew.. sr3857经过反复测试发现只有两个参数必须动态变化geometry查询点的坐标Web墨卡托坐标系EPSG:3857mapExtent当前地图视图范围2.2 参数优化技巧通过删减测试我总结出最小必要参数组合参数作用优化建议layers指定查询图层只保留控规图层20tolerance点击容差保持默认值2imageDisplay屏幕分辨率固定值不影响结果token访问令牌注意有效期特别要注意坐标系问题。该系统使用Web墨卡托坐标系EPSG:3857与我们常用的WGS84EPSG:4326不同。如果要做坐标转换可以用pyproj库from pyproj import Transformer transformer Transformer.from_crs(EPSG:4326, EPSG:3857) x, y transformer.transform(22.123, 113.456) # 纬度, 经度3. 设计自动化采集方案3.1 空间网格划分策略要实现全市数据采集需要解决空间覆盖问题。我的方案是将东莞范围划分为规则网格确定东莞的矩形范围Web墨卡托坐标xmin, ymin 12621272, 2591650 # 西南角 xmax, ymax 12715908, 2649830 # 东北角设置网格间距实测500米较合适delta 500 # 单位米 x_points np.arange(xmin, xmax delta, delta) y_points np.arange(ymin, ymax delta, delta)计算每个网格中心点坐标x_centers (x_points[:-1] x_points[1:]) / 2 y_centers (y_points[:-1] y_points[1:]) / 23.2 请求优化与错误处理直接高频请求会导致IP被封需要做以下优化随机延迟每个请求后暂停0.2-1秒异常重试捕获超时异常并自动重试断点续传记录已完成点位程序中断后可继续def safe_request(url, max_retry3): for i in range(max_retry): try: time.sleep(random.uniform(0.2, 1)) resp requests.get(url, timeout10) return resp.json() except Exception as e: print(f请求失败({i1}/{max_retry}): {e}) return None4. 数据处理与质量验证4.1 空间数据重构API返回的几何数据是坐标串格式需要转换为GeoDataFramefrom shapely.geometry import Polygon features [] for item in response[results]: rings item[geometry][rings] if len(rings) 1: # 简单多边形 geom Polygon(rings[0]) else: # 带洞的多边形 geom Polygon(rings[0], rings[1:]) features.append({ geometry: geom, **item[attributes] }) gdf gpd.GeoDataFrame(features, crsEPSG:3857)4.2 数据质量检查采集完成后需要验证覆盖率检查对比官方地图查看空白区域属性完整性检查字段缺失值几何有效性使用gdf.is_valid检查非法几何我发现在500米网格下东莞共获取36,972条记录但部分区域仍有遗漏。将网格缩小到300米后数据完整性显著提升。5. 完整代码实现以下是整合后的自动化采集脚本import numpy as np import pandas as pd import geopandas as gpd import requests import time import random from shapely.geometry import Polygon # 配置参数 BASE_URL http://120.86.191.153:6080/arcgis/rest/services/KGCX/KGCX/MapServer/identify TOKEN smLb_QfiJj_0mBbVF32JNFpCvn2PlHdRTRNRkwpRV_HB26u84puTMkLZWYjXTKbk8cucgJVlATcJUX9KvqM5Ew.. EXTENT [12621272, 2591650, 12715908, 2649830] # xmin, ymin, xmax, ymax def generate_grid(extent, delta500): 生成采样点网格 x np.arange(extent[0], extent[2] delta, delta) y np.arange(extent[1], extent[3] delta, delta) return [(xx, yy) for xx in (x[:-1]x[1:])/2 for yy in (y[:-1]y[1:])/2] def fetch_parcel_data(x, y): 获取单个点位数据 params { geometry: f{x},{y}, geometryType: esriGeometryPoint, layers: visible:20, tolerance: 2, mapExtent: ,.join(map(str, EXTENT)), imageDisplay: 1115,929,96, f: json, token: TOKEN, sr: 3857 } try: resp requests.get(BASE_URL, paramsparams, timeout10) return resp.json().get(results, []) except: return [] def process_batch(points, batch_size100): 批量处理采集任务 all_features [] for i, (x, y) in enumerate(points): print(f进度: {i1}/{len(points)}) results fetch_parcel_data(x, y) for item in results: rings item[geometry][rings] geom Polygon(rings[0], rings[1:]) if len(rings)1 else Polygon(rings[0]) all_features.append({**item[attributes], geometry: geom}) time.sleep(random.uniform(0.2, 0.5)) return gpd.GeoDataFrame(all_features, crsEPSG:3857) if __name__ __main__: sampling_points generate_grid(EXTENT, delta300) gdf process_batch(sampling_points) gdf.to_file(dongguan_control_plan.shp)6. 工程化建议在实际项目中还需要考虑增量更新记录已采集的地块ID避免重复请求分布式采集使用Scrapy等框架实现多线程数据存储建议使用PostGIS数据库管理可视化监控实时显示采集进度和成功率我曾遇到token过期的问题解决方案是定期从网页源码中提取新token。也可以通过模拟登录获取有效token但这需要分析网站的认证机制。这种逆向方法不仅适用于控规数据也可以用于其他基于ArcGIS Server的公共GIS服务如国土空间规划、不动产登记等系统。关键是要理解REST API的调用规则并设计合理的空间采样策略。