Skip to content

Instantly share code, notes, and snippets.

@danshev
Last active August 29, 2015 14:16
Show Gist options
  • Save danshev/de6719c1731ae3ad0430 to your computer and use it in GitHub Desktop.
Save danshev/de6719c1731ae3ad0430 to your computer and use it in GitHub Desktop.
from TwitterAPI import TwitterAPI
api = TwitterAPI("QHCFXKcJeYvFMr8XBTes3eID8",
"Zh3JhEBL8PXnfAEAAOivlB4xrX1PAfDEIdg6DsC78qs6O2Aruk",
"2401578782-7P2QUySnDc8gFHQ1vCwTrckbLLSty8tOFjrizC6",
"WNcilnQcbd0o7xnTYf1XBylsriyBb1KkNlxyTx4u4uB1s"
)
# instantiate empty lists that will hold Event data.
# these would be populated by a periodic (e.g. every 1 minute) query of "active" Events.
event_ids = []
event_upper_longitudes = []
event_lower_longitudes = []
event_upper_latitudes = []
event_lower_latitudes = []
# helper function for testing (adds an Event to the list of target Events)
def addEvent(boxNeLat, boxNeLon, boxSwLat, boxSwLon, eventID):
global event_ids
global event_upper_longitudes
global event_lower_longitudes
global event_upper_latitudes
global event_lower_latitudes
event_ids.append(eventID)
event_upper_longitudes.append(boxNeLon)
event_lower_longitudes.append(boxSwLon)
event_upper_latitudes.append(boxNeLat)
event_lower_latitudes.append(boxSwLat)
return
# add box around where I live
addEvent(32.819655, -96.802374, 32.817328, -96.807116, 2006)
# add box around Love Field
addEvent(32.861336, -96.830076, 32.829175, -96.869387, 737)
# add box around SMU
addEvent(32.847997, -96.776475, 32.834909, -96.789864, 342)
# add box around White Rock Lake
addEvent(32.852973, -96.706780, 32.814101, -96.742743, 1000)
# add box around Fort Worth Water Gardens
addEvent(32.749163, -97.324360, 32.746618, -97.328266, 420)
# add box around JPS Hospital in Fort Worth
addEvent(32.730951, -97.323065, 32.725734, -97.330017, 83)
# add box around NAS JRB Fort Worth
addEvent(32.788938, -97.413410, 32.746645, -97.463535, 1776)
# helper function to remove t.co link from tweets
def removeLink(tweetText):
# clean up general tweet text
tweetText = tweetText.replace('\n', ' ')
tweetText = tweetText.replace(' ', ' ')
link = False
if "http://t.co/" in tweetText:
target = "http://t.co/"
link = True
offset = 23
elif "https://t.co/" in tweetText:
target = "https://t.co/"
link = True
offset = 24
if link:
i = tweetText.index(target)
before = tweetText[:i]
after = tweetText[(i + offset):]
tweetText = before + after
return tweetText
# helper function to extract video or photo URL (if media is attached to the tweet)
def extractMedia(tweet):
tweetMediaURL = None
# attempt to get video
if 'extended_entities' in tweet:
if 'media' in tweet['extended_entities']:
if 'type' in tweet['extended_entities']['media'][0]:
if tweet['extended_entities']['media'][0]['type'] == 'video':
video = tweet['extended_entities']['media'][0]
# loop through variants (will get highest bitrate version of video)
for vid in video['video_info']['variants']:
if vid['content_type'] == 'video/mp4':
tweetMediaURL = vid['url']
# if no video (more valuable), then attempt to get photo
if tweetMediaURL is None:
if 'entities' in tweet:
if 'media' in tweet['entities']:
tweetMediaURL = tweet['entities']['media'][0]['media_url_https']
return tweetMediaURL
neLat = 0.0
neLon = 0.0
swLat = 0.0
swLon = 0.0
# a helper function to make it easier to work with lat/lon values copied from Google Maps
def quickBox(boxNeLat, boxNeLon, boxSwLat, boxSwLon):
global neLat
global neLon
global swLat
global swLon
neLat = boxNeLat
neLon = boxNeLon
swLat = boxSwLat
swLon = boxSwLon
return
# This function determines if a Tweet falls within a list of Events.
# Compares the coordinates of the [point-type] Tweet against pre-instantiated lists
# that contain the minimum and maximum latitudes & longitudes of all the target Events.
def eventsTweetWithin(tweetLat, tweetLon):
# there's likely a better way to do this (bringing in the target lists)
global event_ids
global event_upper_longitudes
global event_lower_longitudes
global event_upper_latitudes
global event_lower_latitudes
# instantiate the "pointer" lists
upperLonIndexes = []
lowerLonIndexes = []
upperLatIndexes = []
lowerLatIndexes = []
# Scan through the minimum & maximum lists of Event latitudes & longitudes
# We record each qualifying index into the respective "pointer" list
for (index, event_upper_lon) in enumerate(event_upper_longitudes):
if tweetLon < event_upper_lon:
upperLonIndexes.append(index)
for (index, event_lower_lon) in enumerate(event_lower_longitudes):
if tweetLon > event_lower_lon:
lowerLonIndexes.append(index)
for (index, event_upper_lat) in enumerate(event_upper_latitudes):
if tweetLat < event_upper_lat:
upperLatIndexes.append(index)
for (index, event_lower_lat) in enumerate(event_lower_latitudes):
if tweetLat > event_lower_lat:
lowerLatIndexes.append(index)
# finally, we intersect the four "pointer" lists, thus producing (if any) the index (or indexes) that fit *all* four criteria
s = set(upperLonIndexes).intersection(lowerLonIndexes).intersection(upperLatIndexes).intersection(lowerLatIndexes)
# if the resultant set > 0, then the Tweet must "fall within" at least one Event
# - all that's left to do is, using the index (or indexes) retrieve the Event ID(s)
if len(s) > 0:
events = []
for index in list(s):
events.append(event_ids[index])
return events
else:
return None
# this is where we easily paste in our NE and SW coordinates from Google Maps
quickBox(32.953848, -96.611259, 32.647951, -96.998527)
# notice the odd ordering of lat/lon values Twitter uses -- lower left *and then* upper right using lon, lat (versus lat, lon)
stream = api.request('statuses/filter', {'locations': str(swLon) +','+ str(swLat) +','+ str(neLon) +','+ str(neLat) })
print "monitoring the box bounded by "+ str(neLat) +", "+ str(neLon) +" and "+ str(swLat) +", "+ str(swLon) +" ..."
for tweet in stream:
# verify the tweet has geo information (and a usable point-type coordinate pair)
if 'geo' in tweet:
if tweet['geo'] is not None:
if tweet['geo']['type'] == 'Point':
# get the tweet's coordinates
tweetLat = tweet['geo']['coordinates'][0]
tweetLon = tweet['geo']['coordinates'][1]
# sanity check to ensure the tweet is actually within our market bounding box
if tweetLat < neLat and tweetLat > swLat and tweetLon < neLon and tweetLon > swLon:
# analyze the tweet to see if it falls within any of our mock events
tweet_events = eventsTweetWithin(tweetLat, tweetLon)
if tweet_events is not None:
tweetText = removeLink(tweet['text'])
tweetUser = tweet['user']['screen_name']
tweetMediaURL = extractMedia(tweet)
tweetProfilePicULR = tweet['user']['profile_image_url']
# tweetUTC = parser.parse(tweet['created_at'])
print tweetUser +" is on-scene Event "+ str(tweet_events[0]) +" at "+ str(tweetLat) +", "+ str(tweetLon) + " "+ tweetText
if tweetMediaURL is not None:
print ' * '+ tweetMediaURL
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment