from pandas import DataFrame
from itertools import permutations
from collections import Counter
import requests
import json
from math import *
from numpy import *
from multiprocessing.dummy import Pool as dPool
from multiprocessing import Pool as Pool
def to_dict(in_str):
head2 = [x.split(":",1) for x in in_str.split("\n")]
head3 = {x[0].strip():x[1].strip() for x in head2}
return head3
def get_session_id():
out = '{"appName":"Grindr","appVersion":"2.1.3","authenticationToken":"c22d27b4c2e5b3083a2d42ad974f3294f22a008710a4e4dc247554ab12dc974b","deviceIdentifier":"","platformName":"Android","platformVersion":"19","profileId":"39724408"}'
session_header = requests.post('https://primus.grindr.com/2.0/session',headers = to_dict("""Accept: application/json
Content-Type: application/json; charset=utf-8
Content-Length: 223
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; SAMSUNG-SM-G900A Build/KOT49H)
Host: primus.grindr.com
Connection: Keep-Alive
Accept-Encoding: gzip"""),data=out).headers
return session_header['session-id']
def get_nearby_profiles(lati,longi,session_id= None,return_only_dist = True):
if session_id ==None:
session_id = get_session_id()
out1 = '{"filter":{"onlineOnly":false,"page":1,"quantity":1000},"lat":LAT,"lon":LONG}'
out1 = out1.replace('LAT',str(lati))
out1 = out1.replace('LONG',str(longi))
in1 = to_dict("""Accept: application/json
Content-Type: application/json; charset=utf-8
Content-Length: 91
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; SAMSUNG-SM-G900A Build/KOT49H)
Host: primus.grindr.com
Connection: Keep-Alive
Accept-Encoding: gzip""")
in1['Session-Id'] = session_id
ret = json.loads( requests.post('https://primus.grindr.com/2.0/nearbyProfiles',headers = in1,data=out1).text)['profiles']
if return_only_dist:
return [x for x in ret if x.get('showDistance')]
else:
return ret
def triangulate(three_pts):
"""
Thanks to http://gis.stackexchange.com/users/50/wwnick
--->>> http://gis.stackexchange.com/questions/66/trilateration-using-3-latitude-and-longitude-points-and-3-distances/415#415
for this code
"""
#assuming elevation = 0
earthR = 6371
LatA = three_pts[0][0]
LonA = three_pts[0][1]
DistA = three_pts[0][2]
LatB = three_pts[1][0]
LonB = three_pts[1][1]
DistB = three_pts[1][2]
LatC = three_pts[2][0]
LonC = three_pts[2][1]
DistC = three_pts[2][2]
#using authalic sphere
#if using an ellipsoid this step is slightly different
#Convert geodetic Lat/Long to ECEF xyz
# 1. Convert Lat/Long to radians
# 2. Convert Lat/Long(radians) to ECEF
xA = earthR *(math.cos(math.radians(LatA)) * math.cos(math.radians(LonA)))
yA = earthR *(math.cos(math.radians(LatA)) * math.sin(math.radians(LonA)))
zA = earthR *(math.sin(math.radians(LatA)))
xB = earthR *(math.cos(math.radians(LatB)) * math.cos(math.radians(LonB)))
yB = earthR *(math.cos(math.radians(LatB)) * math.sin(math.radians(LonB)))
zB = earthR *(math.sin(math.radians(LatB)))
xC = earthR *(math.cos(math.radians(LatC)) * math.cos(math.radians(LonC)))
yC = earthR *(math.cos(math.radians(LatC)) * math.sin(math.radians(LonC)))
zC = earthR *(math.sin(math.radians(LatC)))
P1 = array([xA, yA, zA])
P2 = array([xB, yB, zB])
P3 = array([xC, yC, zC])
#from wikipedia
#transform to get circle 1 at origin
#transform to get circle 2 on x axis
ex = (P2 - P1)/(linalg.norm(P2 - P1))
i = dot(ex, P3 - P1)
ey = (P3 - P1 - i*ex)/(linalg.norm(P3 - P1 - i*ex))
ez = cross(ex,ey)
d = linalg.norm(P2 - P1)
j = dot(ey, P3 - P1)
#from wikipedia
#plug and chug using above values
x = (pow(DistA,2) - pow(DistB,2) + pow(d,2))/(2*d)
y = ((pow(DistA,2) - pow(DistC,2) + pow(i,2) + pow(j,2))/(2*j)) - ((i/j)*x)
# only one case shown here
z = sqrt(pow(DistA,2) - pow(x,2) - pow(y,2))
#triPt is an array with ECEF x,y,z of trilateration point
triPt = P1 + x*ex + y*ey + z*ez
#convert back to lat/long from ECEF
#convert to degrees
lat = math.degrees(math.asin(triPt[2] / earthR))
lon = math.degrees(math.atan2(triPt[1],triPt[0]))
return lat, lon
def get_grid(left,right,num_pts):
num_pts = num_pts/10
ret = []
x = linspace(left[0], right[0], num_pts)
y = linspace(left[1], right[1], num_pts)
for i in range(num_pts):
for j in range(num_pts):
ret.append([x[i],y[j]])
return ret
def get_requ(incoming):
a,b = incoming
while True:
try:
return get_nearby_profiles(a,b),incoming
except:
continue
def triangulate_multiple(input_dist):
o =[]
for k in list(permutations(input_dist,3)):
tria = triangulate(k)
if not isnan(tria[0]) and not isnan(tria[1]):
o.append(tria)
if len(o)>3:
break
return mean([x[0] for x in o]),mean([x[1] for x in o])
def process_point(each_user):
global profiles
out = []
values = seen[each_user]
if len(values)<3:
return None
else:
loc = triangulate_multiple(values)
if not isnan(loc[0]) and not isnan(loc[1]):
obs = {}
obs ['lat'] = loc[0]
obs ['long'] = loc[1]
obs ['name'] = profiles[each_user].get(u'displayName','')
obs ['headline'] = profiles[each_user].get('headline','')
obs ['image'] = 'http://cdns.grindr.com/images/profile/1024x1024/{}'.format(profiles[each_user].get(u'profileImageMediaHash'))
return obs
def create_profiles(unmerged_profiles):
seen = {}
for data,cord in unmerged_profiles:
for each_person in data:
ID = each_person[u'profileId']
if each_person['showDistance']:
profiles[ID] = each_person
return (seen,profiles)
def download_grid(grid_pts,num_threads= 20):
p1 = dPool(num_threads)
ret = p1.map(get_requ,grid_pts)
p1.close()
return create_profiles(ret)
def triangulate_profiles(seen, processes = 8):
pool = Pool(processes)
result_iterator = pool.imap_unordered(process_point,seen.keys())
for i in result_iterator:
if i !=None:
yield i
if __name__ == '__main__':
# define GPS grid to search
# left is GPS location ==> bottom left bounding point
# right is GPS location ==> top right bounding point
# different grids can be separated by new lines
locations = """42.363612, -71.130838+42.363612, -71.130838""".split("\n")
# locations = """42.363612, -71.130838+42.363612, -71.130838
# 37.757727, -122.446204+37.791716, -122.393418""".split("\n")
locations = [[[float(t.strip()) for t in y.split(",")] for y in x.split("+")] for x in locations]
gps_pts_to_use_for_search = []
for loc in locations:
gps_pts_to_use_for_search+= get_grid(loc[0],loc[1],20)
print "INFO: downloading {} GPS locations".format(len(gps_pts_to_use_for_search))
seen_profiles,profiles = download_grid(gps_pts_to_use_for_search)
print "INFO: creating GPS locations of {} observed users".format(len(profiles))
all_pts = []
for each_located_grindr in triangulate_profiles(seen_profiles):
each_located_grindr['address'] = geo_locate(each_located_grindr['lat'],each_located_grindr['long'])
print each_located_grindr
all_pts.append(each_located_grindr)
DataFrame(all_pts).to_csv('GPS.csv',index=False,encoding='utf-8')
运行时会出现错误
NameError: global name 'profiles' is not defined
有什么想法吗?
答案 0 :(得分:0)
只需在if之后定义profiles变量,我们在包含之后:
from multiprocessing import Pool as Pool
profiles = {}
def to_dict(in_str):