-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgenerate-map-data.py
317 lines (241 loc) · 9.62 KB
/
generate-map-data.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#!/usr/bin/python3
# This script generates a html file of all the photos on the
# Flickr user's photostream, that can be viewed in a web browser as a map
#
# Author: Haraldo Albergaria
# Date : Jul 21, 2020
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
import flickrapi
import json
import os
import sys
import time
import math
from countries_info import getCountryInfo
# ================= CONFIGURATION VARIABLES =====================
# Limits
photos_per_page = '500'
max_number_of_pages = 10
max_number_of_photos = max_number_of_pages * int(photos_per_page)
max_number_of_markers = 2000
# ===============================================================
# get full script's path
run_path = os.path.dirname(os.path.realpath(__file__))
# check if there is a api_credentials file and import it
if os.path.exists("{}/api_credentials.py".format(run_path)):
import api_credentials
else:
print("ERROR: File 'api_credentials.py' not found. Create one and try again.")
sys.exit()
# Credentials
api_key = api_credentials.api_key
api_secret = api_credentials.api_secret
# Flickr api access
flickr = flickrapi.FlickrAPI(api_key, api_secret, format='parsed-json')
#===== MAIN CODE ==============================================================#
# get group id from group url on config file
try:
group_info = flickr.urls.lookupGroup(api_key=api_key, url='flickr.com/groups/the-map-group/')['group']
group_id = group_info['id']
group_name = group_info['groupname']['_content']
except:
sys.exit()
# stores the coordinates of the markers
coordinates = []
# get the total number of photos
try:
photos = flickr.groups.pools.getPhotos(api_key=api_key, group_id=group_id, per_page=photos_per_page)
npages = int(photos['photos']['pages'])
total = int(photos['photos']['total'])
print('Generating map for \'{}\''.format(group_name))
print('{} photos in the pool'.format(total))
except:
sys.exit()
# current number of photos on photostream
current_total = total
# difference on number of photos from previous run
delta_total = int(total)
# if there is no difference, finish script
if os.path.exists("{}/last_total.py".format(run_path)):
import last_total
delta_total = int(current_total) - int(last_total.number)
if delta_total == 0:
print('No changes on number of photos since last run.\nAborted.')
sys.exit()
# if difference > 0, makes total = delta_total
# to process only the new photos, otherwise
# (photos were deleted), run in all
# photostream to update the entire map
if delta_total > 0:
total = delta_total
if total != delta_total:
print('{} new photo(s)'.format(total))
else:
n_deleted = abs(delta_total)
if os.path.exists("{}/locations.py".format(run_path)):
os.system("rm {}/locations.py".format(run_path))
print('{} photo(s) deleted from photos pool.\nThe corresponding markers will also be deleted'.format(n_deleted))
print('Extracting photo coordinates and ids...')
# get number of pages to be processed
npages = math.ceil(total/int(photos_per_page))
# to be included on map
n_photos = 0 # counts number of photos
n_markers = 0 # counts number of markers
# extracts only the photos below a number limit
if npages > max_number_of_pages:
npages = max_number_of_pages
total = max_number_of_pages * int(photos_per_page);
print("Extracting for the last {} photos".format(total))
# process each page
for pg in range(1, npages+1):
try:
page = flickr.groups.pools.getPhotos(api_key=api_key, group_id=group_id, privacy_filter='1', extras='geo,tags,url_sq', page=pg, per_page=photos_per_page)['photos']['photo']
except:
sys.exit()
photos_in_page = len(page)
# process each photo on page
for ph in range(0, photos_in_page):
photo = page[ph]
# variable to store information if already exist a marker
# on the same photo's coordinates
marker_exists = False
n_photos += 1
# get coordinates from photo
longitude = float(photo['longitude'])
latitude = float(photo['latitude'])
photo_owner = photo['owner']
# read each markers coordinates and append photo is case
# there is already a marker on the same coordinate
for coord in coordinates:
if longitude == coord[0][0] and latitude == coord[0][1]:
coord[2].append([photo['id'], photo['url_sq']])
marker_exists = True
break
# create a new marker to be added to the map
if not marker_exists:
coordinates.append([[longitude, latitude], photo_owner, [[photo['id'], photo['url_sq']]]])
n_markers += 1
# stop processing photos if any limit was reached
if n_photos >= total or n_photos >= max_number_of_photos or n_markers >= max_number_of_markers:
break
print('Batch {0}/{1} | {2} photo(s) in {3} marker(s)'.format(pg, npages, n_photos, n_markers), end='\r')
# stop processing pages if any limit was reached
if n_photos >= total:
break
if n_photos >= max_number_of_photos:
print("\nMaximum number of photos on map reached!", end='')
break
if n_markers >= max_number_of_markers:
print("\nMaximum number of markers on map reached!", end='')
break
print('\nAdding marker(s) to map...')
# check if there is a file with the markers on map already
# and import it otherwise created a new variable
locations = []
if os.path.exists("{}/locations.py".format(run_path)):
try:
from locations import locations
except:
pass
# create a new location file or overwrite existing one
locations_file = open("{}/locations.py".format(run_path), 'w')
locations_file.write("locations = [\n")
# get the number of markers (locations) already on map
n_locations = len(locations)
if n_locations > 0:
print('Map already has {} marker(s)'.format(n_locations))
# counts the number of new photos added to markers
new_photos = 0
# process each marker info already on map
for loc in range(n_locations):
# get info for photos on marker
photos_info = locations[loc][3]
n_photos = int(locations[loc][4])
# get number of photos (coordinates) to be added to map
n_coords = len(coordinates)
# iterate over each coordinate
for coord in range(n_coords-1, -1, -1):
# if there is already a marker on the same coordinate
if coordinates[coord][0] == locations[loc][0]:
photo_owner = locations[loc][1]
# read each photo already on the marker
for photo in coordinates[coord][2]:
photo_id = photo[0]
thumb_url = photo[1]
# if the photo is not already on marker, add the photo to it
if [photo_id, thumb_url] not in photos_info:
photos_info.append([photo_id, thumb_url])
new_photos += 1
# remove photo info from
# coordinates to be added
coordinates.pop(coord)
# update the number of photos on marker
locations[loc][3] = photos_info
locations[loc][4] = len(photos_info)
locations_file.write(" {}".format(locations[loc]))
if len(coordinates) > 0:
locations_file.write(",\n")
else:
locations_file.write("\n")
if new_photos > 0:
print('Added {} new photo(s) to existing markers'.format(new_photos))
# reverse the coordinates order so
# the newest ones go to the end
coordinates.reverse()
# check if there is remaining markers to be added
n_markers = len(coordinates)
if n_markers > 0:
print('{} new marker(s) will be added to the map'.format(n_markers))
# remove the oldest locations to make
# room for new markers without violate
# the max number of markers limit
new_locations_length = len(locations) + n_markers
if new_locations_length >= max_number_of_markers:
new_locations_length = max_number_of_markers - n_markers
print('Max number of markers reached. Removing {} marker(s)...'.format(n_markers))
while len(locations) > new_locations_length:
locations.pop(0)
new_markers = 0
# iterate over each marker to be added
for marker_info in coordinates:
new_markers += 1
# get coordinates of the new marker
longitude = float(marker_info[0][0])
latitude = float(marker_info[0][1])
photo_owner = marker_info[1]
try:
country_info = getCountryInfo(latitude, longitude, dict())
country_code = country_info[0]
country_name = country_info[1]
except:
country_code = ''
country_name = ''
# write it to locations file
locations_file.write(" [[{0}, {1}], \'{2}\', \'{3}\', [".format(longitude, latitude, country_code, photo_owner))
# counts the number of photos
n_photos = 0
# iterate over each photo
for photo in marker_info[2]:
# add photo to marker, writing it to locations file
locations_file.write("[\'{0}\', \'{1}\']".format(photo[0], photo[1]))
n_photos += 1
if n_photos < len(marker_info[2]):
locations_file.write(", ")
# finish marker writing to location file
locations_file.write("], {}]".format(n_photos))
if new_markers < n_markers:
locations_file.write(",\n")
else:
locations_file.write("\n")
print('Added marker {0}/{1}'.format(new_markers, n_markers), end='\r')
# finish script
if new_markers > 0:
print('')
else:
print('No new markers were added to the map')
print('Finished!')
locations_file.write("]\n")
locations_file.close()
# update last_total file with the new value
if os.path.exists("{}/locations.py".format(run_path)):
os.system("echo \"number = {0}\" > {1}/last_total.py".format(current_total, run_path))