如何提取ArcGIS Feature Layer全量记录 解决仅返回2000条问题
问题原因
ArcGIS要素服务默认配置了单次查询的最大返回记录数阈值(通常为1000或2000条),单次请求超出阈值的结果会被服务端自动截断,因此无法直接拿到9万条全量记录。
另外你当前代码存在两个影响结果的问题:
- 开启了
returnCountOnly: "true"参数,该参数只会返回匹配条件的记录总数,不会返回实际的要素属性/几何数据 - 未拼接查询接口后缀,要素服务的查询端点为
{你的要素服务地址}/query,直接请求根地址不会触发查询逻辑
全量数据提取方案
采用分页批量拉取的方式获取全量数据,优先使用服务原生支持的偏移分页,兼容性要求高的场景可使用OBJECTID游标遍历,两种方案均不会触发返回条数限制。
方案1:标准偏移分页(推荐,90%以上新版ArcGIS Server/ArcGIS Online均支持)
核心逻辑是通过resultOffset(分页偏移量)和resultRecordCount(单页返回条数)两个参数逐页拉取,直到拉取的总条数匹配记录总数为止。
注意单页条数不要超过服务端允许的最大值,你可以直接请求要素服务根地址,返回的JSON中maxRecordCount字段就是服务端配置的单页上限,单页大小设置为小于等于该值即可。
参考代码:
import requests import time # 配置项 FEATURE_LAYER_URL = "你的要素服务地址" token = "你的认证token" PAGE_SIZE = 2000 # 可根据服务maxRecordCount调整,不要超过阈值 all_features = [] # 第一步:先获取符合条件的总记录数 count_params = { "token": token, "f": "json", "where": "1=1", "returnCountOnly": "true" } count_resp = requests.post(f"{FEATURE_LAYER_URL}/query", params=count_params) total_count = count_resp.json()["count"] print(f"总记录数:{total_count}") # 第二步:逐页拉取数据 data_params = { "token": token, "f": "json", "where": "1=1", "returnGeometry": "false", "outFields": "*", "outSR": 4326, "resultRecordCount": PAGE_SIZE } for offset in range(0, total_count, PAGE_SIZE): data_params["resultOffset"] = offset resp = requests.post(f"{FEATURE_LAYER_URL}/query", params=data_params) resp_data = resp.json() # 异常判断 if "error" in resp_data: raise Exception(f"查询出错:{resp_data['error']}") page_features = resp_data.get("features", []) all_features.extend(page_features) print(f"已拉取{len(all_features)}/{total_count}条记录") time.sleep(0.5) # 加短延时避免触发服务限流 print(f"全量拉取完成,共获取{len(all_features)}条记录")
方案2:OBJECTID游标遍历(兼容旧版不支持偏移分页的服务)
如果调用分页接口返回报错提示不支持resultOffset,可以先拉取所有要素的唯一OBJECTID字段值,再按批次拆分OBJECTID列表,通过where条件每次查询一批ID对应的数据,兼容性拉满,超大数据量下性能也更稳定。
参考代码:
import requests import time FEATURE_LAYER_URL = "你的要素服务地址" token = "你的认证token" BATCH_SIZE = 2000 all_features = [] # 第一步:拉取所有要素的OBJECTID oid_params = { "token": token, "f": "json", "where": "1=1", "returnIdsOnly": "true" } oid_resp = requests.post(f"{FEATURE_LAYER_URL}/query", params=oid_params) all_oids = oid_resp.json()["objectIds"] total_count = len(all_oids) print(f"总记录数:{total_count}") # 第二步:按批次拆分OBJECTID查询 data_params = { "token": token, "f": "json", "returnGeometry": "false", "outFields": "*", "outSR": 4326 } for i in range(0, total_count, BATCH_SIZE): batch_oids = all_oids[i:i+BATCH_SIZE] data_params["where"] = f"OBJECTID IN ({','.join(map(str, batch_oids))})" resp = requests.post(f"{FEATURE_LAYER_URL}/query", params=data_params) resp_data = resp.json() if "error" in resp_data: raise Exception(f"查询出错:{resp_data['error']}") batch_features = resp_data.get("features", []) all_features.extend(batch_features) print(f"已拉取{len(all_features)}/{total_count}条记录") time.sleep(0.5) print(f"全量拉取完成,共获取{len(all_features)}条记录")
注意事项
- 拉取超10万条数据时优先选择方案2,偏移分页在偏移量过大时可能出现数据库查询性能下降的问题
- 如果要素服务开启了地理坐标系转换,返回几何数据时建议单页大小适当调低,避免单响应体积过大导致请求超时
- 不要使用GET方法发起大批次查询,URL参数长度超限会导致查询条件被截断
内容的提问来源于stack exchange,提问作者code_bug
相关产品推荐
相关产品推荐

