{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Exploring ArcGIS REST Services\n", "Data served via ArcGIS Servers support a REST API for accessing these services. This notebook provides some examples on how we can use Python to access these services using the `requests` package. \n", "\n", "→ Full documentation on the ArcGIS REST API: https://developers.arcgis.com/rest/services-reference/get-started-with-the-services-directory.htm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### NCOneMap's REST Endpoint\n", "We'll explore NCOneMap's web services, accessed here: https://services.nconemap.gov/secure/rest/services. \n", "* Begin by navigating to that page to familiarize yourself with the organization and listing of individual services, i.e. the [Services Directory](https://developers.arcgis.com/rest/services-reference/using-the-services-directory.htm).\n", " * You'll see a number of folders containing other services and below that a number of services listed there in the main page. \n", " * Note the types of services listed: `ImageServer`, `FeatureServer`, `MapServer`. These services provide access to different types of data. Other services provide access to data processing capabilities. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Next, click on the [`NC1Map_Census (MapServer)`](https://services.nconemap.gov/secure/rest/services/NC1Map_Census/MapServer) link to open the metadata for that [map service](https://developers.arcgis.com/rest/services-reference/map-service.htm).\n", " * You'll see a number of **properties** for the map service including a `Description`, a list of `Layers` included in that service, `Spatial Reference`, and at the very bottom, a list of the `Supported operations`. \n", " * We'll explore how we can use the [`Export Map`](https://developers.arcgis.com/rest/services-reference/export-map.htm)operation to extract data from this service. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Click on the ['Export Map'](https://services.nconemap.gov/secure/rest/services/NC1Map_Census/MapServer/export?bbox=115398.88167874969,137561.22299815627,951284.8934306827,392245.24220382335) link at the bottom of the map service metadata page. \n", " * Note the URL in the page that appears: This is a REST-based request. And the page that appears is a nifty form to help you edit and explore that REST-based URL. \n", " * Change the bounding box values to: `-79.3, 35, -77.9, 36.5`\n", " * Since those coordinates we just supplied are in NAD 83 geographic coordinates, set the bounding box spatial reference to the WKID of `4269`\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " * Click **Export Map (GET)** to generate the [URL](https://services.nconemap.gov/secure/rest/services/NC1Map_Census/MapServer/export?bbox=-79.3%2C+35%2C+-77.9%2C+36.5&bboxSR=4269&layers=&layerDefs=&size=&imageSR=&format=png&transparent=false&dpi=&time=&layerTimeOptions=&dynamicLayers=&gdbVersion=&mapScale=&rotation=&datumTransformations=&layerParameterValues=&mapRangeValues=&layerRangeValues=&f=html) reflecting our changes and display the results." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " * Enter `show:0` in the Layers: box to show only the first layer contained in this map service (1970 Census Boundary/Population). Upate the map by hitting **Export Map (GET)** again. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " * Change the Format from `HTML` to `Image` and hit **Export Map (GET)** again. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " * Copy the [URL](https://services.nconemap.gov/secure/rest/services/NC1Map_Census/MapServer/export?bbox=-79.3%2C+35%2C+-77.9%2C+36.5&bboxSR=4269&layers=show%3A0&layerDefs=&size=&imageSR=&format=png&transparent=false&dpi=&time=&layerTimeOptions=&dynamicLayers=&gdbVersion=&mapScale=&rotation=&datumTransformations=&layerParameterValues=&mapRangeValues=&layerRangeValues=&f=image) of the generated page and past between the quotes in code block below and run it. *We've captured that same image!* " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import Image\n", "Image(url='https://services.nconemap.gov/secure/rest/services/NC1Map_Census/MapServer/export?bbox=-79.3%2C+35%2C+-77.9%2C+36.5&bboxSR=4269&layers=show%3A0&layerDefs=&size=&imageSR=&format=png&transparent=false&dpi=&time=&layerTimeOptions=&dynamicLayers=&gdbVersion=&mapScale=&rotation=&datumTransformations=&layerParameterValues=&mapRangeValues=&layerRangeValues=&f=image')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dissecting a Map Service REST request\n", "Now let's dissect that URL into a service endpoint (its address) and a list of parmaters. \n", "\n", "Below is the full url: \n", "```html\n", "https://services.nconemap.gov/secure/rest/services/NC1Map_Census/MapServer/export?bbox=-79.3%2C+35%2C+-77.9%2C+36.5&bboxSR=4269&layers=show%3A0&layerDefs=&size=&imageSR=&format=png&transparent=false&dpi=&time=&layerTimeOptions=&dynamicLayers=&gdbVersion=&mapScale=&rotation=&datumTransformations=&layerParameterValues=&mapRangeValues=&layerRangeValues=&f=image\n", "```\n", "\n", "Everything up to the `?` is the **service end point** (the server's internet address and the service location). Everything after that are **parameters** separated by `&`. \n", "\n", "* Break those into components we can use with the `requests` package, i.e. a URL variable and a dictionary of parmeter name:value pairs. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "theURL = 'https://services.nconemap.gov/secure/rest/services/NC1Map_Census/MapServer/export'\n", "params = {\"bbox\":\"-79.3, 35,-77.9, 36.5\",\n", " \"bboxSR\":\"4269\",\n", " \"layers\":\"show:0\",\n", " \"layerDefs\":\"\",\n", " \"size\":\"\",\n", " \"imageSR\":\"\",\n", " \"format\":\"png\",\n", " \"transparent\":\"false\",\n", " \"dpi\":\"\",\n", " \"time\":\"\",\n", " \"layerTimeOptions\":\"\",\n", " \"dynamicLayers\":\"\",\n", " \"gdbVersion\":\"\",\n", " \"mapScale\":\"\",\n", " \"rotation\":\"\",\n", " \"datumTransformation\":\"\",\n", " \"layerParameterValue\":\"\",\n", " \"mapRangeValues\":\"\",\n", " \"layerRangeValues\":\"\",\n", " \"f\":\"image\"\n", " } " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Now, let's import the `requests` package and execute our REST request. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#import the modules\n", "import requests" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "response = requests.get(theURL, params)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import Image\n", "Image(response.content)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, it's just the same as above, but we can easily change values in our `params` dict and modify the output. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Zoom more into Durham and show a different layer\n", "params['bbox'] = '-79.0, 35.85, -78.8, 36.25'\n", "params['layers'] = 'show:8'\n", "response = requests.get(theURL, params)\n", "Image(response.content)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Add a layer definition to just show durham county\n", "params['layerDefs']=\"{8:GEOID10 LIKE '37063%'}\"\n", "response = requests.get(theURL, params)\n", "Image(response.content)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.12" } }, "nbformat": 4, "nbformat_minor": 2 }