Created
April 5, 2018 13:48
-
-
Save solsticedhiver/d0e5696941607cfdf704ac3a92f53b82 to your computer and use it in GitHub Desktop.
Python script to query Wigle.net via its API and launch a html page with result using leaflet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>padv</title> | |
<meta name='description' content="A page showing results from wigle.net API"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico"> | |
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css"> | |
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> | |
<script src="search.geojson"></script> | |
<style> | |
#map {height: 800px; } | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<header class="page-header"> | |
<h1>Search result from wigle.net</h1> | |
</header> | |
<div class="row"> | |
<div class="col-md-11" id="map"></div> | |
<div class="col-md-1" id="ssids"> | |
<table id="results" class="table table-stripped table-condensed"> | |
<caption>Results</caption> | |
<tr><th>MAC</th></tr> | |
</table> | |
</div> | |
</div> | |
</div> | |
</body> | |
<script> | |
var map = new L.Map('map'); | |
// create the tile layer with correct attribution | |
var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; | |
var osmAttrib='Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors'; | |
var osm = new L.TileLayer(osmUrl, {minZoom: 6, maxZoom: 19, attribution: osmAttrib}); | |
map.addLayer(osm); | |
var blueIcon = new L.Icon({ | |
iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/de8203df/img/marker-icon-blue.png', | |
iconSize: [25, 41], | |
iconAnchor: [12, 41], | |
popupAnchor: [1, -34], | |
shadowSize: [41, 41] | |
}); | |
// Add data from geojson file | |
var layer = new L.geoJson(data, { | |
pointToLayer: function(point, latlng) { | |
// customize marker for each feature point | |
var marker = L.marker(latlng, {icon: blueIcon}); | |
marker.SSID = point.properties.SSID; | |
marker.MAC = point.properties.MAC; | |
marker.channel = point.properties.channel; | |
marker.first_time = point.properties.first_time; | |
marker.last_time = point.properties.last_time; | |
marker.bindTooltip('SSID: '+marker.SSID+ | |
'<br>MAC: '+marker.MAC+ | |
'<br>channel: '+marker.channel+ | |
'<br>First time seen: '+marker.first_time+ | |
'<br>Last time seen: '+marker.last_time); | |
return marker; | |
} | |
}); | |
layer.addTo(map); | |
// generate list of results | |
var first = true; | |
for (f of data.features) { | |
var res = {}; | |
res.lon = f.geometry.coordinates[0]; | |
res.lat = f.geometry.coordinates[1]; | |
res.MAC = f.properties.MAC; | |
res.SSID = f.properties.SSID; | |
res.channel = f.properties.channel; | |
res.first_time = f.properties.first_time; | |
res.last_time = f.properties.last_time; | |
$('#results').append('<tr><td><a class="result" href="#" data-lat="'+res.lat+'" data-lon="'+res.lon+'">'+res.MAC+'</a></td></tr>'); | |
if (first) { | |
// move map to first result location | |
map.setView(new L.LatLng(res.lat, res.lon), 12); | |
first = false; | |
} | |
} | |
// pan map to location of ssid | |
$('.result').click(function() { | |
map.panTo([$(this).data('lat'), $(this).data('lon')]); | |
}); | |
</script> | |
</html> | |
<!-- vim: set ts=2 sw=2 et: --> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2 | |
import sys | |
import requests | |
import json | |
import argparse | |
import geojson | |
import subprocess | |
YOUR_API_KEY = 'xxxx' | |
parser = argparse.ArgumentParser(description='Query Wigle.net via its API') | |
parser.add_argument('--onlymine', action='store_true', help='only use data I have uploaded') | |
parser.add_argument('--freenet', action='store_true', help='only take into account free APs') | |
parser.add_argument('--paynet', action='store_true', help='only takeinto account paying APs') | |
parser.add_argument('--ssid', help='look for matching SSID') | |
args = parser.parse_args() | |
class AP(object): | |
def __init__(self, mac, ssid, channel, lat, lon, first_time, last_time): | |
self.mac = mac | |
self.ssid = ssid | |
self.channel = channel | |
self.coord = (round(lon, 6), round(lat, 6)) | |
self.first_time = first_time | |
self.last_time = last_time | |
def __str__(self): | |
return 'MAC=%s, SSID=%s, channel=%d, lat=%f, lon=%f' % (self.mac, self.ssid, self.channel, self.coord[1], self.coord[0]) | |
MAX_LOOP = 1 | |
APs = [] | |
headers = {'Accept': 'application/json', 'Authorization': 'Basic %s' % YOUR_API_KEY} | |
url = 'https://api.wigle.net/api/v2/network/search' | |
payload = {'onlymine': args.onlymine, | |
'freenet': args.freenet, | |
'paynet': args.paynet, | |
#'latrange1': 46.27, | |
#'latrange2': 49.24, | |
#'longrange1': -5.0, | |
#'longrange2': 0.00, | |
} | |
if args.ssid: | |
payload['ssid'] = args.ssid | |
r = requests.get(url, params=payload, headers=headers) | |
j = r.json() | |
try: | |
for res in j['results']: | |
ap = AP(res['netid'].lower(), res['ssid'], res['channel'], res['trilat'], res['trilong'], res['firsttime'], res['lasttime']) | |
APs.append(ap) | |
except KeyError: | |
print j | |
sys.exit(-1) | |
# loop until there is no more result but stop at MAX_LOOP | |
count = 0 | |
try: | |
payload['searchAfter'] = j['search_after'] | |
except KeyError: | |
print j | |
sys.exit(-1) | |
while payload['searchAfter'] != None: | |
r = requests.get(url, params=payload, headers=headers) | |
j = r.json() | |
payload['searchAfter'] = j['search_after'] | |
for res in j['results']: | |
ap = AP(res['netid'].lower(), res['ssid'], res['channel'], res['trilat'], res['trilong'], res['firsttime'], res['lasttime']) | |
APs.append(ap) | |
count += 1 | |
if count > MAX_LOOP: | |
break | |
print ':: found %d result(s)' % len(APs) | |
if len(APs) == 0: | |
sys.exit(0) | |
# create APs feature collection for geojson | |
tmp = [] | |
for ap in APs: | |
point = geojson.Point(ap.coord) | |
feature = geojson.Feature(geometry=point, | |
properties={'MAC':ap.mac, 'SSID':ap.ssid, 'channel':ap.channel, 'first_time':ap.first_time, | |
'last_time': ap.last_time}) | |
tmp.append(feature) | |
fc = geojson.FeatureCollection(tmp) | |
f = open('search.geojson', 'wb') | |
f.write('var data=%s' % geojson.dumps(fc)) | |
f.close() | |
cmd = 'xdg-open search.html' | |
subprocess.call(cmd.split(' ')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment