Closed cookies4All closed 3 years ago
It doesn't take much to update it to Python 3, thanks for going through and adding that here. If you wanted to make a pull request I would be happy to review and bring in your changes, otherwise I can basically duplicate them to make an "official" release of them with credit.
I am converting the main branch to Python3, and leaving the desktop version as a separate branch in case anyone needs it.
**For ArcPro the Python script needs to be updated from Python 2x to Python 3.
below is an updated versrion that will work in ArcPro running Python3 also the zipped .py file
DataServicePillager.zip**
-- coding: utf-8 --
-------------------------------------------------------------------------------
Purpose: Extract data from an ArcGIS Service, in chunks defined by
the service Max Record Count to get around that limitation.
Requires that JSON is supported by the service
#
Author: Grant Herbert
#
Created: 12/11/2014
Copyright: (c) Grant Herbert 2014
Licence: MIT License
-------------------------------------------------------------------------------
""" This software is designed for use with ArcGIS as a toolbox tool.
This software is distributed with an MIT License.
THIS SOFTWARE IS SUPPLIED AS-IS, WITH NO WARRANTY OR GUARANTEE, EXPLICT OR IMPLICIT. THE AUTHORS OF THIS SOFTWARE ASSUME NO LIABILITY FROM IMPROPER USE OR OPERATION.
"""
try: import sys import arcpy import urllib import urllib.request import json import os import codecs import datetime import time from urllib.parse import urlparse from urllib.parse import urlunsplit import itertools import re except ImportError as e: print (e)
--------
globals
arcpy.env.overwriteOutput = True count_tries = 0 max_tries = 5 sleep_time = 2
--------
def trace(): import sys import traceback tb = sys.exc_info()[2] tbinfo = traceback.format_tb(tb)[0] # script name + line number line = tbinfo.split(", ")[1]
Get Python syntax error
def output_msg(msg, severity=0): """ Adds a Message (in case this is run as a tool) and also prints the message to the screen (standard output) :param msg: text to output :param severity: 0 = none, 1 = warning, 2 = error """ print (msg)
Split the message on \n first, so that if it's multiple lines,
def test_url(url_to_test): """test a url for validity (non-404) :param token_url: String """ try: if urllib.request.urlopen(url_to_test): output_msg("Ho, a successful url test: {}".format(url_to_test)) return url_to_test except urllib.request.HTTPError as e: if e.code == 404: output_msg("Arr, 404 error: {}".format(url_to_test)) return None except urllib.request.URLError as e: return None
def get_adapter_name(url_string): """extract web adaptor name from endpoint :param url_string: url of service """ u = urlparse(url_string) if u.netloc.find('arcgis.com') > -1:
is an esri domain
def get_referring_domain(url_string): """get referring domain part of url :param url_string url of service """ u = urlparse(url_string) if u.netloc.find('arcgis.com') > -1:
is an esri domain
def get_token(username, password, referer, adapter_name, client_type='requestip', expiration=240): """ Get Esri access token. Uses requestip by default :param username: valid username :param password: valid password :param referer: referer url :param adapter_name: name of the arcgis server adapter :param client_type: whether to use referer value over requestip (default False uses requestip) :param expiration: optional validity time in minutes (default 240) """ query_dict = {'username': username, 'password': password, 'expiration': str(expiration), 'client': client_type, 'referer': referer, 'f': 'json'}
def get_all_the_layers(service_endpoint, tokenstring): """walk the endpoint and extract feature layer or map layer urls :param service_endpoint starting url :param tokenstring string containing token for authentication """ service_call = urllib.request.urlopen(service_endpoint + '?f=json' + tokenstring).read() if service_call: service_layer_info = json.loads(service_call, strict=False) if service_layer_info.get('error'): raise Exception("Gaaar, 'service_call' failed to access {0}".format(service_endpoint)) else: raise Exception("Gaaar, 'service_call' failed to access {0}".format(service_endpoint))
def get_data(query): """ :param query: url query string Download the data. Return a JSON object Automatically retries up to max_tries times. """ global count_tries global max_tries global sleep_time
def combine_data(fc_list, output_fc): """ :param fc_list: array of featureclass paths as strings :param output_fc: path to output dataset Combine the downloaded datafiles into one fastest approach is to use cursor """ if len(fc_list) == 1: arcpy.Copy_management(fc_list[0], output_fc) output_msg("Created {0}".format(output_fc)) else: for fc in fc_list: if fc_list.index(fc) == 0:
append to first dataset. much faster
def grouper(iterable, n, fillvalue=None): """ Cut iterable into n sized groups from itertools documentation, may not be most efficient, fillvalue causes issue :param iterable: object to iterate over :param n: int value to group :param fillvalue: value to fill with if chunk smaller than n """ args = [iter(iterable)] n return itertools.zip_longest(args, fillvalue=fillvalue)
def create_layer_file(service_info, service_name, layer_source, output_folder): """ write out a layer file from service renderer information, providing :param service_info: json (to extract the drawingInfo from) :param service_name: String :param layer_source: String path to file :param output_folder: String path """ try: render_info = {"drawingInfo": {"renderer": {}}} if 'drawingInfo' not in service_info: render_info["drawingInfo"]['renderer'] = service_info.get('drawingInfo').get('renderer')
def make_service_name(service_info, output_workspace, output_folder_path_len): global service_output_name_tracking_list global output_type
-------------------------------------------------
def main(): global count_tries global max_tries global sleep_time global service_output_name_tracking_list global output_type
if name == 'main': main()