Added static option for static server list

This commit is contained in:
Nils Gerke 2020-10-30 09:51:35 +01:00
parent c58ad3367b
commit 67985db684
1 changed files with 108 additions and 98 deletions

View File

@ -17,6 +17,7 @@
import os import os
import re import re
import json
import csv import csv
import sys import sys
import math import math
@ -1224,132 +1225,139 @@ class Speedtest(object):
return self.config return self.config
def get_servers(self, servers=None, exclude=None): def get_servers(self, servers=None, exclude=None, servers_json=None):
"""Retrieve a the list of speedtest.net servers, optionally filtered """Retrieve a the list of speedtest.net servers, optionally filtered
to servers matching those specified in the ``servers`` argument to servers matching those specified in the ``servers`` argument
""" """
if servers is None:
servers = []
if exclude is None: if servers_json is None:
exclude = [] if servers is None:
servers = []
self.servers.clear() if exclude is None:
exclude = []
for server_list in (servers, exclude): self.servers.clear()
for i, s in enumerate(server_list):
for server_list in (servers, exclude):
for i, s in enumerate(server_list):
try:
server_list[i] = int(s)
except ValueError:
raise InvalidServerIDType(
'%s is an invalid server type, must be int' % s
)
urls = [
'://www.speedtest.net/speedtest-servers-static.php',
'http://c.speedtest.net/speedtest-servers-static.php',
'://www.speedtest.net/speedtest-servers.php',
'http://c.speedtest.net/speedtest-servers.php',
]
headers = {}
if gzip:
headers['Accept-Encoding'] = 'gzip'
errors = []
for url in urls:
try: try:
server_list[i] = int(s) request = build_request(
except ValueError: '%s?threads=%s' % (url,
raise InvalidServerIDType( self.config['threads']['download']),
'%s is an invalid server type, must be int' % s headers=headers,
secure=self._secure
) )
uh, e = catch_request(request, opener=self._opener)
if e:
errors.append('%s' % e)
raise ServersRetrievalError()
urls = [ stream = get_response_stream(uh)
'://www.speedtest.net/speedtest-servers-static.php',
'http://c.speedtest.net/speedtest-servers-static.php',
'://www.speedtest.net/speedtest-servers.php',
'http://c.speedtest.net/speedtest-servers.php',
]
headers = {} serversxml_list = []
if gzip: while 1:
headers['Accept-Encoding'] = 'gzip' try:
serversxml_list.append(stream.read(1024))
except (OSError, EOFError):
raise ServersRetrievalError(get_exception())
if len(serversxml_list[-1]) == 0:
break
errors = [] stream.close()
for url in urls: uh.close()
try:
request = build_request(
'%s?threads=%s' % (url,
self.config['threads']['download']),
headers=headers,
secure=self._secure
)
uh, e = catch_request(request, opener=self._opener)
if e:
errors.append('%s' % e)
raise ServersRetrievalError()
stream = get_response_stream(uh) if int(uh.code) != 200:
raise ServersRetrievalError()
serversxml_list = [] serversxml = ''.encode().join(serversxml_list)
while 1:
try:
serversxml_list.append(stream.read(1024))
except (OSError, EOFError):
raise ServersRetrievalError(get_exception())
if len(serversxml_list[-1]) == 0:
break
stream.close() printer('Servers XML:\n%s' % serversxml, debug=True)
uh.close()
if int(uh.code) != 200:
raise ServersRetrievalError()
serversxml = ''.encode().join(serversxml_list)
printer('Servers XML:\n%s' % serversxml, debug=True)
try:
try: try:
try: try:
root = ET.fromstring(serversxml) try:
except ET.ParseError: root = ET.fromstring(serversxml)
e = get_exception() except ET.ParseError:
raise SpeedtestServersError( e = get_exception()
'Malformed speedtest.net server list: %s' % e raise SpeedtestServersError(
) 'Malformed speedtest.net server list: %s' % e
elements = etree_iter(root, 'server') )
except AttributeError: elements = etree_iter(root, 'server')
except AttributeError:
try:
root = DOM.parseString(serversxml)
except ExpatError:
e = get_exception()
raise SpeedtestServersError(
'Malformed speedtest.net server list: %s' % e
)
elements = root.getElementsByTagName('server')
except (SyntaxError, xml.parsers.expat.ExpatError):
raise ServersRetrievalError()
for server in elements:
try: try:
root = DOM.parseString(serversxml) attrib = server.attrib
except ExpatError: except AttributeError:
e = get_exception() attrib = dict(list(server.attributes.items()))
raise SpeedtestServersError(
'Malformed speedtest.net server list: %s' % e
)
elements = root.getElementsByTagName('server')
except (SyntaxError, xml.parsers.expat.ExpatError):
raise ServersRetrievalError()
for server in elements: if servers and int(attrib.get('id')) not in servers:
try: continue
attrib = server.attrib
except AttributeError:
attrib = dict(list(server.attributes.items()))
if servers and int(attrib.get('id')) not in servers: if (int(attrib.get('id')) in self.config['ignore_servers']
continue or int(attrib.get('id')) in exclude):
continue
if (int(attrib.get('id')) in self.config['ignore_servers'] try:
or int(attrib.get('id')) in exclude): d = distance(self.lat_lon,
continue (float(attrib.get('lat')),
float(attrib.get('lon'))))
except Exception:
continue
try: attrib['d'] = d
d = distance(self.lat_lon,
(float(attrib.get('lat')),
float(attrib.get('lon'))))
except Exception:
continue
attrib['d'] = d try:
self.servers[d].append(attrib)
except KeyError:
self.servers[d] = [attrib]
try: break
self.servers[d].append(attrib)
except KeyError:
self.servers[d] = [attrib]
break except ServersRetrievalError:
continue
except ServersRetrievalError: if (servers or exclude) and not self.servers:
continue raise NoMatchedServers()
else:
if (servers or exclude) and not self.servers: printer('Loading Servers from:\n%s' % servers_json, debug=True)
raise NoMatchedServers() with open(servers_json) as json_file:
self.servers = json.load(json_file)
return self.servers return self.servers
def set_mini_server(self, server): def set_mini_server(self, server):
"""Instead of querying for a list of servers, set a link to a """Instead of querying for a list of servers, set a link to a
speedtest mini server speedtest mini server
@ -1744,6 +1752,8 @@ def parse_args():
help='Suppress verbose output, only show basic ' help='Suppress verbose output, only show basic '
'information in JSON format. Speeds listed in ' 'information in JSON format. Speeds listed in '
'bit/s and not affected by --bytes') 'bit/s and not affected by --bytes')
parser.add_argument('--load-servers-from-json', dest='servers_json', type=PARSER_TYPE_STR,
help='Serverlist for static testing in json Format')
parser.add_argument('--list', action='store_true', parser.add_argument('--list', action='store_true',
help='Display a list of speedtest.net servers ' help='Display a list of speedtest.net servers '
'sorted by distance') 'sorted by distance')
@ -1903,7 +1913,7 @@ def shell():
if not args.mini: if not args.mini:
printer('Retrieving speedtest.net server list...', quiet) printer('Retrieving speedtest.net server list...', quiet)
try: try:
speedtest.get_servers(servers=args.server, exclude=args.exclude) speedtest.get_servers(servers=args.server, exclude=args.exclude, servers_json=args.servers_json)
except NoMatchedServers: except NoMatchedServers:
raise SpeedtestCLIError( raise SpeedtestCLIError(
'No matched servers: %s' % 'No matched servers: %s' %