This JS file present on the page handles all the magic behind the scene, and defines where the spreadsheet can be found and how to use the GIS. However, it is minified and obscured so not the easiest one to read https://www.toronto.ca/resources/swm_collection_calendar/scripts/swm_collection_calendar.js
In short, you've two options:
- Trust that the site (it's wordpress based) and the google APIs and generated URLs are stable enough that those addresses don't change over the course of 2020, and that you can just hardcode those links to read out the information you need. If you prettify the code you'll find a link to this spreadsheet: https://docs.google.com/spreadsheets/d/1Om0nwrYzeombeuMf-1pMksyG7oaTdXVpN3vR7-qrjdo/pubhtml It is also available as CSV file, and with a bit of additional searching as JSON too. If you do a search through the GIS service, your location is returned with the Friday2 code. Meaning that you can now take the spreadsheet as base, and look for rows with Friday2 in the calendar column. That should be teh easiest way.
- This is usually my preferred way: I don't trust those addresses to be stable and if possible will have my scraper figure out that information on its own. Take the
swm_collection_calendar.js
file as a base, do a text search (regex maybe) for the gis.toronto.ca endpoint and the corresponding path to be defined, dynamically format the URL, and continue from there so the system can recover if the files were to change. From there, do the same with the spreadsheets address and dynamically set it up. Do note that this option is definitely advanced usage. I actually utilised this method in a black box third party automated testing job I had to do once for my work.
For a more detailed description of how the page works, the swm_collection_calendar.js
defines a number of endpoints that are checked one by one. First the address search field on the page. The contents of that box are appended to https://map.toronto.ca/geoservices/rest/search/rankedsearch?searchString=
, with the special characters URL encoded. You can automate this step in Node-RED through an inject node and a simple HTTP request:
[{"id":"5b2164ff.2af9f4","type":"http request","z":"a3aaf733.357c88","name":"","method":"GET","ret":"obj","paytoqs":true,"url":"https://map.toronto.ca/geoservices/rest/search/rankedsearch","tls":"","persist":false,"proxy":"","authType":"","x":250,"y":400,"wires":[["bba60015.07f7d8"]]},{"id":"e14673e0.7b49f8","type":"inject","z":"a3aaf733.357c88","name":"","topic":"","payload":"{\"searchString\":\"<search query>\"}","payloadType":"json","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":110,"y":400,"wires":[["5b2164ff.2af9f4"]]},{"id":"bba60015.07f7d8","type":"debug","z":"a3aaf733.357c88","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":430,"y":400,"wires":[]}]
Through that JSON response you get the Latitude and Longitude of the location, which are then inserted in the GIS service API: The base address for that can be found in the javascript file too, and is https://gis.toronto.ca/arcgis/rest/services/primary/cot_geospatial21_mtm/MapServer
.
This is further appended with the following syntax: <HOST>/3/query?where=&text=&objectIds=&time=&geometry=<LNG>%2C<LAT>&geometryType=esriGeometryPoint&inSR=4326&spatialRel=esriSpatialRelWithin&relationParam=&outFields=AREA_ID%2CAREA_ATTR_ID%2CPARENT_AREA_ID%2CAREA_SHORT_CODE%2CAREA_NAME%2CAREA_DESC&returnGeometry=false&maxAllowableOffset=&geometryPrecision=&outSR=3857&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&returnDistinctValues=false&returnTrueCurves=false&resultOffset=&resultRecordCount=&f=pjson
. In that <HOST>
is the base URL, <LNG>
has to be replaced with the longitude and <LAT>
with the latitude. This can be done in a change node with JSONata, for example. That too returns a JSON, in which you can find the key.
Finally, the google sheets URL is formatted, this is a bit more complicated but can be found there too. Check the Javascript file if you're truly interested in how that part works