2014-09-03 107 views
-7
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:全局名称的个人资料“没有定义

NameError: global name 'profiles' is not defined 

任何想法?

+2

那么它明显不是吗? 'profiles'(你在if语句中声明的)不在全局范围内。什么是神秘的奥秘? – 2014-09-03 12:07:56

+0

道歉,但我对Python完全陌生,这不是我的脚本,我如何在全局范围内定义它? – Paul 2014-09-03 12:10:54

+0

对不起,但我不会阅读你的200行代码,特别是当你(显然)在提出这个问题之前没有花时间阅读一行Python文档时。 – Anto 2014-09-03 12:35:04

回答

0

只要定义配置文件的变量外你如果在包括我们之后:

from multiprocessing import Pool as Pool 

profiles = {} 

def to_dict(in_str): 
相关问题