0

I'm trying to create a KML that will dynamically update using an API call in python based off where the user is currently looking. I've tried to include as much commented work as possible for what I've already done, hopefully it's not too much.

Right now, I'm using a given list of locations and the Wikipedia API to (1) Look up the coordinates for the given locations, (2) Parse the JSON output for the Coordinates and the PageID, and (3) Creating a KML that shows the Location and the Webpage linked to the location. This all looks like the following, just for reference:

import requests # Used to access webpages
import re # Used to select and clean text
import objectpath # Used to parse JSON response cleanly
import wikipedia # Used to interact with Wikipedia
import simplekml # Used to create the kml from the csv

# Create url parameters for Wiki API; location names goes between these two
base_URL = "https://en.wikipedia.org/w/api.php?action=query&prop=coordinates&titles="
end_URL = '&format=json'

# Mock list of locations:
locations = ['Colorado', 'Texas', 'Florida']
locations_Meta = []

# Create list of lists that will include the metadata for each location
for x in locations:
    locations_Meta.append([x])

# Get the JSON URL from each location
location_API_Pages = []

for place in locations:
    API_URL = base_URL + str(place) + end_URL # API page to get the coords
    location_API_Pages.append(API_URL) # Add API URLs to list

# Get the coordinates from each locations JSON output
tempList = []
tempList1 = []
url_pre = 'https://en.wikipedia.org/?curid=' # Adding a pageID to this makes a complete URL
count = len(locations) # Length of locations so script knows how many times to run the loop

# Generate the JSON output from the webpage and pull out the coordinate information
for x in location_API_Pages:
    r = requests.get(str(x)) # Access the Wikipedia API
    data = r.json() # Turn response into JSON
    tree_obj = objectpath.Tree(data) # Turn the JSON output into a objectpath tree
    tempList.append(list(tree_obj.execute('$..coordinates'))) # Search the tree for specifically
    tempList1.append(list(tree_obj.execute('$..pages'))) # Search the tree for the pagesIDs

# Seperate the coordinates from the rest of the JSON file
for x in range(0, count):
    for k,v in tempList[x][0].items(): # The piece holding the coords is in a dict
        if k in ('lat', 'lon'):
            locations_Meta[x].append(v) # Append the coords

# Seperate the pageID from the rest of the JSON file and 
for x in range(0, count):
    for k,v in tempList1[x][0].items(): # The piece holding the pageIDs is in a dict
        locations_Meta[x].append(url_pre + k) # Append pageIDs to later turn into URLs

# Create KML from the CSV that was created as proof of concept
kml = simplekml.Kml()

for x in range(0, count):
        kml.newpoint(name=locations_Meta[x][0], description=locations_Meta[x][3], coords=[(locations_Meta[x][2],locations_Meta[x][1])])
kml.save('Locations.kml')

(This is my first time parsing JSON with python - or anything. I'm sure there's better ways to do my above code, but that's not what I'm here to ask.)

Now, I know you can dynamically request pages with an API call using a lat and long. What I would like to do is use Wikipedia's built-in search method to dynamically retrieve and display pages from their API call found here:

current_location_lat = 'Somehow get users current view from the loaded KML platform'.
current_location_long = 'Somehow get users current view from the loaded KML platform'

Wiki_API_URL = "https://en.wikipedia.org/w/api.php?action=query&list=geosearch&gscoord={0}%7C-{1}&gsradius=10000&gslimit=100".format(current_location_lat, current_location_long)

I can create a static KML from a fixed data source, but I have no idea how to create this kind of dynamic 'linked' KML. Can anyone help point me in the right direction?

1 Answer 1

1

Sounds like what you're looking for is a KML NetworkLink with a view-based refresh, and a serverside script that gets the view parameters from the NetworkLink request, and sends back new KML content based on the user's view.

In a bit more detail, you probably want a <NetworkLink> tag, whose <Link> tag uses a view-based refresh via the tags: <viewRefreshMode>onStop</viewRefreshMode> and something like: <viewRefreshTime>1</viewRefreshTime>, to wait 1 second after the user stops moving (panning/zooming) the view, before sending a new request for the KML content. That request will include the view parameters as a bounding box, or another format as specified in a <viewFormat> tag. Then you can use the user's view info to generate a new KML on the server, based in their location, and send that back to the user.

See the KML Reference sections on <NetworkLink> and <Link>. for more info: https://developers.google.com/kml/documentation/kmlreference#link

Also see the KML Tutorial guide section for examples of using this technique: https://developers.google.com/kml/documentation/kml_tut#network_links

1
  • 1
    Wanted to come back and say thank you again. The KML is in an Apache Web Server, and it makes its API call and renders the KML back to the user. Commented Mar 31, 2021 at 14:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.