random_street_view.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import random
  2. import requests
  3. from .shared import point_has_streetview, GeoPointSource, CachedGeoPointSource, ExhaustedSourceError, GeoPointSourceGroup
  4. RSV_URL = "https://randomstreetview.com/data"
  5. VALID_COUNTRIES = ("ad", "au", "ar", "bd", "be", "bt", "bw",
  6. "br", "bg", "kh", "ca", "cl", "hr", "co",
  7. "cz", "dk", "ae", "ee", "fi", "fr", "de",
  8. "gr", "hu", "hk", "is", "id", "ie", "it",
  9. "il", "jp", "lv", "lt", "my", "mx", "nl",
  10. "nz", "no", "pe", "pl", "pt", "ro", "ru",
  11. "sg", "sk", "si", "za", "kr", "es", "sz",
  12. "se", "ch", "tw", "th", "ua", "gb", "us")
  13. def call_random_street_view(country_lock):
  14. """
  15. Returns an array of (some number of) tuples, each being (latitude, longitude).
  16. All points will be valid streetview coordinates. There is no guarantee as to the
  17. length of this array (it may be empty), but it will never be None.
  18. This function calls the streetview metadata endpoint - there is no quota consumed.
  19. """
  20. try:
  21. rsv_js = requests.post(RSV_URL, data={"country": country_lock.lower()}).json()
  22. except:
  23. return []
  24. if not rsv_js["success"]:
  25. return []
  26. return [
  27. (country_lock, point["lat"], point["lng"])
  28. for point in rsv_js["locations"]
  29. if point_has_streetview(point["lat"], point["lng"])
  30. ]
  31. class RSVCountryPointSource(GeoPointSource):
  32. def __init__(self, country_lock, max_attempts=100):
  33. self.country_lock = country_lock
  34. self.max_attempts = max_attempts
  35. def get_name(self):
  36. return f"RSV-{self.country_lock}"
  37. def get_points(self, n):
  38. attempts = 0
  39. points = []
  40. while len(points) < n:
  41. if attempts > self.max_attempts:
  42. raise ExhaustedSourceError(points)
  43. points.extend(call_random_street_view(country_lock=self.country_lock))
  44. attempts += 1
  45. return points
  46. COUNTRY_SOURCES = { k: CachedGeoPointSource(RSVCountryPointSource(k), 10) for k in VALID_COUNTRIES }
  47. class RSVWorldPointSource(GeoPointSource):
  48. def __init__(self, max_attempts=10):
  49. self.max_attempts = max_attempts
  50. def get_name(self):
  51. return "RSV-global"
  52. def get_points(self, n):
  53. attempts = 0
  54. points = []
  55. while len(points) < n:
  56. if attempts > self.max_attempts:
  57. raise ExhaustedSourceError(points)
  58. points.extend(COUNTRY_SOURCES[random.choice(VALID_COUNTRIES)].get_points(1))
  59. attempts += 1
  60. return points
  61. WORLD_SOURCE = RSVWorldPointSource()
  62. SOURCE_GROUP = GeoPointSourceGroup(COUNTRY_SOURCES, WORLD_SOURCE)