Skip to content

Instantly share code, notes, and snippets.

@TheBryanMac
Last active November 26, 2023 06:04
Show Gist options
  • Save TheBryanMac/da76aea0b736aa3da99a80408f6db42f to your computer and use it in GitHub Desktop.
Save TheBryanMac/da76aea0b736aa3da99a80408f6db42f to your computer and use it in GitHub Desktop.
Python script that connects to an ArcGIS Server Map Service and downloads a single vector layer to shapefiles. If there are more features than AGS max allowed, it will iterate to extract all features.
#Name: Export ArcGIS Server Map Service Layer to Shapefile with Iterate
#Author: Bryan McIntosh
#Description: Python script that connects to an ArcGIS Server Map Service and downloads a single vector layer
# to shapefiles. If there are more features than AGS max allowed, it will iterate to extract all features.
import urllib2,json,os,arcpy,itertools
ws = os.getcwd() + os.sep
#Set connection to ArcGIS Server, map service, layer ID, and server max requests (1000 is AGS default if not known).
serviceURL = "https://domain/arcgis/rest/services"
serviceMap = "/Public/Directory/MapServer"
serviceLayerID = 0
serviceMaxRequest = 1000
dataOutputName = "MyShapefile"
def defServiceGetIDs():
IDsRequest = serviceURL + serviceMap + "/" + str(serviceLayerID) + "/query?where=1%3D1&text=&objectIds=&time=&geometry=&geometryType=esriGeometryEnvelope&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=&returnGeometry=true&returnTrueCurves=false&maxAllowableOffset=&geometryPrecision=&outSR=&returnIdsOnly=true&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&returnDistinctValues=false&resultOffset=&resultRecordCount=&f=pjson"
IDsResponse = urllib2.urlopen(IDsRequest)
IDsJSON = json.loads(IDsResponse.read())
IDsSorted = sorted(IDsJSON['objectIds'])
return IDsSorted
def defGroupList(n, iterable):
args = [iter(iterable)] * n
return ([e for e in t if e != None] for t in itertools.izip_longest(*args))
def defQueryExtractRequests(idMin, idMax):
myQuery = "&where=objectid+>%3D+" + idMin + "+and+objectid+<%3D+" + idMax
myParams = "query?geometryType=esriGeometryEnvelope&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=*&returnGeometry=true&geometryPrecision=&outSR=&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&returnZ=false&returnM=false&returnDistinctValues=false&returnTrueCurves=false&f=pjson"
myRequest = serviceURL + serviceMap + "/" + str(serviceLayerID) + "/" + myParams + myQuery
response = urllib2.urlopen(myRequest)
myJSON = response.read()
# Write response to json text file
foo = open(dataOutputName + idMin + ".json", "w+")
foo.write(myJSON);
foo.close()
# Create Feature Class
arcpy.JSONToFeatures_conversion(dataOutputName + idMin + ".json", ws + dataOutputName + idMin + ".shp")
#**MAIN**#
#Get all objectIDs (OIDs) for the layer (there is no server limit for this request)
AllObjectIDs = defServiceGetIDs()
#Divide the OIDs into chunks since there is a limit to map queries (assumed limit stored in serviceMaxRequest variable)
ObjectID_Groups = list(defGroupList(serviceMaxRequest, AllObjectIDs))
#Create a shapefile for each chunk
for ObjectID_Group in ObjectID_Groups:
idMin = str(ObjectID_Group[0])
idMax = str(ObjectID_Group[-1])
defQueryExtractRequests(idMin, idMax)
#Append all shapefiles if desired
@ojoaoaugusto
Copy link

Hello, Bryan. Thank you very much for those pieces of code! But I'd like to ask you some help. I tried you first code (MapService2Shapefile.py) with success, but this one is not working properly. I changed just the 3 variables that were required:

serviceURL = "https://www.geoservicos1.segeth.df.gov.br/arcgis/rest/services"
serviceMap = "/Luos/LUOS_PLC/MapServer"
serviceLayerID = 0

Am I supposed to do something else?
Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment