Skip to content

Instantly share code, notes, and snippets.

@solsticedhiver
Created April 5, 2018 13:48
Show Gist options
  • Save solsticedhiver/d0e5696941607cfdf704ac3a92f53b82 to your computer and use it in GitHub Desktop.
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
<!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/leaflet@1.2.0/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/leaflet@1.2.0/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: -->
#!/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