Hi! Attached is a pretty simple Python script to compute some statistics about relays. Here's the doc: Usage: tor-relays-stats.py <output> [args ...] Where <output> is one of: - countries [FLAGS] relative percentage of the consensus in each countries - as-sets [FLAGS] [COUNTRIES] relative percentage of the consensus in each AS sets - top [COUNT] [FLAGS] [COUNTRIES] top relays according their place in the whole consensus Examples: - To get the top five exit nodes in France: tor-relays-stats.py top 5 Exit fr - To get weights of each AS of all relays in Germany: tor-relays-stats.py as-sets Running de Maybe it has flaws. Maybe it should land in some Git repository. I just felt it might be of interest to other folks. Feel free to comment and hack. -- delber
#!/usr/bin/env python # # tor-relay-stats.py: extract some statistics about relays # # This script expect to have a file called 'details.json' in the # current directory. In order to retrieve the needed data, one # can issue the following command: # # curl -o details.json https://onionoo.torproject.org/details # # # Author: delber@xxxxxxxxxx # # This program is free software. It comes without any warranty, to # the extent permitted by applicable law. You can redistribute it # and/or modify it under the terms of the Do What The Fuck You Want # To Public License, Version 2, as published by Sam Hocevar. See # http://sam.zoy.org/wtfpl/COPYING for more details. import json import operator import sys class RelayStats(object): def __init__(self): self._data = None @property def data(self): if not self._data: self._data = json.load(file('details.json')) return self._data def get_total_consensus_weight(self, relays=None): if relays is None: relays = self.get_relays() total_consensus_weight = 0 for relay in relays: total_consensus_weight += relay['consensus_weight'] return total_consensus_weight def get_relays(self, flags=[], countries=''): relays = [] for relay in self.data['relays']: if not relay['running']: continue if set(flags) & set(relay['flags']) != set(flags): continue if countries and not relay.get('country', '') in countries: continue relays.append(relay) return relays def output_countries(self, flags=''): flags = flags.split() relays = self.get_relays(flags) countries = {} for relay in relays: country = relay.get('country', None) if country not in countries: countries[country] = 0 countries[country] += relay['consensus_weight'] total_consensus_weight = self.get_total_consensus_weight(relays) for country, weight in sorted(countries.iteritems(), key=operator.itemgetter(1)): print "%3.2f%% %s" % (weight * 100.0 / total_consensus_weight, country) def output_as_sets(self, flags='', countries=''): flags = flags.split() relays = self.get_relays(flags, countries) as_sets = {} for relay in relays: as_set = relay.get('as_name', 'Unknown') if as_set not in as_sets: as_sets[as_set] = 0 as_sets[as_set] += relay['consensus_weight'] total_consensus_weight = self.get_total_consensus_weight(relays) for as_set, weight in sorted(as_sets.iteritems(), key=operator.itemgetter(1)): print "%3.4f%% %s" % (weight * 100.0 / total_consensus_weight, as_set) def output_top(self, count='10', flags='', countries=''): count = int(count) flags = flags.split() relays = self.get_relays(flags, countries) top = sorted(relays, key=operator.itemgetter('consensus_weight')) total_consensus_weight = self.get_total_consensus_weight() for relay in top[-count:]: print "%3.4f%% %-20s %s" % (relay['consensus_weight'] * 100.0 / total_consensus_weight, relay['nickname'], relay['fingerprint']) OUTPUTS = { 'countries': 'output_countries', 'as-sets': 'output_as_sets', 'top': 'output_top', } def usage(): print >>sys.stderr, """Usage: %(progname)s <output> [args ...] Where <output> is one of: - countries [FLAGS] relative percentage of the consensus in each countries - as-sets [FLAGS] [COUNTRIES] relative percentage of the consensus in each AS sets - top [COUNT] [FLAGS] [COUNTRIES] top relays according their place in the whole consensus Examples: - To get the top five exit nodes in France: %(progname)s top 5 Exit fr - To get weights of each AS of all relays in Germany: %(progname)s as-sets Running de """ % { 'progname': sys.argv[0] } sys.exit(1) if '__main__' == __name__: if len(sys.argv) == 1: usage() func = OUTPUTS.get(sys.argv[1], None) if not func: usage() stats = RelayStats() getattr(stats, func)(*sys.argv[2:])
Attachment:
pgp1SyzBv5phU.pgp
Description: PGP signature
_______________________________________________ tor-relays mailing list tor-relays@xxxxxxxxxxxxxxxxxxxx https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-relays