PyQGIS – Loading Layers from ArcGIS Feature Service in QGIS 3

feature-servicepyqgisqgis-3

When opening QGIS and add connection to the ArcGIS Feature/Map Service like :https://gis.adem.alabama.gov/arcgis/rest/services it giving me the list of all services and the layers within each service.

Is there a way to do it using PyQGIS ?

enter image description here

I know to load layer with:

QgsVectorLayer(uri, layer_name, "arcgisfeatureserver")

I want to get all the layers available on a source using PyQGIS.

Best Answer

On the webpage of the REST services URL there is a json link at the top left. Clicking this will show a json of the service metadata, including a list of names. Likewise, a similar link will show a json of all the layers in each service.

enter image description here

The service names and corresponding layers can be extracted like so:

import urllib.request, json 

json_url = 'https://gis.adem.alabama.gov/arcgis/rest/services?f=pjson'

# download the services json
with urllib.request.urlopen(json_url) as url:
    data = json.loads(url.read().decode())
    
# get services from the json
services = data['services']

# get names and types of services
for i,x in enumerate(services):
    print(i, ' | ',  x['name'], ' | ', x['type'])

# number of service
num = 5

# get name and type from list 
service_name = services[num]['name']
service_type = services[num]['type']

# get layers from service
layers_url = f"https://gis.adem.alabama.gov/arcgis/rest/services/{service_name}/{service_type}/layers?f=pjson"

# download the layers json
with urllib.request.urlopen(layers_url) as url:
    data = json.loads(url.read().decode())

layers = data['layers']

available_layers = []
for layer in layers:
    available_layers.append([layer[k] for k in ['id', 'name', 'type', 'geometryType']])

[print(x) for x in available_layers]

## pick a layer 
layer_index = 0

# check that the chosen index is available
if layer_index in (x[0] for x in available_layers):
    # build the REST service url
    uri = f"crs='EPSG:4326' url='https://gis.adem.alabama.gov/arcgis/rest/services/{service_name}/{service_type}/{layer_index}"
    
    # make QGIS layer
    lyr = QgsVectorLayer(uri, layer['name'], "arcgisfeatureserver")
    
    # add to map
    QgsProject.instance().addMapLayer(lyr)
else:
    print(f"chosen layer index ({layer_index}) is not in available layers")