Search standalone server services through ArcGIS API for Python

643
2
Jump to solution
04-07-2021 02:03 PM
shapo
by
New Contributor II

Does anyone know how to search services, such as a Feature Layer, on a standalone ArcGIS server through ArcGIS API for Python? For example, I am trying to access and list services published  at  https://geoappext.nrcan.gc.ca/arcgis/rest/services/ by using gis.content.search but with no luck.

I have been using this code:

gis = GIS()
items = gis.content.search(query="NRCAN",item_type="Feature Layer", max_items=10000)

I do get some of the services back as items but 'search' casts a too wide net, grabbing services that are not on that server as well, which then due to the max_items cap of 10,000 results in many of the services on the stated server not caught and returned as items. I would like to have only the feature layer services on the stated server returned as items, no other services.

Any help would be much appreciated, thank you.

 

0 Kudos
2 Solutions

Accepted Solutions
jcarlson
MVP Esteemed Contributor

What you want is the ServicesDirectory class. With it, you can iterate over the server's folders and return the services.

There is a "find" method, but repeated tests don't return reliable results. There's also a "report" method that returns the services in a folder as a Pandas DataFrame, which sounds ideal, but I haven't gotten that to return anything useful, either.

In any case, you can simply iterate over the entire server and populate a list of services, then search that.

 

from arcgis.gis.server.catalog import ServicesDirectory

s = ServicesDirectory('https://geoappext.nrcan.gc.ca/arcgis/rest/services/')

full_list = []

for f in s.folders:
    for svc in s.list(folder=f):
        full_list.append(svc)
    
full_list

 

Returns

[<MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBCT3978/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBCT_TXT_3857/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBCT_TXT_3978/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBME_CBCE_HS_RO_3978/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBMT3978/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBMT_CBCT_GEOM_3857/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBMT_CBCT_GEOM_3978/MapServer">,
...

You can then search through that list for specific items.

Bonus points: use list comprehension to compile the list in one line:

[svc for sublist in [s.list(f) for f in s.folders] for svc in sublist]
- Josh Carlson
Kendall County GIS

View solution in original post

0 Kudos
shapo
by
New Contributor II

Perfect! Thank you very much, Josh, this is exactly what I was looking for. I spent so much time this morning to find a solution so this is greatly appreciated! I did play with the ServiceDirectory class but I obviously wasn't using the right syntax.

Thanks again!

Tomislav

View solution in original post

0 Kudos
2 Replies
jcarlson
MVP Esteemed Contributor

What you want is the ServicesDirectory class. With it, you can iterate over the server's folders and return the services.

There is a "find" method, but repeated tests don't return reliable results. There's also a "report" method that returns the services in a folder as a Pandas DataFrame, which sounds ideal, but I haven't gotten that to return anything useful, either.

In any case, you can simply iterate over the entire server and populate a list of services, then search that.

 

from arcgis.gis.server.catalog import ServicesDirectory

s = ServicesDirectory('https://geoappext.nrcan.gc.ca/arcgis/rest/services/')

full_list = []

for f in s.folders:
    for svc in s.list(folder=f):
        full_list.append(svc)
    
full_list

 

Returns

[<MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBCT3978/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBCT_TXT_3857/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBCT_TXT_3978/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBME_CBCE_HS_RO_3978/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBMT3978/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBMT_CBCT_GEOM_3857/MapServer">,
 <MapImageLayer url:"https://geoappext.nrcan.gc.ca/arcgis/rest/services//BaseMaps/CBMT_CBCT_GEOM_3978/MapServer">,
...

You can then search through that list for specific items.

Bonus points: use list comprehension to compile the list in one line:

[svc for sublist in [s.list(f) for f in s.folders] for svc in sublist]
- Josh Carlson
Kendall County GIS
0 Kudos
shapo
by
New Contributor II

Perfect! Thank you very much, Josh, this is exactly what I was looking for. I spent so much time this morning to find a solution so this is greatly appreciated! I did play with the ServiceDirectory class but I obviously wasn't using the right syntax.

Thanks again!

Tomislav

0 Kudos