-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcrawler.py
128 lines (115 loc) · 4.94 KB
/
crawler.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
import datetime
import pprint
import random
import requests
import time
class TracksCrawler():
def __init__(self, cartodbAPI, debug=False):
self.cartodbAPI = cartodbAPI
self.URL = 'https://api.findmespot.com/spot-main-web/consumer/rest-api/2.0/public/feed/{tracker_id}/message.json'
self.DEBUG = debug
self._get_trackers_metadata()
def _generate_random_message(self, name):
"""
For development purposes only. Will generate a random message that resembles one coming from the real SPOT API
:param name: name of the tracked person
:return: message with some random (but plausible) values
"""
now = datetime.datetime.now()
msg = {
'@clientUnixTime': "0",
'id': int(random.random() * 100000),
'messengerId': "0-8255037",
'messengerName': name,
'unixTime': time.mktime(now.timetuple()),
'messageType': "TRACK",
'latitude': 51 + (random.random() * 10),
'longitude': 2 + (random.random()),
'modelId': "SPOT2",
'showCustomMsg': "Y",
'dateTime': now.isoformat(),
'batteryState': "GOOD",
'hidden': '0'
}
return msg
def _generate_random_riders(self):
self.riders = [{'full_name': 'John Doe', 'tracker_id': '494-eil4824dqe'},
{'full_name': 'Eric Foo', 'tracker_id': '49242-dqie8473he93'}]
def _get_trackers_metadata(self):
"""
Fetches trackers metadata from the trackers table @ CartoDB. A CartoDB API must be set since this table is not
public. The resulting rider names and their corresponding tracker ids are cached.
:return: nothing
"""
if self.DEBUG:
self._generate_random_riders()
else:
sql = 'SELECT * FROM riders'
params = {'q': sql, 'api_key':self.cartodbAPI}
r = requests.get('https://bartaelterman.cartodb.com/api/v2/sql', params=params)
data = r.json()['rows']
self.riders = data
def _fetch_messages_for_rider(self, rider):
messages = []
if self.DEBUG:
for i in range(10):
messages.append(self._generate_random_message(rider['full_name']))
else:
url = self.URL.format(tracker_id=rider['tracker_id'])
print url
r = requests.get(url)
if r.status_code == 200:
data = r.json()
if u'errors' in data['response'].keys():
pprint.pprint(data['response']['errors'])
else:
messages = data['response']['feedMessageResponse']['messages']['message']
return messages
def _existing_message_ids(self):
"""
Fetch existing message_ids in the cartodb table
:return: message_ids
"""
if self.DEBUG:
return [1, 2, 3]
else:
sql = 'SELECT message_id FROM tracks;'
params = {'q': sql, 'api_key':self.cartodbAPI}
r = requests.get('https://bartaelterman.cartodb.com/api/v2/sql', params=params)
data = r.json()['rows']
return [x['message_id'] for x in data]
def _write_messages_to_cartodb(self, message):
"""
Write the incoming messages to the Cartodb table.
:param messages: list of incoming messages
:return:
"""
if not self.DEBUG:
sql = """INSERT INTO tracks
(message_id, battery_state, date_time, latitude, longitude, rider_full_name, the_geom)
SELECT '{0}', '{1}', '{2}', {3}, {4}, '{5}', ST_SetSRID(ST_Point({4}, {3}),4326)
WHERE NOT EXISTS (
SELECT 1 FROM tracks WHERE message_id='{0}'
)""".format(
str(message['id']), message['batteryState'], message['dateTime'], message['latitude'],
message['longitude'], message['rider_name'])
print sql
params = {'q': sql, 'api_key':self.cartodbAPI}
r = requests.get('https://bartaelterman.cartodb.com/api/v2/sql', params=params)
print('API_RESPONSE: {0}: {1}: {2}'.format(message['rider_name'], r.status_code, r.text))
def fetch_new_messages(self):
existing_messages = self._existing_message_ids()
messages_to_write = []
for rider in self.riders:
messages = self._fetch_messages_for_rider(rider)
for message in messages:
if str(message['id']) not in existing_messages:
message['rider_name'] = rider['full_name']
messages_to_write.append(message)
self._write_messages_to_cartodb(message)
if self.DEBUG:
return messages_to_write
if __name__ == '__main__':
crawler = TracksCrawler('a72c682f541f69035c0698dacd029d3d19409aa6', debug=False)
msgs = crawler.fetch_new_messages()
pprint.pprint(msgs)